react native application returns 404 error - laravel

I am creating app in react native with laravel backend.So as I want to get api from laravel server so i run laravel with that command
php artisan serve --host=some-domain.test --port=anyPort
I create api like that way
Route::get('users','PostController#get_users');
function get_users()
{
return Response()->json(User::get(),200);
}
In react native I call that api in that way
constructor()
{
super();
this.state={
data :[]
}
}
componentDidMount()
{
this.callApi();
}
async callApi()
{
let data=await fetch(' http://192.168.1.1:8081/api/users') //same as where laravel server is running
let adata= await data.text();
this.setState({data:adata})
console.warn(data)
}
It returns me 404 error:development server returned response error code:404
but when i stop laravel server and refresh my app then start laravel server it return me that error
Possible unhandled promise rejection(id:0):
what should I do now ?

You are not handling your Promise right hence you get the Error. The way that Fetch should be used is something like this:
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
You can read more about it on the official Docs:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
If you want to set the State you would have to do it in the second .then() Call.
Also remeber to add a .catch(err => console.log(err)) to filter your errors.

I think you need to handle cors request
You can install this package
https://github.com/fruitcake/laravel-cors
To generate config file run following command
php artisan vendor:publish --tag="cors"
and then update in config/cors.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
To allow CORS for all your routes, add the HandleCors middleware at the top of the $middleware property of app/Http/Kernel.php class:
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
// ...
];

Related

Laravel Inertia apps doesn't support subdomain redirects - No 'Access-Control-Allow-Origin'

