get SENT headers in an XMLHttpRequest - javascript

Trying to get the Request headers from the XHR object, but with no luck, is there a hidden method or property of that object that will expose the headers sent by the browser?
I already know how to set custom request headers and view the response headers, I'm looking to get a list of all REQUEST headers sent, ones created by the browser and my custom ones.
I'm using webkit/chrome, don't care about other browsers.
EDIT: I'm not looking to monitor the request, I'm building a web app and I need to list those headers and display them within the app, please don't tell me about fiddler, firebug and chrome tools, that's not what I'm looking for.

There is no method in the XMLHttpRequest API to get the sent request headers. There are methods to get the response headers only, and set request headers.
You'll have to either have the server echo the headers, or use a packet sniffer like Wireshark.

Try using Fiddler Web Debugger.
http://www.fiddler2.com/fiddler2/
You can capture the request that was sent in any browser as well as inspect the request headers, response headers, and even copy a capture sent request and send it out as your own.

Assuming you are using jQuery, and you're looking for anything attached, but maybe not ALL headers sent, this could help. Not sure if it meets your exact needs, (since the browser tends to add its own things), but if you need to grab your own headers first, this works:
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
if(!(settings.headers && settings.headers.token)) {
//no token header was set, so set the request header
jqXHR.setRequestHeader('token', newtoken);
}
}
})

As the name suggests, sent headers were SENT, (duh)! And the XMLHttpRequest class doesn't store sent headers in RAM or put sent headers in an instance of XMLHttpRequest... which is good for performance.
If you want to get the headers that have been sent, all you need to do is to create a log mechanism.
And since custom request header are created through XMLHttpRequest.prototype.setRequestHeader(), You need to intercept XMLHttpRequest.prototype.setRequestHeader();
var sentHeaders = {}
var originalXMLHttpRequest_setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
sentHeaders[header] = value;
originalXMLHttpRequest_setRequestHeader.call(this, header, value);
}
That's all. No need for external library nor Wireshark. All done within Javascript;
Just make sure the intercept code above executed before any XMLHttpRequest initialization.
Ps. this code will obviously only intercept the custom header created through setRequestHeader(). The XMLHttpRequest itself will set some default headers which can't be accessed through this method.

Related

Getting the http request headers in the frontend

I would like to see the http request headers in the frontend. I've been digging around in the browser's window object and saw the following:
new window.Response().headers.values()
I am aware that I can see the request headers on the backend server and then just send it as a response to the frontend, but I don't want to make the extra call instead I want to use the window object or something similar. Is such anything possible?
You can get response headers like this. The Headers class instance that fetch returns is an iterable.
fetch('https://api.sampleapis.com/wines/reds').then(function(response) {
response.headers.forEach(console.log);
});

Is there a way to get the Response Headers of WebSocket request?

On a Network tab (Chrome browser) we can see a Headers tab.
Further if we have a request list we see General, Response Headers and Request Headers lists.
For example:
General:
Request URL: wss://some.url.com/websocket
Request Method: GET
Status Code: ...
Response Headers:
OWN-KEY-FROM-SERVER: true
etc...
If that was a XMLHttpRequest, we can use getAllResponseHeaders method of xhr, but WebSocket doesn't have something like this according to the WebSocket API.
I need to get from server some trigger and he is inside Responses Headers list.
Maybe somebody know a decision with that.
If using chrome is not the only option for you, then:
I used wireshark to manitor my websocket traffic. It included all the headers and bodies and works perfectly. Just set filter for tcp.port==YOUR_PORT || (websocket) and start manitoring.

Axios how to set form data similar to jQuery ajax method?

I'm using axios in my application, but I'm having a hard time setting the content of the request.
There's currently a call to a URL using $.ajax like this:
$.ajax({
method: 'POST',
data: { 'accountId': accountId },
url: serverUrl,
/* success: ... */
});
And when I look at this request in Chrome dev tools, at the end I see something like this:
Now, I'm trying to do the same thing with axios:
axios.post(serverUrl, { accountId: accountId })
.then(/* ... */);
But, when I look at the request in Chrome dev tools, I have this:
How can I get axios to do the same formatting as jQuery? And maybe the question is that: are they different or it's just the representation?
Also, I noticed that the jQuery call is somehow adding this header: x-requested-with: XMLHttpRequest, but to have the same header in axios, I have to set it manually. Is it normal? Am I missing an axios configuration to add this header?
Thank you
Some frameworks use this header to detect XHR requests, for example. Grails Spring uses this header to identify the query XHR and gives the JSON response or the HTML response as a response.
Most Ajax libraries (Prototype, JQuery and Dojo from version 2.1) include the X-Requested-With header, which indicates that the query was made using XMLHttpRequest instead of running by clicking a regular hyperlink or submitting a form button.
A good reason for security is that it can prevent CSRF attacks, because this header can not be added to the cross domain of the AJAX request without the server's consent through CORS.
Only the following headers are allowed:
To accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
any others call the "before flight" request in the browsers supported by CORS.
Without CORS, X-Requested-With can not be added to an XHR request with a cross domain.
If the server checks the presence of this header, it knows that the request did not initiate an attempt to make a request on behalf of the user from the attacker's domain using JavaScript.
It also checks that the request was not sent from the usual HTML form, from which it is more difficult to verify that it is not a cross domain without the use of tokens. (However, checking the Origin header can be an option in supported browsers although you leave old browsers vulnerable.)
See also: https://markitzeroday.com/x-requested-with/cors/2017/06/29/csrf-mitigation-for-ajax-requests.html
So also read for greater understanding:
FormData()
https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData
Request Payload
What's the difference between "Request Payload" vs "Form Data" as seen in Chrome dev tools Network tab
As documented here, You can use the URLSearchParams API to send data in the application/x-www-form-urlencoded format using axios.
Example from offical docs:
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);

