2

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' } } }
prototype
  • 7,249
  • 15
  • 60
  • 94
  • 500 internal error generally means there is an error at the server side. Did you check the API server logs? Is it trying to parse the 'User-Agent' header? – Nehal J Wani Apr 09 '17 at 15:49
  • Great question. I don't have access to the server, just the OAuth route. Does curl or request pass a `User-Agent` header? – prototype Apr 09 '17 at 15:50
  • Curl passes one, I don't think request does unless you specify it. – Nehal J Wani Apr 10 '17 at 03:04
  • 1
    @NehalJWani Thank you!! That was the clue I needed. curl supplies additional headers. Adding `--verbose` to curl, I see one of these is `"Accept: */*"` and adding that to request makes it work. Just for fun and formality please write that as an answer I can accept. – prototype Apr 10 '17 at 04:34
  • I have added it as an answer. – Nehal J Wani Apr 10 '17 at 16:20

1 Answers1

2

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.

Nehal J Wani
  • 16,071
  • 3
  • 64
  • 89