Why does Angular send Http Request Method: Options before POST? - angularjs

I'm using Angular Dart V1 for a front end framework
I am using shelf && shelf router for a backend API
I'm trying to migrate some old get requests to accept Post Data
Old request:
Future fetchRoutes(FlightPostParamsVO params) async {
return _http.get(BASE + 'routes').then(handleRoutes);
}
New Request
Future fetchRoutes(FlightPostParamsVO params) async {
Map post = params.toPostable();
return _http.post(BASE + 'routes', post ).then(handleRoutes);
}
I'm setting the CORS headers in a generic response for all calls as its strictly a JSON API:
Future<Response> makeResponse( json ) async {
var response = new Response.ok( json, headers: {'content-type': 'text/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': "Origin, X-Requested-With, Content-Type, Accept",
'Access-Control-Allow-Methods': "POST, GET, OPTIONS"} );
return response;
}
I get a 404 an the following output:
OPTIONS http://localhost:1234/tickets/routes 404 (Not Found)
(index):1 XMLHttpRequest cannot load http://localhost:1234/tickets/routes. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404.
When i inspect the network traffic - all my GET request DO HAVE the correct headers
When i inspect the network traffic - my POST call is lead bya request with a method set as OPTIONS - this call does not have the headers included.
My POST route handler never gets called
Router
Router airRouter = router();
Router tickets = airRouter.child('/tickets');
tickets.add('/cities', ['GET'], controller.handleCitites);
tickets.add('/times', ['GET'], controller.handleTimes);
tickets.add('/routes', ['POST'], controller.handleRoutes);
tickets.add('/{id}/tickets/', ['GET'], controller.handleTickets);
io.serve(airRouter.handler, 'localhost', 1234);
Fix Symptom:
tickets.add('/routes', ['OPTIONS'], controller.handleRoutes);
Question: Why is the HTTP Request sending a Request Method:OPTIONS before each POST, and whats the proper way only call POST?

That is not angular. Its the browser. The first request of method OPTION is to test for CORS header to make sure the browser is allowed to post.
Solution:
http://thomaslockerambling.blogspot.com/2014/10/shelf-middleware-adding-cors-headers.html
Create a CORS Object and append to header
Intercept an Call to OPTIONS
Response with status code 200 OK

Related

I am using react and axios. Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response

axios. post error.
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.
I am using the axios, react and redux.
My code is:
const config = {
method: 'post',
url: addActivityUrl,
data:data,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
};
return function (dispatch) {
axios.request(config)
.then(function(response){
dispatch({type:ADD_ACTIVITY_SUCCESS,payload:response.data});
} )
.catch((error)=> {
dispatch({type:ADD_ACTIVITY_ERROR,payload:error});
})
}
}
I set the breakpoint in the error callback function. When I send a post request,the error above will show me.
I looked for the answer on Stack Overflow. I don't found the answer yet.
I don't know the reason.
Most you have an issue with custom request headers.
When using custom request header you will get a CORS preflight. This type of request use HTTP OPTIONS and includes Access-Control-Request-Headers listing the headers the client wants to include in the request.
Your client code need to reply to CORS preflight with the appropriate CORS headers. That header needs to contain the same values the Access-Control-Request-Headers.

CORS Issue in Web Console (angular js)