jQuery.getJSON - Access-Control-Allow-Origin Issue

I'm jusing jQuery's $.getJSON() function to return a short set of JSON data.
I've got the JSON data sitting on a url such as example.com.
I didn't realize it, but as I was accessing that same url, the JSON data couldn't be loaded. I followed through the console and found that XMLHttpRequest couldn't load due to Access-Control-Allow-Origin.
Now, I've read through, a lot of sites that just said to use $.getJSON() and that would be the work around, but obviously it didn't work. Is there something I should change in the headers or in the function?
Help is greatly appreciated.
It's simple, use $.getJSON() function and in your URL just include
callback=?
as a parameter. That will convert the call to JSONP which is necessary to make cross-domain calls. More info: http://api.jquery.com/jQuery.getJSON/
You may well want to use JSON-P instead (see below). First a quick explanation.
The header you've mentioned is from the Cross Origin Resource Sharing standard. Beware that it is not supported by some browsers people actually use, and on other browsers (Microsoft's, sigh) it requires using a special object (XDomainRequest) rather than the standard XMLHttpRequest that jQuery uses. It also requires that you change server-side resources to explicitly allow the other origin (www.xxxx.com).
To get the JSON data you're requesting, you basically have three options:
If possible, you can be maximally-compatible by correcting the location of the files you're loading so they have the same origin as the document you're loading them into. (I assume you must be loading them via Ajax, hence the Same Origin Policy issue showing up.)
Use JSON-P, which isn't subject to the SOP. jQuery has built-in support for it in its ajax call (just set dataType to "jsonp" and jQuery will do all the client-side work). This requires server side changes, but not very big ones; basically whatever you have that's generating the JSON response just looks for a query string parameter called "callback" and wraps the JSON in JavaScript code that would call that function. E.g., if your current JSON response is:
{"weather": "Dreary start but soon brightening into a fine summer day."}
Your script would look for the "callback" query string parameter (let's say that the parameter's value is "jsop123") and wraps that JSON in the syntax for a JavaScript function call:
jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
That's it. JSON-P is very broadly compatible (because it works via JavaScript script tags). JSON-P is only for GET, though, not POST (again because it works via script tags).
Use CORS (the mechanism related to the header you quoted). Details in the specification linked above, but basically:
A. The browser will send your server a "preflight" message using the OPTIONS HTTP verb (method). It will contain the various headers it would send with the GET or POST as well as the headers "Origin", "Access-Control-Request-Method" (e.g., GET or POST), and "Access-Control-Request-Headers" (the headers it wants to send).
B. Your PHP decides, based on that information, whether the request is okay and if so responds with the "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", and "Access-Control-Allow-Headers" headers with the values it will allow. You don't send any body (page) with that response.
C. The browser will look at your response and see whether it's allowed to send you the actual GET or POST. If so, it will send that request, again with the "Origin" and various "Access-Control-Request-xyz" headers.
D. Your PHP examines those headers again to make sure they're still okay, and if so responds to the request.
In pseudo-code (I haven't done much PHP, so I'm not trying to do PHP syntax here):
// Find out what the request is asking for
corsOrigin = get_request_header("Origin")
corsMethod = get_request_header("Access-Control-Request-Method")
corsHeaders = get_request_header("Access-Control-Request-Headers")
if corsOrigin is null or "null" {
// Requests from a `file://` path seem to come through without an
// origin or with "null" (literally) as the origin.
// In my case, for testing, I wanted to allow those and so I output
// "*", but you may want to go another way.
corsOrigin = "*"
}
// Decide whether to accept that request with those headers
// If so:
// Respond with headers saying what's allowed (here we're just echoing what they
// asked for, except we may be using "*" [all] instead of the actual origin for
// the "Access-Control-Allow-Origin" one)
set_response_header("Access-Control-Allow-Origin", corsOrigin)
set_response_header("Access-Control-Allow-Methods", corsMethod)
set_response_header("Access-Control-Allow-Headers", corsHeaders)
if the HTTP request method is "OPTIONS" {
// Done, no body in response to OPTIONS
stop
}
// Process the GET or POST here; output the body of the response
Again stressing that this is pseudo-code.

getting the location header of an ajax call with javascript prototype

In my javascript application(using prototype), I need some info from a third party server an this server sometimes requires web interaction with the user, and for that reason it sends 302 http code with a new URL in the Location header. What I want is to capture this new URL to open it in a separate window, however the method getHeader('Location') is always returning null. Any Idea??? This is simplified version of my code:
UPDATE = function(){
new Ajax.Request(proxy_url,{
method: 'post',
parameters: "p1=1&p2=2",
on302: function(response){
OpenURLfromLocation(response);
},
onSuccess: function(transport){
alert("OK");
}
});}
OpenURLfromLocation = function(response){
alert(response.getHeader('Location'));
}
The ajax proxy is working properly and I can see on firebug that it behaves correctly until it tries to recover the location from the header.
Most browsers consider the request of a third-party url from ajax (XMLHttpRequest) a security violation. http://www.xml.com/pub/a/2005/11/09/fixing-ajax-xmlhttprequest-considered-harmful.html
You should probably consider requesting this through a proxy or other means (like curl in php) which make the javascript request a local one.
Not sure, if that 100% answers your question, but probably should also be considered in your case here.
It's been a while since I've used Prototype, but on the actual XMLHttpRequest object, the method name is getResponseHeader. However, if you control the server's response, why not just return the new URL in the response body?
As a side note, if you're adding "location" to the response header being sent back from the server, the convention is to prepend anything that you add to the headers with an "X-", so you would have "X-Location"

Categories