I have a REST API in GO language and the front-end in Angularjs , but when I get my resource in angular my custom header don't exist.
Controller:
Persons.query(
function (data, headerGetter, status) {
var headers = headerGetter();
console.log(headers["X-Total-Count"]); //PRINT: undefined
console.log(headers) //PRINT: {Content-Type:application/json;charset=utf-8}
console.log(data); //PRINT: [{name:'mr x', age:'67'}, ....]
},
function (error) {
console.error(error);
});
Model:
myApp.factory("Persons", function ($resource) {
return $resource(api_url+"/persons");
});
Response Chrome or Firefox, any client:
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:*
Content-Length:1839
Content-Type:application/json; charset=utf-8
Date:Thu, 12 Mar 2015 21:53:54 GMT
X-Total-Count:150
You're making a request from a different domain than the one where your API is located, operation which is called Cross-site HTTP requests ( CORS )
In order to use custom headers you need to set another one called Access-Control-Expose-Headers
If you want clients to be able to access other headers, you have to
use the Access-Control-Expose-Headers header. The value of this header
is a comma-delimited list of response headers you want to expose to
the client.
This header lets a server whitelist headers that browsers are allowed
to access. For example:
Access-Control-Expose-Headers: X-My-Custom-Header,X-Another-Custom-Header
This allows the X-My-Custom-Header and
X-Another-Custom-Header headers to be exposed to the browser.
The way I do it in .NET ( I suppose it's kinda similar in Go):
HttpContext.Current.Response.AppendHeader("Access-Control-Expose-Headers", "X-Total-Pages, X-Records");
HttpContext.Current.Response.AppendHeader("X-Total-Pages", pages.ToString());
HttpContext.Current.Response.AppendHeader("X-Records", records.ToString());
And in AngularJS I'm getting headers like this :
var headers = headers();
headers['x-total-pages']
So this IS a CORS issue. Setting
Access-Control-Expose-Headers:"X-Total-Count"
in the server response solves your problem.
You will need to parse the response to a number:
parseInt(headers('X-Total-Count'), 10)
Related
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;
});
I need to know Accept-Language request header value in order to make a translation on a page. I've tried to create an interceptor like
$httpProvider.interceptors.push(requestInterceptor);
, but in the method
request: function (config) {
of my interceptor I don't see Accept-Language header. I see Accept, Cache-Control, If-Modified-Since, Pragma but in the browser I do see Accept-Language.
Not all request headers are available in AngularJS request interceptor's config parameter. other header values are browser settings that are added while constructing the request.
You could use, but i'm not sure it gives you the right language.
var language = window.navigator.userLanguage or
window.navigator.language;
Only the server can see the value of Accept-Language. So i think the best way is to get this value from the server response-body and memorize it in you cookies (name example AcceptLanguageCookie) and after that you can overide the Accept-Language someway like this in your interceptor.
var app = angular.module("app", []);
app.config(["$httpProvider", function($httpProvider) {
// set Accept-Language header on all requests
$httpProvider.defaults.headers.common["Accept-Language"] = $cookies.get("AcceptLanguageCookie");
}]);
When I make a GET request that passes through grunt-connect-proxy that returns a 204, no content-type is set. If I make the same request but instead using PUT, grunt-connect-proxy (or grunt-contrib-connect - i don't know) is attaching Content-type: application/json to the response automatically. This is a problem because 1) There is no content so it's inaccurate to say the content-type is anything. and more importantly 2) Angular tries to parse the empty response as JSON which breaks my application.
I've tested the endpoint through my browser and the actual server is not sending this additional information back.
How do I prevent grunt-connect-proxy (or grunt-contrib-connect) from adding a content type to a 204 No Content response?
I've fixed the problem but I'm not sure if it's a hack. I don't think other people would have to do this because no one else has complained on the internet about it. My solution was to add a middleware to watch the 'header' event on the response and if the statusCode was 204 and the content-type was set to delete the content-type from the headers.
var apply204 = function(req, res, next) {
res.on('header', function() {
if(res.statusCode === 204) {
if(res._headers['content-type'] !== undefined) {
delete res._headers['content-type'];
}
}
});
next();
};
Still would be interested in why this happens.
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 am using $http to make an api call which is sending some custom header like X-Foo. However I can't yet figure out how to read them. Inside the $http({...}).success(function (data, status, headers, config) {...}) function, headers is a function that should give me a hash of all headers but it only shows the header content-type. Is there a way to get the response headers ?
The custom headers will be visible in same domain. However, for the crossdomain situation, the server has to send Access-Control-Expose-Headers: X-Foo, ... header to make the custom headers visible.
Spring 4.0+ provide #CrossOrigin annotation which has following parameters
origins = list of Comma separated origin.
exposedHeaders = list ofcomma separated count custom parameters.
example
#CrossOrigin(origins = "*", exposedHeaders ="X-Total-Count")