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.
Related
This question has been asked before but those solutions i have already tried and i shall
explain along the way.
Task:
I want to send data to api with content-type as "application/x-www-form-urlencoded".
Problem:
The URL works fine in Postman and returns me the correct response. When i try the same body parameters through my Reactjs app, it responds with 400 bad request error.
What i have tried:
myBody:{
grant_type:"XYZ",
client_id:"XYZ"
}
var request = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: "POST",
body:myBody
};
Then i fetch something like this.
const data = yield fetch(complete_url,request);
I also tried to compose myBody as a formData . Still gives the same error.
Apologies i have not given the URL because of restrictions. I am looking for possibilities of errors i could make.
With 'Content-Type': 'application/x-www-form-urlencoded',
Your request body should follow certain rule (https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
the keys and values are encoded in key-value tuples separated by '&', with a '=' between the key and the value,
example:
grant_type =value1&client_id=value2.
So i suggest what it looks like in debugger -> network tab.
If the request body is not a problem. Then you should check if there's any special chars.
You also will need to escape symbols and special chars.
I want to send a post rquest with axios that has body data and form data and I can get anything to reach through to my route hadler:
axios({
method: 'POST',
url: `${keys.SERVER_URL}/post/new-post/${isAuthenticated()._id}`,
formData,
data: { title, content },
headers: {
'Content-Type': 'application/json',
'Content-Type': 'multipart/form-data',
},
});
then in the route handler I console.log and I get nothing:
app.post("/new-post", (req, res) => {
console.log(req.body);
console.log(req.file):
});
There is no formData option for the axios() options object. If you want to set formData, you set the data property to your formData.
So, that illustrates that there is ONLY one set of data that you send with a POST or a PUT. If you want to send multiple pieces of data, you have to combine them into the same set of data and you have to obviously make them the same type of data (since there is only one master content-type). If you really needed to send multiple different types of data, then you would need to send a multi-part body that has separate sections to it. You would likely need some sort of helper to create that multi-part body since that isn't something that axios will do for you and it can get a little complicated.
If you could describe what you're actually trying to do (what the actual purpose of this request is), then we might be able to advise how to combine your data into one simpler type so it an be sent more simply.
In ngResource action I can specify custom request headers. However I need to set the headers at the time of calling the resource action.
The reason is I need paging and sorting data for the list query, and those need to be specified by custom headers (X-Order, X-Offset, and so on). This data can vary from call to call, so I cannot have them in the resource action definition.
Is there a way to pass headers while calling the action? (other than setting $http defaults)
Try Restangular service.
You can find there method: setFullRequestInterceptor which may fit your needs
//From Documentation
RestangularProvider.setFullRequestInterceptor(function(element, operation, route, url, headers, params, httpConfig) {
return {
element: element,
params: _.extend(params, {single: true}),
headers: headers,
httpConfig: httpConfig
};
});
Examples: http://plnkr.co/edit/d6yDka?p=preview
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
I have tried the following command, using resource on Angular:
angular.module('appServices', ['ngResource']).factory('Example',
function($resource){
return $resource('http://api.example.com.br/teste', {}, {
query: {method:'GET', headers: {'Content-Type': 'application/json'}}
});
});
but the http content type is not being generated correctly, in this case "application/json".
I have seen similar questions like AngularJS resource not setting Content-Type ,but I have the lastest Angular version (1.0.6/1.1.4).
What is wrong with the code above?
Conclusion
As mentioned bellow, HTTP Get method should not have a body.
The attribute headers does not work in the version described above. I used the following command unsuccessfully:
query: {method:'POST', headers: {'Content-Type': 'application/json'}}
This way has worked for me:
$http.defaults.headers.put['Content-Type'] = 'application/json';
Look at the angular source, line 8742 in the version 1.1.4:
// strip content-type if data is undefined
if (isUndefined(config.data)) {
delete reqHeaders['Content-Type'];
}
The Content-Type header gets removed if the request does not contain any data (a request body).
I think this is the expected behaviour since GET requests do not have a body.
A POST method in the other hand, will set the content-type as you expect, as long it has data in the request body. Try the following:
Change the method to POST
query: {method:'POST', headers: {'Content-Type': 'application/json'}}
And call your resource action with some parameter:
Example.query(yourData)
In this case the content type is correctly set.
Edit:
It seems it also works with get, in this case the data is in the second parameter:
Example.query(yourParams, yourData)
An example: http://jsfiddle.net/WkFHH/
Looks like it's still not supported - if you have to set the headers you can use the $http service