AngularJS $http.post server doesn't allow a request with method OPTIONS - angularjs

I am trying to do a an HTTP POST to a server.
The data I have to send is a json object.
The problem is that $http.post in angular override the method with options.
I can make this config
.config(['$httpProvider', function ($httpProvider) {
//Reset headers to avoid OPTIONS request (aka preflight)
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
}])
and changes from options to POST, but I can't set the content-type to "application/json", and I am getting a "415 Unsupported Media Type"
Thank you

$http.post in angular doesn't override the method with OPTIONS. It appear that you are trying to call api in different domain than the one your JS code come from. This is called Cross Domain. For such cases the browser performs preflight request with OPTIONS in order to see the returned headers. In your backend response you should add the header Access-Control-Allow-Origin: * for example. When the browser sees that header he performs the actual POST request.
More details here: https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
Hope this is helps!

Add
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json';
But note this will set the Content-Type header globally.
If you need to set the content-type per call, you should use $http.post like
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/json'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
});

Related

Response for preflight has invalid HTTP status code 403 on angular post request

I am having an $http request in my localhost which is calling a url of some api. I am getting an error on executing the call
Response for preflight has invalid HTTP status code 403
Can I do anything using angular so that I can fix this issue? I have CROS plugin of chrome to allow cross origin request
$http({
method: 'POST',
url: url,
data:data1,
headers: {
'Access-Control-Allow-Origin': '*',
}
})
If you using java restful controller as your server.
You can refer to https://spring.io/guides/gs/rest-service-cors/
I added #CrossOrigin(origins = "*") on my controller and it works.
Basically, you cannot do anything in the client side.
Lin
Ok so here's how I figured this out. It all has to do with CORS policy. Before the POST request, Chrome was doing a preflight OPTIONS request, which should be handled and acknowledged by the server prior to the actual request. Now this is really not what I wanted for such a simple server. Hence, resetting the headers client side prevents the preflight:
app.config(function ($httpProvider) {
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
});
The browser will now send a POST directly. Hope this helps a lot of folks out there... My real problem was not understanding CORS enough.
Link to a great explanation: http://www.html5rocks.com/en/tutorials/cors/
Kudos to this answer for showing me the way.
AngularJS POST Fails: Response for preflight has invalid HTTP status code 404
I have this code in angularjs:
$http.post('http://localhost:8080/employee/'
, $scope.alumno
,{headers: {'Content-Type': 'application/json'}}
).success(function(data){
if ( data.err === false ) {
$scope.actualizado = true;
setTimeout(function() {
$scope.actualizado = false;
$scope.$apply();
}, 3500);
};
});
My API have this data:
//Add employee:
Url: http://localhost:8080/employee
Type request: POST
Add a new employee:
{
"firstName": "Javier",
"lastName": "Piedra",
}`
I use chrone with extension for available CORS for the GET all perfect but post sample this error:
XMLHttpRequest cannot load http://localhost:8080/employee/. Response for
preflight has invalid HTTP status code 403
In my app.config use:
app.config( function($routeProvider,$httpProvider){
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
Maybe this can be a solution for your issue.
Regards

How do you pass in HTTP headers to make a request from an API?

Using Angular, I'm trying to pass in HTTP headers with the request, “App-Id” and “App-Key” to get data from this API.
I tried setting the headers like this:
$http.defaults.headers.common["App-Id"] = '5a3d8b8d';
$http.defaults.headers.common["App-Key"] = '738e9aca62e7465446b7be8fe4219ffa';
but I got a Response for preflight is invalid error.
http://jsfiddle.net/9Ymvt/4573/
Adding Headers to an $http Request on a Per Request Basis
To add headers to a $http request on a per request basis, add them to the headers property of the $http config object.
var xheaders = {};
xheaders["App-Id"] = '5a3d8b8d';
xheaders["App-Key"] = '738e9aca62e7465446b7be8fe4219ffa';
var xurl = 'https://uk.bookingbug.com/api/v1';
var configObj = { method: 'GET',
url: xurl,
headers: xheaders
};
$http(configObj)
.then(function onFulfilled(response) {
console.log(response);
vm.headers = response.config.headers;
vm.data = response.data
}).catch( function onRejection(errorResponse) {
console.log("Error: ", errorResponse.status);
console.log(errorResponse);
vm.error = errorResponse;
})
;
The code was getting pre-flight errors because it was using the incorrect URL. The correct base URL is https://uk.bookingbug.com/api/v1 which supports App-Id headers and CORS.
The DEMO on JSFiddle.
I do not think this is a complete answer to your question, but here is what I have in my project:
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
// code for routes
});
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
This solves my problem with CORS. If you want to do another type of header, you probably can find your answer here.
Preflight errors are related to CORS. You might want to look at rack-cors to enable cross-site api calls via javascript. There is a manual configuration here: https://gist.github.com/dhoelzgen/cd7126b8652229d32eb4

Angular $http.get sending two requests

I am trying to send authorization info in a header using Angular $http.get.
If I call $http.get without config, it send the request only once.
As soon as I add a config with header info, it sends the request twice to the server. Once without the authorization header and the second time with.
Here is my code:
var config = {
headers: {
Authorization: authorization
},
withCredentials: true
};
$http.get(url, config).success(function (response) {
$scope.records = validateResponse(response);
});
How can I get it to send only one request with the header information?
Try modifying the default http header of angularjs and make the request.
$http.defaults.headers.common.Authorization = 'token';

How to access response headers using $resource in Angular?

I basically call get requests like so:
var resource = $resource('/api/v1/categories/:id')
resource.get({id: 1}).$promise.then(function(data){
console.log(data)
})
This works fine.. but how do I get the response headers?
You could use the transformResponse action defined here this would allow you add the headers
$resource('/', {}, {
get: {
method: 'GET',
transformResponse: function(data, headers){
response = {}
response.data = data;
response.headers = headers();
return response;
}
}
See a working example here JSFiddle
#Martin's answer works for same domain requests. So I would like to add to his answer that if you are using cross domain requests, you will have to add another header with Access-Control-Expose-Headers: X-Blah, X-Bla along with the Access-Control-Allow-Origin:* header.
where X-Blah and X-Bla are custom headers.
Also you do not need to use transform request to get the headers. You may use this code:
var resource = $resource('/api/v1/categories/:id')
resource.get({id: 1}, function(data, headersFun){
console.log(data, headersFun());
})
See this fiddle.
Hope this helps !!!
Old question, but i think it's worth mentioning for the future reference.
There is 'official' solution for this in angular documentation:
It's worth noting that the success callback for get, query and other
methods gets passed in the response that came from the server as well
as $http header getter function, so one could rewrite the above
example and get access to http headers as:
var User = $resource('/user/:userId', {userId:'#id'});
var users = User.query({}, function(users, responseHeaders){
// ...
console.log(responseHeaders('x-app-pagination-current-page'));
});
(code from docs slightly updated for clarity)
For CORS requests, exposing headers as mentioned in other answers is required.

AngularJS $resource not sending custom headers

I'm using angular and angular-resource version 1.1.5 and I'm using a $resource to make a request to a REST service. But it seems like the custom headers is not appended to the request. My definition is as below. Is there anything I did wrong?
myApp.factory('User', function($resource) {
var User = $resource('http://localhost\\:7017/mydomain/users/jack', { }, {
get: {
method: 'GET',
isArray: false,
headers: {'X-Requested-By':'abc'}
}
});
return User;
});
Read this to see how to configure default headers in one place: http://docs.angularjs.org/api/ng.$http
EDIT:
Your header must be included in Access-Control-Allow-Headers header in response to the OPTIONS request, which is sent automatically prior to your GET request.
You can modify the default headers inside the $httpProvider.
the headers are an object and separated intocommon, patch, post and put
so if you want to change the default for all your requests, just do a
$httpProvider.defaults.headers.put['Content-Type'] = 'application/json';
You have to call get method by using its name, i.e User.get(callback)
It seems that custom headers do not get sent when get method is called with User.query(callback)

Resources