why axios send OPTIONS request method not DELETE or PUT method - reactjs

why I use axios.delete(url) or axios.put() to send request, but when I check request from NetWork in Chrome Dev Tools the Request Method is OPTIONS and Access-Control-Request-Method is DELETE or PUT like this:

DELETE or PUT (or other non-simple) requests first send out a preflighted OPTIONS request to determine if you're allowed to send this request. The request method is given in the Access-Control-Request-Method header.
See more here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests

Axios uses JSON as the default content type, the call was always going with a browser as a OPTIONS call not a POST method. To overcome, we need to set the ‘Content-Type’ correctly. My configuration as following
let config={
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}
return axios.post(postUrl,postJson,config).then(response=>{
return response.data;
}).catch(error=>{
return error;
});

Related

Axios .get request weird behaviour

I have the following get request:
return axios
.get<ArticlesResponse>(SUGGESTED_ARTICLES, {
headers: {
'Content-Type': 'application/json',
},
})
.then(onRequestSuccess)
.catch(onRequestError);
It returns me an object with the data I need, however, the data field inside the object is a string instead of an actual object. Anyone has any ideea about why? I looked it up and saw that adding that header above will fix the issue but it doesn't. Thanks in advance!
My onRequestSucces is:
export function onRequestSuccess<T = any>(response: AxiosResponse<T>) {
console.log('Request Successful!', response);
return response.data;
}
JSON.Parse() also won't fix it.
The problem may be due to the API returning a response that contains invalid JSON data, now JSON.parse would throw an error, but Axios manages the exception by setting the invalid JSON as string in the data property. Try using the Fetch API.
Since you're using a GET request (doesn't have a body) the 'Content-Type' is not being useful. This header is used to tell the server which type of content you're sending, but you're sending none. You should use it only on POST/PUT requests.
See this question for more details on this.
In order for your request to be read as JSON you have to set the header in the server. This will tell the browser you're receiving a JSON, which will then be parsed automatically by axios.

How can I set cookie header using react and request-promise

"Cookie" header is never sent, even when browser console shows otherwise
I am trying to use request-promise and Reactjs to send request from my web application to SAP B1 Service Layer. First, I tried using the "headers" option in request-promise, then tried setting a cookie using rp.cookie("...") and jar.setCookie("...") but got errors both times.
The browser console is showing it is sending the "Cookie" header, but when I intercept the request using Burp Suite the header is never sent.
var rp = require('request-promise').defaults({jar:true});
var rd= require('request-debug');
rd(rp);
const b1jar=rp.jar();
let options = {
method: method,
rejectUnauthorized: false,
uri: url,
insecure:true,
jar:b1jar,
json: true,
resolveWithFullResponse:fullres,
// I TRIED TO USE THIS FIRST
headers:
{ 'Cookie': "B1SESSION="+(sessionStorage.SessionID||'')+';',
}
};
//THEN DELETED THE headers OPTION AND TRIED WITH THE jar OPTION
var b1cookie=rp.cookie('B1SESSION='+sessionStorage.SessionID);
b1cookie.setExpires(moment().add(sessionStorage.SessionTimeout,'m')
.toDate());
b1jar.setCookie(b1cookie,config.server);
res = await rp(options);
The expected result is that the B1SESSION Cookie should be sent when using rp(options), but it is not.
That API is pretty bad, try axios...
https://www.npmjs.com/package/react-axios

Angular: set Content-Type per query

I need to perform one query with Content-Type different than application/json.
Changing default $http options is not a variant, because a lot of queries still be performed with JSON data.
I've found example
var req = {
method: 'POST',
url: 'example.com',
headers: {
'Content-Type': "application/x-www-form-urlencoded"
},
data: "somedata"
}
$http(req).then(function (resp) { console.log(resp);});
But it don't want to work — Content-Type is still a application/json.
Is any true way to do it right? Changing $http defaults and then restoring is not a solution.
What you are doing is not a valid way to set headers in angularjs.
To add or overwrite these defaults, simply add or remove a property
from these configuration objects. To add headers for an HTTP method
other than POST or PUT, simply add a new object with the lowercased
HTTP method name as the key, e.g. $httpProvider.defaults.headers.get =
{ 'My-Header' : 'value' }.
Ref. https://docs.angularjs.org/api/ng/service/$http - "Setting HTTP Headers" section
Edit.
What you're doing is right but you're missing one thing.
In your scenario it does not work because when using application/x-www-form-urlencoded you need to encode your data using $httpParamSerializerJQLike(). Also remember to put $httpParamSerializerJQLike as dependency.

In an Angular http response interceptor, how can I get at the actual xhr object?

The method for a response interceptor is:
return {
response: function(response) {
// processing here
}
};
Because of the issues with CORS response headers and various bugs, I want to access the xhr object directly and retrieve specific headers. However, response seems to only have:
data - the returned body
config - the original request
status - the response status
headers() - the problematic function that gets stuck on the bugs
How can I get at the actual xhr object so I can look at the headers directly?
For reference: AngularJS and Apiary.IO - can't read any response headers?
I want to do option 3, and work with xhr directly, but how do I get to it in an interceptor?
I don't think there's a way to access the xhr object directly exposed to interceptors. However, If this is all due to the Firefox bug mentioned, you can do the following to get access to the headers you're looking for in FF:
Patch
https://github.com/angular/angular.js/blob/v1.2.0-rc.2/src/ng/httpBackend.js#L76
Add the headers you need. Currently it's only asking for the specified headers in that array for the FF work-around. You'd add something like:
simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type",
"Expires", "Last-Modified", "Pragma", "Access-Control-Allow-Origin"];

How do I remove the default headers just for specific XHR requests in AngularJS?

99% of my ajax calls need a specific "X-API-TOKEN" to authenticate and communicate with my Rails REST API. But I'm also making a call to one thrid party API and I keep getting an error saying "Request header field X-API-TOKEN is not allowed by Access-Control-Allow-Headers."
Everything works fine if I delte the header right before the call, and a work around would be to delete and then re-add after the call, but is there an easier way than this:
apiToken = $http.defaults.headers.common["X-API-TOKEN"]
delete $http.defaults.headers.common["X-API-TOKEN"]
$http(
method: "GET"
url: 'http://...}}'
).success((data, status, headers, config) ->
).error (data, status, headers, config) ->
$http.defaults.headers.common["X-API-TOKEN"] = apiToken
Set the desire header/headers to undefined like this, then it will not affect the global settings.
$http( {
method: 'GET',
url: 'someurl',
headers: {
'X-API-TOKEN': undefined
}
}
)
The $http service config object allows you to override the http header send for a specific request. See config property headers.
This can take a list of headers or a function that return a list of headers. So for the non auth header request make a copy of the default headers remove the header you dont require and then make the request. You can store this for later use.
See $http documentation

Resources