4

I am dealing with server, which is not accepting uncapitalized headers and unfortunately I can't do much with it.

var headers = {};
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36';
headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8';
headers['Connection'] = 'keep-alive';
headers['Cache-Control'] = 'max-age=0';
headers['Upgrade-Insecure-Requests'] = '1';
headers['Accept-Encoding'] = 'gzip, deflate';
headers['Accept-Language'] = 'en-US,en;q=0.9,ru;q=0.8,hy;q=0.7';

request.post({url: 'http://10.10.10.10/login', headers: headers, ...

this in fact sending out the following

User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,ru;q=0.8,hy;q=0.7
DNT: 1
host: 10.10.10.10
cookie: vvv=765936875155218941

cookie and host are lower cased. How can I alter request, to send out capitalized headers?

Pablo
  • 24,270
  • 32
  • 112
  • 196
  • Header names are case-insensitive, https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive . – Estus Flask Jul 10 '18 at 11:16
  • I know it, but for some reason the server is not respecting this and I need to find workaround. – Pablo Jul 10 '18 at 13:08
  • Are you saying that `http://10.10.10.10/login` doesn't behave correctly with lower-cased `host` and `cookie`? Are you sure that this is the real problem with request and not anything else? Seems like it's server's problem in the first place, it's not spec-compilant. – Estus Flask Jul 10 '18 at 14:04
  • I'm sure because I tried to simulate it through Fiddle. Changing the `cookie` to `Cookie` is successfully authenticating user. – Pablo Jul 10 '18 at 14:59
  • Consider reporting this as a bug then if it's your or friendly server. Any way, I provided a workaround, I would expect it to work. – Estus Flask Jul 10 '18 at 15:02
  • It's an enemy server :) I'm trying now the workaround you proposed. Thx – Pablo Jul 10 '18 at 15:05

1 Answers1

5

This is not Node.js issue but a supposed issue with particular library, request. In fact, not an issue at all because HTTP headers are case-insensitive. request uses caseless package to enforce lower-cased headers, so it's expected that user headers will be lower-case if consistency is required.

These headers may be left as is, as they should be handled correctly by remote server according to the specs.

It may be necessary to specific header case if a request is supposed to mimic real client request. In this case header object can be traversed manually before a request, e.g.:

const normalizeHeaderCase = require("header-case-normalizer");

const req = request.post('...', { headers: ... });

for (const [name, value] of Object.entries(req.headers)) {
    delete req.headers[name];
    req.headers[normalizeHeaderCase(name)] =  value;
}

req.on('response', function(response) {...});
Estus Flask
  • 150,909
  • 47
  • 291
  • 441
  • basically I can no more use `function (error, response, body) {...}` callback and need to buffer data using `.on('data', ...)` ? – Pablo Jul 10 '18 at 15:50
  • I expect that request callback can be used as well. – Estus Flask Jul 10 '18 at 15:59
  • With request callback it works as well, but as far as I understand, once `request.post(...)` line passed, connection is starting. Not sure if a separate thread is spawn for it, but what can guarantee, that at the time of header normalization, the request not already sent out? Could race condition happen here? – Pablo Jul 10 '18 at 19:28
  • Seems like it's ok. The actual request starts when request(...).start() is called internally, and it's called on next tick. – Estus Flask Jul 10 '18 at 20:08