I have a developed a web console in angular JS in which I am using post and put methods and making HTTP requests in which I send json and calling a WSO2 REST API to get response accordingly. Its running on server but I am facing CORS problem. I have add add extension in browser and enable it otherwise I get following error.
XMLHttpRequest cannot load http://127.197.200.100:8000/ManagementAPI/createuser. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.197.200.100:8000' is therefore not allowed access.
This is how I am sending request
CreateUser: function(adata) {
var config = {
headers :{
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
var promise = $http.post(213.187.243.177:8283/ManagementAPI/createuser,adata,config).then(function (response) {
return [response.status,response.data];
},function (response) {
console.log("Error Returned" + response.status);
return [response.status,response.data];
});
return promise;
},
I have tried ThisLink for solution but did not work. Need a solution for accessing it without CORS.
Set headers in back end for avoiding CORS issues .
Sample code in php is shown in below
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}

Ionic http post to external url

Im trying to send a post to a url with Ionic using angular, but i have the response:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 404.
I know that the external service is working, because i tested it by ajax and everything works perfectly...
Below the code used in AngularJS (Ionic) and Ajax:
Ionic:
var loginServiceUrl = 'http://url.com.br'; //It is not the real one
var loginServiceData = {
email: email#email.com.br
senha: 1234
};
$http.post(loginServiceUrl, loginServiceData).
then(function (res){
console.log(res);
});
Ajax:
$.ajax({
type: "POST",
url : 'http://url.com.br', //It is not the real one
data : {email: 'email#email.com.br', senha: '1234'},
success: function(result) {
$('html').text(JSON.stringify(result));
}
});
Does anyone know why I get the post via ajax on my localhost and not with the ionic, also localhost?
Check this out. It is well explained how to handle issues like yours --> http://blog.ionic.io/handling-cors-issues-in-ionic/
Try to add headers in your POST request.
//example of DataToSend
var DataToSend = {
userID: deviceID,
coordLat : pos.coords.latitude,
coordLon: pos.coords.longitude
};
$http({
method: 'POST',
url: 'http://url.com.br',
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
data: DataToSend
})
CORS has nothing to do with your frontend.
Before sending the POST request, browser send a OPTIONS request to the server to check if call from your domain is allowed or not.
Since, you are getting Status 404, that means your server is not handling the OPTIONS request
1. Allow the OPTIONS request (same as POST)
Now come to second part i.e " Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' "
After allowing the OPTIONS request, now set the response header of OPTIONS request (Browser will check the response of OPTIONS request and then process the POST request only if there is 'Access-Control-Allow-Origin' present in the OPTIONS response.
2. Set the response headers of OPTIONS request
response().setHeader("Access-Control-Allow-Origin", "*");
response().setHeader("Allow", "*");
response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent");
Example..
(In Java)
Router:
OPTIONS /*all
controllers.Application.preflight(all)
Controller Function:
public static Result preflight(String all) {
response().setHeader("Access-Control-Allow-Origin", "*");
response().setHeader("Allow", "*");
response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent, Auth-Token");
return ok();
}
Hope this will solve your problem.
Cheers

CORS error with AngularJS post only in FireFox

I am having issues only with FireFox when making a cross origin request in an Ionic app (so it's using AngularJS). The js app is doing a $http.post() to a Laravel 5.1 API, and I get the following error only in FireFox (39.0.3):
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://blah.dev/endpoint. (Reason: missing token 'content-type' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
This is on my localhost (OSX Mavericks). and works fine in Chrome and Safari, only FireFox is given the error. I have cleared the cache, and tried in a "private window", with the same results.
Here is the Laravel route defined to handle the OPTIONS request:
Route::options('endpoint', function() {
return response('OK')
->header('Access-Control-Allow-Headers ', 'Origin, Authorization, X-Requested-With, Content-Type, Accept')
->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
->header('Access-Control-Allow-Origin', '*')
->header('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0')
;
});
Route::post('endpoint', array('uses' => '\Path\To\Controller#endpoint'));
I did find this question that seems to have a similar issue only in FireFox, but the solution was to comma separate the Allow-Methods, which I already am.
The message " missing token 'content-type' " is about the client. For a http request to be a valid post one, it must have a header
'Content-Type': 'application/x-www-form-urlencoded'
or
'Content-Type': 'multipart/form-data'
The first content-type is the most common one.
In angularjs one way to do a CORS post request is
$http.post(
'http://external-domain.ext/the/rest/url',
'param_name=param_value',
{headers:{'Content-Type': 'application/x-www-form-urlencoded'}}
).
then(function successCallback(response) {
$scope.something = response;
}, function errorCallback(response) {
// not good
});
If the server is configured with
header('Access-Control-Allow-Origin', '*'), the CORS post must succeed without authentication and credentials.
on the back end try putting
->header('Access-Control-Allow-Credentials', 'true')
and on the front end try putting
.config(function($locationProvider, $httpProvider) {
// CORS requests with credentials
$httpProvider.defaults.withCredentials = true;
})

AngularJS $http GET method to backend server: Request Method:OPTIONS 405

$http GET request to a clojure backend, to get a list of services.
I get is an OPTIONS request (???), which gets a 405 response...
<code>
var config = {headers: {
'Authorization': 'Bearer d2VudHdvYW5nZV9tZQ',
"X-Testing" : "testing"
}
};
$http.get(SERVER.MESSAGE_SERVICES, config)
.success(function(successCallback) {
$scope.services = successCallback;
})
.error(function(errorCallback) {
console.log(errorCallback.toString);
}).
finally(function() {
console.log("Message services rest call");
});
</code>
**clojure backend**:
<code>
headers {"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Headers" "X-Requested-With, Origin,Content-Type, Accept"
"Access-Control-Allow-Methods" "GET, POST, OPTIONS"}
</code>
There is no problem that AngularJS sends an OPTIONS request, that is because CORS standards force to do so. Be sure that the server is configured to allow a GET method.
Yes as raso suggested this problem is because of Cross Origin Resource Sharing(CORS). The same old privacy policy prevents JS/ angularJS from making requests across domain boundaries.
Configure server to allow cross domain requests.
Or
If you are using Chrome than you can use this extension to surpass this problem.

Resources