My server returns this kind of header: Content-Range:0-10/0:
I tried to read this header in angular with no luck:
var promise = $http.get(url, {
params: query
}).then(function(response) {
console.log(response.headers());
return response.data;
});
which just prints
Object {content-type: "application/json; charset=utf-8"}
Any ideas how to access the content range header?
Use the headers variable in success and error callbacks
From documentation.
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
If you are on the same domain, you should be able to retrieve the response headers back. If cross-domain, you will need to add Access-Control-Expose-Headers header on the server.
Access-Control-Expose-Headers: content-type, cache, ...
Why not simply try this:
var promise = $http.get(url, {
params: query
}).then(function(response) {
console.log('Content-Range: ' + response.headers('Content-Range'));
return response.data;
});
Especially if you want to return the promise so it could be a part of a promises chain.
Updated based on Muhammad's answer...
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
console.log(headers()['Content-Range']);
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Additionally to Eugene Retunsky's answer, quoting from $http documentation regarding the response:
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Please note that the argument callback order for $resource (v1.6) is not the same as above:
Success callback is called with (value (Object|Array), responseHeaders (Function), status (number), statusText (string)) arguments, where the value is the populated resource instance or collection object. The error callback is called with (httpResponse) argument.
response.headers();
will give you all the headers (defaulat & customs). worked for me !!
Note . I tested on the same domain only. We may need to add Access-Control-Expose-Headers header on the server for cross domain.
The response headers in case of cors remain hidden.
You need to add in response headers to direct the Angular to expose headers to javascript.
// From server response headers :
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Origin, X-Requested-With,
Content-Type, Accept, Authorization, X-Custom-header");
header("Access-Control-Expose-Headers: X-Custom-header");
header("X-Custom-header: $some data");
var data = res.headers.get('X-Custom-header');
Source : https://github.com/angular/angular/issues/5237
According the MDN custom headers are not exposed by default. The server admin need to expose them using "Access-Control-Expose-Headers" in the same fashion they deal with "access-control-allow-origin"
See this MDN link for confirmation
[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers]
Related
I am trying to do a $http.post, but this response give me this error.
XMLHttpRequest cannot load http://XXXXXXXXX:2222/server/api/v1/controllers. Response for preflight has invalid HTTP status code 403
All of I read on internet sais that Its a fault by the CORS, I try to solve this with no success.
Here is my $http.post method.
// Set the Content-Type
$http.defaults.headers.post["Content-Type"] = "application/json";
// Delete the Requested With Header
delete $http.defaults.headers.common['X-Requested-With'];
var config = {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=utf-8'}
}
$http.post("http://XXXXXXXXX:2222/server/api/v1/controllers", objToSave , config)
.then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
console.log(response)
}, function errorCallback(error) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(error)
});
I am using Angular v1.5.5.
I hope You can help me,
Regards!
chrome first send preflight request to check if server responds properly. If server properly handles that preflight request, then original request will be sent by chrome. Try to add below line in your server request handler header.
Access-Control-Allow-Origin: *
In my Angular app, I am sending a config object with an $http.delete request using the following method:
return $http.delete('projects/' + projectID + '/activityTypes', {data: [{id: 2}]})
This appends the value of my data key to the body of the request as you can see in the picture below:
However, Angular seems to be setting the content-type as text/plain by default, and I need to be JSON.
How can I change the content type of this $http.delete request?
EDIT: I posted a screenshot with the wrong Network tab open (Response Headers instead of Request Headers) by mistake. Here is the correct version:
#charlietfl, thank you for pointing that out.
After some research I found out you can pass multiple options (such as Content-Type) within the config object that I was already passing, like so:
$http.delete('projects/' + id + '/activityTypes',
{data: activitiesToDelete, headers: {'Content-Type': 'application/json'}});
The above is working exactly as intended, so it is indeed possible to send a body with an $http.delete using Angular, and further customize the http request using that same config object.
From Angular's $http documentation:
data – {string|Object} – Data to be sent as the request message data.
headers – {Object} – Map of strings or functions which return strings representing HTTP headers to send to the server. If the
return value of a function is null, the header will not be sent.
Functions accept a config object as an argument.
I'm creating an Express route that calls the GitHub API with a ?callback=foo pattern added to the endpoint so that it will return the Link headers which I'll need to parse out the Link: header because it contains the link that I'll have to call to get the next page of the response.
The problem is that the response has the expected pattern, but when I try to create a function to tease out the meta and data portions of the function, they turn up undefined.
My code:
app.get('/populate', function(req, res, next) {
console.log('/populate route hit');
var token = "<something>";
var options = {
url: 'https://api.github.com/users?callback=resp',
headers: {
'User-Agent': 'Our-App',
'Authorization': 'token '+ token
}
};
api(options) // 'api' is request-promise module, makes http requests
.then(function(response) {
console.log(response); // Note 1
function resp(res) {
var meta = res.meta;
var data = res.data;
console.log('meta ', meta); // Note 2
console.log('data ', data);
}
resp(response);
Note 1: The response looks like:
/**/resp({"meta":{"X-RateLimit-Limit":"5000","X-RateLimit-Remaining":"4993",
"X-RateLimit-Reset":"1435297775","X-OAuth-Scopes":"public_repo, user:email",
"X-Accepted-OAuth-Scopes":"repo","Cache-Control":"private, max-age=60, s-maxage=60",
"Vary":"Accept, Authorization, Cookie, X-GitHub-OTP",
"ETag":"\"0cbbd180648a54f839a237b0302025db\"",
"X-GitHub-Media-Type":"github.v3; format=json",
"Link":[["https://api.github.com/users?callback=resp&since=46",
{"rel":"next"}],["https://api.github.com/users{?since}",
{"rel":"first"}]],"status":200},"data":[{"login":"mojombo","id":1,
...etc etc...
}]})
The response looks like it's been JSON.stringified but when I JSON.parse(response) it returns an error. I don't know how to access the deeply-embedded Link: headers and even the data, which looks like JSON, too.
Note 2 The res.meta and res.data log as undefined.
The response isn't JSON, it's JSONP. JSONP is a cross-domain mechanism for retrieving data. You don't use XHR (e.g., app.get) to request JSONP, you use a script tag. (Because XHR is limited by the Same Origin Policy; script tags aren't.)
If your call retrieving that data via XHR works, it means cross-domain XHR calls are allowed in your situation (the server supports Cross-Origin Resource Sharing with your page's origin, and the browser supports CORS). You can get JSON instead of JSONP by removing the ?callback=resp in the URL.
Im stuck at this 2 days I can not find a solution.
When im doing an AngularJS POST it Sends OPTIONS in the header and returns error from the API the code looks like this nothing special.
$http.defaults.headers.post["Content-Type"] = "application/json";
$http.post(URL, JSON.stringify(data)).
success(function(data, status, headers, config) {
alert(data);
error(function(data, status, headers, config) {
console.log("Error");
});
CORS is enabled on the API it has the Headers, when i do POST with fiddler or POSTMan in Chrome it works fine only when i use angularJS post it won't go thru.
why do i get OPTIONS /SubmitTicket HTTP/1.1 instead of POST?
What do i need to do to POST ? I have read about it it says something like CORS is adding OPTIONS header but why?
When you invoke the CORS requests, the browser always sends the OPTIONS request to server to know what methods are actually allowed. So this is the desired behaviour. This is so called: "Preflighted request", see: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/ (section: "Preflighted requests")
Therefore in your case, you have to allow the OPTIONS method in 'Access-Control-Allow-Methods' header of your CORS filter.
My understanding is that angular initially sends an OPTIONS request to the server in order to ask the server if the full request is permissable.
The server will then respond with Headers specifying what is and is not allowed.
I guess this might be an issue with the server returning the wrong CORS headers.
You said that the server returns an error please post that error here.
See Preflighted CORS request at: http://www.staticapps.org/articles/cross-domain-requests-with-cors
and
AngularJS performs an OPTIONS HTTP request for a cross-origin resource
// Simple POST request example (passing data) :
$http.post('/someUrl', {msg:'hello word!'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Should only need to do this code to get it to work:
angular.module('TestApp', [])
.factory('someService', ['$http', someService]);
function someService() {
var service = {
save: save
};
var serviceUrl = '/some/Url';
return service;
function save(data) {
$http.post(serviceUrl, data)
.success(function(data, status, headers, config) {
alert(data);
})
.error(function(data, status, headers, config) {
console.log("Error");
});
}
}
Then pull your someService into your controller and use:
someService.save(data);
In a very basic test web app I am making, I am using angular to run a function when a form is submitted. The function asynchronously posts data to a simple api I built which is supposed to input data into a database dependent on the POST information it receives. It seems like the POST is working correctly on the front end, however I cannot access request.json from Flask at all or get any of the post data. I feel like this problem may be something simple I have overlooked but as of now I cannot figure it out at all. Here is some of the code:
AngularJS:
$scope.submitAddMsg = function (){
var data = {'author': $scope.msgauthor, 'message': $scope.msgmsg};
$http.post('/addMessage', data, {headers: {'Content-Type': 'application/json'}}).
success(function(data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
}).
error(function(data, status, headers, config) {
alert(JSON.parse(data));
});
};
Flask view function for /addMessage
#app.route('/addMessage', methods=['POST'])
def addMessage():
#results in 'None type not iterable'
#response = request.form.get('author')
#results in a 400 error
#response = request.get_json()
#results in a 400 error
#response = request.get_json()
#results in 'author' not defined
#name = request.args.get('author')
#return jsonify(author = author)
return str(jsonify(response))
I cannot stop getting errors as if the request is not what I think it should be, is there something else I should be doing to properly handle this? Because I cannot access any POST information when using Angular to send the POST or even a REST Client with payload exactly how the angular is sending data.
Here is the JavaScript console to see what data, status, headers, and config ends up being in the success function that runs after the POST:
<Response 46 bytes [200 OK]>
testbase.js:53 200
testbase.js:54 function (c){a||(a=Xc(b));return c?(c=a[z(c)],void 0===c&& (c=null),c):a}
testbase.js:55 Object {method: "POST", transformRequest: Array[1], transformResponse: Array[1], headers: Object, url: "/addMessage"…}data: Objectheaders: ObjectAccept: "application/json, text/plain, */*"Content-Type: "application/json"__proto__: Objectmethod: "POST"transformRequest: Array[1]transformResponse: Array[1]url: "/addMessage"__proto__: Object
Any help on getting this working right is much appreciated, let me know if you need more information
you can use request.data to get the raw post data.
you can also set the silent Flag of get_json to True so you can get the exact message of failure.
from the docs
get_json(force=False, silent=False, cache=True)
Parameters:
force – if set to True the mimetype is ignored.
silent – if set to False this method will fail silently and return False.
cache – if set to True the parsed JSON data is remembered on the request.
Try adding app.debug = True before you start the app and try again.
You can also try:
message = request.json.get('message')
And I would also try putting this in your route
['POST', 'OPTIONS'])