I'm working on a Laravel 9, InertiaJS and vue project where a user can submit a new product through products/create route and this sends to ProductController#store which does all what it's supposed to do and then supposedly redirect the user to the newly created product on a subdomain route like this http://username.example.test/my-new-product
The issue I'm having is that I keep getting the below error and the redirect doesn't work:
Access to XMLHttpRequest at 'http://user.example.test/my-first-product' (redirected from 'http://example.test/products/create') from origin 'http://example.test' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The code works as follows:
1- The form:
const form = useForm("createProduct", {
webshop_id: null,
title: null,
price: null,
type: null,
currency: null,
description: null,
thumbnail: null,
});
const submit = () => {
form.post(route("products.create"), {
onSuccess: () => form.reset(),
});
};
2- Products create router:
Route::middleware([
'auth:sanctum',
config('jetstream.auth_session'),
'verified',
])->group(function () {
Route::post('products/create', [ProductController::class, 'store'])->name('products.create');
});
3- The controller - Storing the new product with user details and redirecting (which doesn't work) to show the product
public function store(StoreProductRequest $request)
{
// Code
return redirect()->route('products.show', [$user, $product]);
}
4- The show route and controller#show
Route::domain('{user:username}.' . env('APP_URL'))->group(function () {
Route::get('{product:slug}', [ProductController::class, 'show'])->name('products.show');
});
public function show(User $user, Product $product)
{
return Inertia::render('Products/Show', [
'user' => $user,
'product' => $product,
'thumbnails' => $product->productimages
]);
}
I saw #reinink explain in this Issue that we can use now Inertia::location
The only way I could get this to work is returning this is the ProductController#store:
return Inertia::location('http://' . $user->username . '.example.test/' . $validated['slug']);
But It causes a full page refresh which defeats the whole concept of having a single page application and I will have to remember changing 'http' to 'https' and domain to the real domain when I'm going to put the app in production. I was hoping that I was doing something wrong but after hours of searching for a solution I began to think that Laravel Inertia apps doesn't support subdomain redirects
I found a solution that solved for me the CORS errors from this Stackoverflow answer
Making those changes to cors.php solved that for me:
'paths' => ['api/*', '*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => ['x-inertia'],
'max_age' => 0,
'supports_credentials' => false,
but I'm facing an issue where it redirects me to a url that ignores the subdomain completely. Find the new issue here please

CORS in Laravel when using fetch to download a file on storage on localhost

Sorry if it looks like I again ask for CORS-configuration in Laravel. But my scenario is alittle bit different and I couldn't find anything helpful yet.
I'm serving my Laravel-Application via php artisan serve --port 80
CORS is configured like this in config/cors.php:
return [
'paths' => ["*"],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
And enabled in middleware in Kernel.php:
protected $middleware = [
// ...
\Fruitcake\Cors\HandleCors::class,
// ...
];
In my frontend (localhost:8080) I do a simple
const content = await fetch("http://localhost/storage/plans/46718040-5c72-4999-865f-5174a7c59313.png")
but I'm getting the following error:
Access to fetch at 'http://localhost/storage/plans/46718040-5c72-4999-865f-5174a7c59313.png'
from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Do I have to setup Nginx locally to configure cors for the storage? Or are there any other ideas?
Do I have to setup Nginx locally to configure cors for the storage?
Yes. Your request isn't invoking Laravel at all, the file is being served statically.
Do you need to use fetch to get the content, or can you just set an image source to the file path instead?

Laravel Sanctum Vue SPA CORS issue

I've setup a VUE frontend which connects and authenticates perfectly well with a Laravel backend, using sanctum. I'm able to login and successfully retrieve the logged in user by visiting /api/user. I believe I've followed all the config steps stated in the documentation.
Here is sanctum.php config for stateful domains:
'stateful' => explode(
',',
env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,localhost:8080,127.0.0.1,127.0.0.1:8080,::1'
)
), //this is what is in my env SANCTUM_STATEFUL_DOMAINS=app.foo-bar.test:8080
//my laravel backend is running on foo-bar.test
Here is my session.php config:
'domain' => env('SESSION_DOMAIN', null), //in my .env I have: SESSION_DOMAIN=.foo-bar.test
I have the sanctum middleware setup in http/kernel.php, and I'm using auth:sanctum in my routes
Here is my cors.php config:
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
and in my vue frontend, I've configured axios to use the following
axios.defaults.baseURL = 'http://foo-bar.test';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.withCredentials = true;
As I mentioned, I'm able to successfully login, and even visit /api/user. All works fine,
But when I make a post request to: api/users/multiple,
I get the CORS error: Access to XMLHttpRequest at 'http://foo-bar.test/api/users/multiple' from origin 'http://app.foo-bar.test:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I'm out of ideas, as it seems I've done all the necessary config. Perhaps I'm missing something ? Any help is appreciated.
Kind regards
Add a middleware
php artisan make:middleware Cors
In app/Http/kernel.php paste this in $middleware
protected $middleware = [
\App\Http\Middleware\Cors::class,
....
];
In Middleware/Cors.php now add
public function handle(Request $request, Closure $next)
{
return $next($request)->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods','GET, POST, PUT, PATCH, DELETE,
OPTIONS')
->header('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-
Type, Accept, Authorization');
}
What I came to realise was that this was not actually a CORS issue. If it was a CORS issue, I would not have been able to login, or visit the API that returns the currently logged in user.
What actually happens is that, chrome sometimes fails to report 500 errors on the API and rather returns CORS errors. When I tried making the API call on Firefox, I was able to actually see the 500 error.
Once I resolved the 500 error, the CORS error also stopped appearing in chrome.
What I've seen from this is that the network request error reporting on Firefox is more reliable than that on chrome

Laravel 7 cors problem for nuxt with grouped prefix

New to nuxt and laravel 7 Route::group
Update opened an issue here:
https://github.com/fruitcake/laravel-cors/issues/487
My laravel and cors package versions:
- "fruitcake/laravel-cors": "^2.0",
- "laravel/framework": "^7.24",
My Api Routes
Route::group(['prefix' => 'auth', 'namespace' => 'Auth'], function () {
Route::post('signin', 'SignInController');
Route::get('me', 'MeController');
Route::post('signout', 'SignOutController');
});
Route::group(['prefix' => 'snippets', 'namespace' => 'Snippets'], function () {
Route::post('', 'SnippetController#store');
Route::get('{snippet:uuid}', 'SnippetController#show');
});
The auth route works but the snippet one doesn't work.
My cors is like this:
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*', 'api/snippets', '*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000'],
'allowed_origins_patterns' => ['*'],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
I also tried this
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => ['*'],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
Before every retry, I used the php artisan config:cache command.
Cors error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/snippets. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
This request http://localhost:8000/api/snippets/ works fine in postman but not in nuxt, I get the cors error.
Can someone tell me what is happening here?
Thanks
Using dd or any log function in laravel will affect the cors.
Here is a quote from the official site https://github.com/fruitcake/laravel-cors#echodie
Echo/die
If you echo(), dd(), die(), exit(), dump() etc in your code, you will break the Middleware flow. When an output is sent before headers, CORS cannot be added. When the scripts exits before the CORS middleware finished, CORS headers will not be added. Always return a proper response or throw an Exception.
This code will make it work:
public function store(Request $request)
{
$snippet = $request->user()->snippets()->create();
return fractal()
->item($snippet)
->transformWith(new SnippetTransformer)
->toArray();
}

Axios getting blocked by laravel 7 cors. No "access-control-allow-origin-header"

I've a backend app working with Laravel 7 and a frontend which works with VueJs. My Laravel app is running on laradock (nginx, postgres etc...) Using Postman the API (Laravel 7) works properly.
This API replies by dns or by ip. http://192.168.0.3:80/api/mobile or http://laraapi.com/api/mobile
Once I'm still developing the VueJs app I'm running it with "npm run serve" which provides two ways to access my app, first by localhost and the second one by IP address. Both of them running on port 8081.
When Axios consume the API which uses the GET verb, everything works fine. When Axios consumes a POST verb than a get error.
Access to XMLHttpRequest at 'http://larapi.com/api/mobile/startorder/' from origin 'http://192.168.0.3:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
By default laravel 7 already have a pre-done configuration for CORS which is provided by "Fruitcake"
So my kernel.php is like that:
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
Fruitcake was moved in to be the first one, the tip from another StackOverflow which didn't help anyway.
My cors configuration:
'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => false,
'max_age' => false,
'supports_credentials' => true,
See that supports_credentials and allowed_origins were changed. Anyway, changing allowed_origins to "*" does not work.
I've created another route file named "mobile" and I'm using this one instead of "api.php", the content is:
Route::group(['middleware' => 'auth:api'], function(){
Route::namespace('Mobile')->group(function () {
Route::post('startorder',
['as' => 'startorder', 'uses' => 'PRC\PurchaseController#startOrder']);
});
});
This new file was created because the idea is use api.php for another purpose.
I've tried already to set a proxy on VueJs side but unfortunately, the result was the same one.
Axios call
import { http } from "./config";
startOrder: (order, user, token) => {
var data = {
"order": order,
"user": user,
}
return http.post("startorder/",data, {
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
withCredentials: true,
});
}
my config.js
import axios from "axios";
export const http = axios.create({
baseURL: "http://192.168.0.3:80/api/mobile/",
withCredentials: true
});
vue.config.js
module.exports = {
devServer: {
proxy: "http://192.168.0.3:80/api/mobile/",
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8081,
https: false,
hotOnly: false,
},
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = 'LaraAPi'
return args
})
}
}
For sure something is missing but actually I don't know which side is wrong anymore after a lot of tries.
I would appreciate it a lot if someone would help with that issue.
if you use axios withCredentials = true you need to enable laravel cros.php file supports_credentials = true
for axios code example:
axios.get('/user?ID=12345', { withCredentials: true })
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
for cros.php code example
[
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true
]
I don't know about this '*' stuff. Remember, this is very bad practice in production!
Access to XMLHttpRequest at 'http://larapi.com/api/mobile/startorder/'
from origin 'http://192.168.0.3:8081' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Try to put the failed origin inside cors.php:
'paths' => ['api/*'],
'allowed_origins' => ['http://192.168.0.3:8081', 'http://192.168.0.3:80', 'http://laraapi.com'],
All three origins above are allowed to make requests to this endpoint.
It's always recommended to create an environment variable to better control this type of configurations. If you make it work in development, it will automatically work in production too!
'paths' => ['api/*'],
'allowed_origins' => env('CORS_ALLOWED_ORIGINS'),
.env
CORS_ALLOWED_ORIGINS=http://192.168.0.3:8081,http://192.168.0.3:80,http://laraapi.com
Update your production .env file accordingly.
cors.php I strongly suggest you change paths
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => false,
'max_age' => false,
'supports_credentials' => false,
];
Kernel.php
<?php
namespace App\Http;
use App\Http\Middleware\cors;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}
mobile.php (similar to api.php)
<?php
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length');
header('Access-Control-Allow-Origin: http://192.168.0.4:8081');
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('login', 'Mobile\Login\UserController#login');
Route::post('register', 'Mobile\Login\UserController#register');
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
VueJs Side
//const configureAPI = require('./src/server/configure')
module.exports = {
devServer: {
proxy: "http://192.168.0.4:80/api/mobile/",
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8081, // CHANGE YOUR PORT HERE!
https: false,
hotOnly: false,
}
}
config.js
import axios from "axios";
export const http = axios.create({
baseURL: "http://192.168.0.4:80/api/mobile/",
withCredentials: false
});
service.js (consumes the API)
start: (parameter, token) => {
var data = {
parameter: parameter,
user: user,
};
return http.post("start/", data, {
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
withCredentials: false,
});
},
#Keith Gulbro I hope this helps you to fix that nightmare. Let me know if you need something else.
Folks, seems the issue has been solved at least for now.
I will keep looking for a better solution.
Below, the details how this was solved.
1- remove the \Fruitcake\Cors\HandleCors::class from protected middleware on kernel.php
2 - On the header of api routes file you must set those lines below:
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length');
header('Access-Control-Allow-Origin: http://192.168.0.3:8081');
In my case, I removed the wildcard * and put my valid origin. The wildcard is insecure.
3 - I've changed my Axios post method to send withCredentials as false.
export default {
login: data => {
return http.post("login",data, {
headers: {
"Content-Type": "application/json",
},
withCredentials: false,
});
},
4 - Config and cache were cleared.
php artisan config:clear
php artisan cache:clear
Now the response header is fulfilled correctly and the Access-Control-Allow-Origin' error disappeared.
Anyway, might have a better solution using FruitCake, otherwise would make no sense at all to provide an inefficient package.
If someone has a better solution, please share it!
Thank's

Resources