API Server always responds "No" Access-Control-Allow-Origin "
I am writing back end with laravel. And try calling api from IONIC use @angular/http
.
In the back-end serer, I already add Access-Control-Allow-Origin
in middleware and answer.
Middleware.
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
->header('Access-Control-Allow-Credentials', true)
->header('Access-Control-Allow-Headers', 'Content-Type')
->header('Vary', 'Origin');
Answer.
return response($data, 200)
->withHeaders([
'Content-Type' => 'application/json',
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => 'Content-Type',
'Vary' => 'Origin',
]);
ION
url: any = 'http://myurl.local/api/';
headers = new Headers(
{
'Accept' : 'application/json',
'Content-Type' : 'application/json',
'Access-Control-Request-Methods' : 'POST'
});
options = new RequestOptions({ headers: this.headers });
login(username, password) {
let data = JSON.stringify({
username : username,
password : password
});
let fullUrl = this.url+'login';
return new Promise((resolve, reject) => {
this.http.post(fullUrl, data, this.options)
.toPromise()
.then((response) =>
{
console.log('API Response : ', response);
resolve(response.json());
})
.catch((error) =>
{
console.error('API Error : ', error.toString());
reject(error.json());
});
});
}
When I call the api with 'Content-Type' : 'application/json'
, it is always responsible for the error.
XMLHttpRequest cannot load http: //myurl.local/api/login . Preflight Request Response Fails Access Control Check: None The Access-Control-Allow-Origin header is present on the requested resource. Origin ' http: // localhost: 8100 ' is therefore not allowed access.
But if I change 'Content-Type'
to 'application/x-www-form-urlencoded'
. I didn't have any errors.
But when I try to see the entrance $request->all()
. Received data - '{"username":"XXXXXXXXXX","password":"XXXXXXXXXX"}' => NULL
.
The postman is all right. I am really trying a lot to solve this problem, but I cannot.
What's wrong?
source to share
Yeahhhh !!! Finally I can work it out. God damn it.
In middleware.
public function handle($request, Closure $next)
{
if ($request->getMethod() == "OPTIONS") {
return response(['OK'], 200)
->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => 'Authorization, Content-Type',
]);
}
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
->header('Access-Control-Allow-Credentials', true)
->header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
}
The header changes IONIC to.
headers = new Headers(
{
'Content-Type' : 'application/json'
});
And it won't work until you add a route options
. (In my case, because I am not using Route::resource
)
Route::group(['middleware' => 'AddHeader'], function()
{
Route::post('/login', 'LoginController@index');
Route::options('/login', 'LoginController@index');
});
PS. I have some logic in function index()
I am trying to use __construct()
. But it doesn't work.
source to share
In your Laravel code that handles requests, you need to add handling for requests OPTIONS
:
if ($request->getMethod() == "OPTIONS") {
$headers = [
'Access-Control-Allow-Origin' => '*'
'Access-Control-Allow-Methods'=> 'POST, GET',
'Access-Control-Allow-Headers'=> 'Content-Type'
];
return Response::make('OK', 200, $headers);
}
When I call the api with
'Content-Type' : 'application/json'
, it is always responsible for the error.But if I change
'Content-Type'
to'application/x-www-form-urlencoded'
. I didn't have any errors.
application/json
content type triggers browsers to perform CORS previews OPTIONS
.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests has more details.
The postman is fine.
Postman is free to send cross-origin requests without limitation. But browsers will not allow your external JavaScript code to access the response from a cross-origin request, unless the response indicates that the server to which the request is sent is the choice to accept cross-origin requests.
And if your request is the one that triggers browsers to request the OPTIONS
CORS preflight request , the server that the request is sent to must be configured to respond correctly to the request OPTIONS
. This is why you need to add additional processing to your Laravel code for requests OPTIONS
.
If the server does not respond to the preview OPTIONS
correctly, the browser will stop there and never be able to fulfill the request POST
you are actually trying to send.
source to share