I am trying to make a post request from AngularJS to WebAPI on a different domain.
$http({
method: 'POST',
url: 'http://www.test.com/api/app/controller',
data: postdata,
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response) {
// Do stuff
}, function() {
// Show error
})
.finally(function() {
// Cancel loading indicator
});
I believe Web API is setup correctly to handle CORS requests. If I make a CORS OPTIONS request using Chrome Advanced REST client, the correct headers and a 200 response code are returned.
When I make the POST call above, a preflight OPTIONS request is made. This always times out with a 504 code. The logging in my Application_BeginRequest is never hit (which it is when calling from Chrome plugin).
What is the difference between calling from AngularJS and the Chrome plugin? Both are being run from the same machine and AngularJS is running in an application on localhost. The same headers are being set in both calls.
This was a stupid mistake on my behalf. I am answering the question (rather than deleting) in case somebody does the same.
I was pointing to a service containing a typo:
url: 'http://www.test2.com/api/app/controller',
Instead of:
url: 'http://www.test.com/api/app/controller',
My CORS pre-flight request was working without an issue, it was just never getting to the right server.
Related
Maximum time my rest api fails and some times it works in chrome but it always works in firefox.
when calling api old data is coming in response.
Cors is also enabled with proper rule.
As per my observation it started happening after recent chrome update on 2nd sept,2017.
Technology used :- Java,Angularjs
Below is the error I get when api fails :-
XMLHttpRequest cannot load . Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin is therefore not allowed access. The response had HTTP status code 403.
Get Api code :-
executeGet: function () {
var deferred = $q.defer();
$http({
url: REST_API.SERVICE_BASE_URL + encodeURI(this.restURI),
method: 'GET',
timeout: 2000,
cache: false,
headers: {'Content-Type': 'application/json'},
withCredentials: true,
}).then(function (response) {
deferred.resolve(response.data, response.status, response.headers, response.config);
$log.debug( 'URL - '+ url_called, response.data, response.status);
},function (response) {
deferred.reject(response.data, response.status, response.headers, response.config);
$log.debug( 'URL - '+ url_called, response.data, response.status);
});
return deferred.promise;
},
Thanks in advance.
Sadly it's impossible to help you from this description. It's nothing to do with being a REST API, and it seems likely that the Chrome vs Firefox thing is just a coincidence.
To find out the cause of this missing Access-Control-Allow-Origin you need to debug your application like you would anything else. This can be done in a few ways.
You can enable New Relic or Data Dog to try to catch errors and other debugging information in an intelligent form, you can use Papertrail, Logentries, etc to see a trail of logs, you can use Rollbar to see just exceptions being fired if that's a bit cheaper than New Relic.
It's very likely that some error is being triggered (validation, auth, something) which is making your application return early, and it's not triggering whatever layer handles CORS. I can't take any guesses at what that might be because you've just put "Java" and we dunno if its Spring, something else or custom.
Best of luck with your debugging!
I faced the same issue, where it was working via Chrome but not when accessing through AngularJS. I was using Spring boot on server side. The solution in my case was to enable Allowing CORS on the server side. In Spring you can enable using WebMvcConfigurer. WebMvcConfigurer enabling CORS
Install in Chrome the extension https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
and enable the cros origin resources
I am trying to do an http post to get a token back. When I do it with Postman, it works and I get a success with a token. When I do it through angularjs, I get a 200 response, but the json returned is telling me my credentials are wrong - the same credentials that work in Postman. Im wondering if there is something in the Angular post call that is causing the data field to be not understood on the other end? Here is the code I am using for the post:
$http({
method: 'POST',
url: syncURL,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: { clientId:'anid', clientSecret:'asecret'}
})
.then(function(resp){
alert("succes!");
});
The response I get back is: {"error":"Invalid Client Id or Client Secret","success":false}.
However, when doing it through postman, it works - see the screen shots with response and settings:
Any ideas on what could be going on or any settings I might be missing that makes postman different from the AngularJS http post call?
I'm actually trying to implement a file upload system between my client side angularjs app and my server but i'm having difficulties to implement this feature.
The problem seems to come from the preflight OPTIONS request sent from Chrome.
When I test my route with postman everything work just fine.
Here is a few screen shots of the postman request execution:
First part of postman example
Second part of postman example
As you can see the route has two parameters a library id and a file to be uploaded and an authentification token.
The problems appear when I try to implement an upload feature in my angular web app.Indeed when I call my $http post request a OPTIONS preflight request is sent to my server.This OPTIONS request doesn't seem to have any of the parameters given to the post request it precedes making my authentification middleware (that has the function of validating the user/token) on my server side respond with a 401 error.
More exactly:
XMLHttpRequest cannot load ..... Response for preflight has invalid http status code 401
It seems that those preflight request are made by the browser when say detect a cross origin resource sharing. This is were I hit a brick wall. I cannot seem to understand how to:
- either send the token with the options request to validate this request
- or to bypass this options request to directly send my post request.
my upload function looks like this:
$http({
method: 'POST',
url: 'my-upload-url',
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
library: my-library-id,
file: my-file-to-upload,
token: user-authentification-token
},
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return formData;
}
})
.success(function (data) {
})
.error(function (data, status) {
});
My questions are:
Is there a way to actually send my user token in the OPTIONS request to make it valid server side?
Is there a way of formatting my post request (header/data/params) to make it bypass this preflight browser request?
Is the formatting of my post request wrong in any way making it trigger the OPTIONS request from Chrome?
Thank you in advance for your help.
Martin
In cors, the OPTIONS method is used to tell the server what will your request do. The server must handle the OPTIONS correctly so your main request will send normally. The browser will send the OPTIONS request automatically when your request is a complex cross origin request.
To bypass the OPTIONS request your request should be POST and GET and content-type must be application/x-www-form-urlencoded, multipart/form-data, or text/plain and the headers only contain Accept, Accept-Language and Content-Language.
Your request is not wrong. The reason is that your request is a cross origin request and it isn't a simple request.
So the best way to solve this problem is to make your server handle the cors request correctly.
For express you can use https://github.com/expressjs/cors
see more: cors-mdn cors-w3c
I am developing a single page application using Angularjs framework.
inside my homeController i use a service call as below
$http({
method: 'POST',
url: 'http://localhost:1530/api/Profile?username=sa&password=da',
data: { Email: "dmytest#test.com", Password: "saas" },
headers: {'Content-Type': 'application/json'}
}).success();
The problem is that when i am making a api call the browser initiates a preflight request with method options instead of post.
Server responds with all required headers.But the actual call is not done.Preflight request initiates only when using "Content-Type:application/json".
I am posting Json data to server.
Is there any way to either prevent the preflight request nor making a successfull api call?
It is working fine on mobile as well as on ajax call.
Thanks in advance.
Depending on you browser, try forceCORS
Chrome: https://chrome.google.com/webstore/detail/forcecors/oajaiobpeddomajelicdlnkeegnepbin?hl=en
Firefox: http://www-jo.se/f.pfleger/forcecors
Also ensure you have enabled CORS on your Server side. I reference here some examples. Please find out what you platform offers:
JAX-RS: http://www.developerscrappad.com/1781/java/java-ee/rest-jax-rs/java-ee-7-jax-rs-2-0-cors-on-rest-how-to-make-rest-apis-accessible-from-a-different-domain/
JAX-RS: http://cxf.apache.org/docs/jax-rs-cors.html
Nodejs: http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm
Hope this helps.
I am trying to send a POST request to an endpoint over HTTPS.
The request has 2 headers, content-type (application/json) and an apiKey.
I am using the request in a PhoneGap application built in Angular, and when the request is sent its method is changed to OPTIONS.
I know this is standard practice for browsers due to CORS, but I have a payload which I need the server to take, and I'm told by the server guys that OPTIONS requests have an empty payload with CORS (although I can't find verification on this).
The server is set up for CORS and should accept POST and OPTIONS.
For some reason my request hangs.
Angular code:
var submitDBIDResource = $resource(env.loginUserUrl, {}, {
save: {
method: 'POST',
headers: { 'apiKey': apiKey }
}
});
submitDBIDResource.save({"dbid": dbid}).$promise.then(function(data) {
console.log(data);
return data;
});
I have in my config.xml file
Any ideas what I need to do?
Thanks
The browser will automatically send an OPTIONS request before it sends the POST request. The OPTIONS request must respond with the appropriate response or else the browser will not send the POST request.
Your backend guys need to create two request handlers, one for the OPTIONS and one for the POST.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS