I've run into this issue with custom headers when trying to perform and Http GET request from angular 2. Preforming the same request from Postman works fine, however I get a following 405 error in Angular2:
OPTIONS http://[somehost.com]/api/v1/admin/account/singin 405 (Method Not Allowed)
The API has a GET operation where you pass a username and password in the header and it returns a 200 with a token in it's header. Here is an example of the code block I am using:
constructor (private http: Http) {
}
login (userName: string, password: string): Observable<any> {
const endPointUrl = this.baseUrl + '/admin/account/singin';
const headers = new Headers({
'Accept': 'application/json',
'X-Rem-Username': userName,
'X-Rem-Password': password
});
const options = new RequestOptions({headers: headers});
return this.http.get(endPointUrl, options)
.map((response: Response) => {
console.log(response);
return response;
});
}
As I mentioned, performing this request in Postman and in he WebStorm REST client with these headers works fine. If I remove these 'X-Rem' headers I get a 401, which is expected. Any help would be appreciated, thanks.
Try this
const headers = new Headers({
'Accept': 'application/json',
'X-Rem-Username': userName,
'X-Rem-Password': password
});
this.http.get('url', {headers: headers})
This is not problem with angular app. Your app and rest api server are different server/domain. You should configure cross domain allow in server. Whenever you request any api on server by web browser, it first check cross domain allow options by request a OPTION method. In postman api directly send, there is no cross domain.
I am not sure but you can try add this header:
"Access-Control-Expose-Headers" : "Authorization"
I found it in this discussion
Related
I'm making a POST request to a node.js server and I'm having trouble getting it to work. Here's my request:
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
};
export const postVote = (id, vote) =>
fetch(`${uri}/posts/${id}`, {
method: 'POST',
headers,
body: JSON.stringify({options: vote}),
}).then(response => response.json())
.then(data => data)
.catch(err => console.log(err));
The function accepts an 'id' and a 'vote', both strings. The id is being used as part of the URI in the request, and the vote is being supplied as options so the API knows what to do with it. Both of the arguments are being passed correctly:
id = '8xf0y6ziyjabvozdd253nd'
vote = 'upVote'
Here's a link to the GitHub repository for the server/API:
Udacity Readable API
and a screenshot of the network when firing the request:
UPDATE: Added the second screenshot which shows status 200. Though it shows this and appears to have been successful, it still doesn't post to the server and the information stays the same.
What you are looking at is the OPTIONS request in the network tab. For cross origin requests, every request if preceeded by an OPTIONS request which tells the calling client (browser, for example) if those HTTP methods are supported by the remote server for use in crosss origin context.
Check the other requests out. If the OPTIONS request was responded to correctly by the server, the browser must automatically follow up with your POST request
EDIT:
Also, the docs specify the param name to be option whereas in your screenshot it is coming up as options.
Further reading: CORS
Try declaring the headers as such:
var headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
})
return fetch(`{SERVICE API URL}`, {
method: 'GET',
headers: {
'userName': "username",
'password': "password",
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
I'm trying to get service API data with authorization headers, but getting 401 - Unauthorized error and the response is Missing Request Headers.
Tried with sending authorization content with body also - getting same error 401 - Unauthorized error.
Edited:
headers: {
'userName': "xyz",
'sessionToken': "xyz................."
}
When I'm checking with Postman client it is working fine, but not with the redux-saga fetch method. Kindly help me for this.
Looks like it's a backend problem - CORS Filter configuration
If the backend is on a different server (could be on the same machine, but in a different Application Server, in other words, on a different port) you have to do some CORS Filters configurations.
The frontend code is running on a server - that means it's an application. Postman is a client, just like Google Chrome or any other browser. That's the explanation why you can do the request without any problem from Postman but unsuccessful from your frontend application.
I guess you enabled the Access-Control-Allow-Origin header on the backend
Now you have to allow your custom headers with Access-Control-Allow-Headers
Whenever I use fetch and I need to add headers to the request I do it this way:
headers: new Headers({
Accept: 'application/json',
Authorization: token,
'Content-Type': 'application/json',
}),
so you might want to try this approach, also in order to debug this issue you might want to check your Netowrk tab and verify which headers are sent with the request.
You need to add an Authorization bearer header.
For instance:
headers = new Headers({
'Authorization': `Bearer ${authorizationCodeOrCredentials}`
});
In your code:
return fetch(`{SERVICE API URL}`, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + someValue, // Add this line
'userName': "username",
'password': "password",
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
If you are using Linux system & If you have chrome in it...
Run your chrome using following command
/opt/google/chrome/chrome --disable-web-security --user-data-dir
Try now, If everything works fine then it's CORS issue from Backend.
I make $http POST request to a server api but request method changes to OPTIONS.
I do it all with localhost. So I did the same request through the Postman and everything works
Service:
function httpReg(userData) {
console.log(userData)
return $http({
method: 'POST',
url: CONFIG.APIHost + '/auth/signup',
data: {
"username": userData.username,
"email":userData.email,
"password": userData.password
},
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
});
}
Screenshot:
(source: joxi.net)
Actually your preflight request is bounced back.
If the browser doesn't trusts the data source you are hitting the browser first sends a preflight request to that server and if that returns 200OK, then browser will send your original request.
The applies only to browsers, and other tools such as postman dosen't send and preflight requests, so your code might work their.
How to solve the problem.
Add headers for accepted options GET, POST, OPTIONS, PUT to the requested resource.
Yes it looks like cors problem.
Try one of the following:
Try to set the referrer in your header
Try this:
app.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 = {};
}]);
Remove the x-auth* settings from _app.js file of your yeoman/gulp settings.
Reference: AngularJS performs an OPTIONS HTTP request for a cross-origin resource
I am trying to add a custom header, X-Query-Key, to a HTTP request using Fetch API or request but when I add this to the header of the request it appears to fail at setting the headers and the Request Method is set to OPTIONS for some reason.
When I remove the header it goes back to being GET as it should do.
Sample code looks like below:
const options = {
url: url,
headers: {
'Accept': 'application/json',
'X-Query-Key': '123456' //Adding this breaks the request
}
};
return request(options, (err, res, body) => {
console.log(body);
});
Try this:
const headers = new Headers({
"Accept": "application/json",
"X-Query-Key": "123456",
});
const options = {
url: url,
headers: headers
};
return request(options, (err, res, body) => {
console.log(body);
});
If that does not solve the issue, it may be related to CORS.
Custom headers on cross-origin requests must be supported by the
server from which the resource is requested. The server in this
example would need to be configured to accept the X-Custom-Header
header in order for the fetch to succeed. When a custom header is set,
the browser performs a preflight check. This means that the browser
first sends an OPTIONS request to the server to determine what HTTP
methods and headers are allowed by the server. If the server is
configured to accept the method and headers of the original request,
then it is sent. Otherwise, an error is thrown.
So you will have 2 requests if use custom headers, first one with method OPTIONS to check if server allows custom headers and after that if the server response is 200 OK and allows your originary request the second one will be send
Working with the Fetch API
I am working on an angular.js project with one of my friends, and we are running into a specific CORS (cross origin request) issue. The server is a Microsoft ASP.NET restful API, and I am using angular.js with Node.js.
We enabled CORS on the server side, and are able to get responses for everything else, accept the user login, which we are using ASP.NET Identity with. We always get the same error which I will post bellow, as well as the POST from the Client side. So basically my question is, does any one have an idea on how to fix this? Thanks!
XMLHttpRequest cannot load http://lectioserver.azurewebsites.net/api/v1/accounts/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost' is therefore not allowed access. The response had HTTP status code 400.
function login(username, password) {
var innerconfig = {
url: baseUrl + "/api/v1/accounts/login",
data: {
username: username,
password: password,
grant_type: "password"
},
method: "POST",
headers:
{
'Accept': 'text/json'
}
};
return $http(innerconfig).then(onSuccess, requestFailed);
function onSuccess(results) {
if (results && results.data) {
$rootScope.access_token = results.data.access_token;
return results.data;
}
return null;
}
}
Try to set the content-type in the headers, this might fix the issue
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
This usually happens because app that provides you token starts before CORS initiates.
Fixing it is very easy. You just need to go to IdentityConfig.cs and inside that there is function called as
public static ApplicationUserManager Create
(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
Insert this following line of code there
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
This will enable CORS for Token request.
But problem is when we do this other normal requests will start throwing error since we have granted access origin * twice. Once in identiy and other in cors.
if you run into this error use this if statement on cors code in identity config you just pasted.
if(context.Request.ContentType == "text/plain")