Search code examples
node.jscurlhttpsrequestjs

request.js fails where CURL succeeds for GET request with Authorization header


I can make a GET request with an Authorization header from curl but not from request or https in Node.js. The server returns status 200 with curl but 500 with request or https. How might the call from request or https be different from curl? How might the server be reading them differently?

The following cURL succeeds from command line:

curl -H "Authorization:  Bearer abc123def456" https://api.domain.com/path/to/resource

But the same request fails with request.js in Node

var options = {
  type: 'get',
  url: "https://api.domain.com/path/to/resource",
  headers: {
     "Authorization": " Bearer abc123def456" 
  }
}
request(options, function (err, response, body) {
  assert.equal(response.statusCode, 200) ; // 500 internal error
})

The following also fails with request.js using the auth option:

var options = {
  type: 'get',
  url: "https://api.domain.com/path/to/resource",
  auth: {
    "bearer": "abc123def456" 
  }
}
request(options, function (err, response, body) {
  assert.equal(response.statusCode, 200) ; // 500 internal error
})

It also fails when using https without request.js:

var options = {
  host: 'api.domain.com',
  port: 443,
  path: '/path/to/info',
  method: 'GET',
  headers: {
    "Authorization": " Bearer abc123def456"
  }
}
var req = https.request(options, function (res) {
  res.setEncoding('utf8');
  res.on('end', function () {
    assert.equal(res.statusCode, 200) // 500 internal error
  })
});

req.on('error', function (e) {
  console.log('problem with request: ' + e.message);
});

req.end();

But the curl requests succeeds if shelled out from Node:

exec("curl -H "Authorization:  Bearer abc123def456" https://api.domain.com/path/to/resource", function (error, stdout, stderr) {
  var obj = JSON.parse(stdout) // successfully retrieved and parsed
});

request-debug gives the following info:

{ request: 
   { debugId: 1,
     uri: 'https://api.domain.com/path/to/resource',
     method: 'GET',
     headers: 
      { host: 'api.domain.com',
        authorization: 'Bearer abc123def456' } } }

Solution

  • 500 internal error generally means there is an error at the server side . So, ideally, you should be taking a look at the server logs.

    However, if you don't have access to those logs, look at the difference between the requests sent by each one of the options you tried:

    Module: Request (with manually specified auth header):

    GET /path/to/resource HTTP/1.1
    Authorization:  Bearer abc123def456
    host: api.domain.com
    

    Module: Request (with explicitly specified auth header):

    GET /path/to/resource HTTP/1.1
    host: api.domain.com
    authorization: Bearer abc123def456
    

    Module: HTTP (with manually specified auth header):

    GET /path/to/info HTTP/1.1
    Authorization:  Bearer abc123def456
    Host: api.domain.com
    

    Curl:

    GET /path/to/resource HTTP/1.1
    Host: api.domain.com
    User-Agent: curl/7.51.0
    Accept: */*
    Authorization:  Bearer abc123def456
    

    It is quite evident that the rest of the modules do not send the HTTP headers 'User-Agent' and 'Accept'. So, it could be the case that the app running on the server is trying to parse at least one of this and failing.