Supertest: How can I get the server address?

Created on 26 May 2016  路  5Comments  路  Source: visionmedia/supertest

Hi, how can I get the server address?

import app from './app'
const client = supertest(app)

client.get('/api/customers').then(response => {

})

// how do I find out what port supertest is using?

Thanks.

Most helpful comment

I think this is worth re-opening. It's a common requirement for REST services to return e.g. Location headers which would include a port.

The SO suggestion proposes:

var app = require('express')();

var listener = app.listen(8888, function(){
    console.log('Listening on port ' + listener.address().port); //Listening on port 8888
});

As far as I can see, the invocation of require('supertest')(someExpressApp) never gives access to that listener. The created server (source link) is passed in the closure to all methods but is never itself returned to the caller.

app = http.createServer(app);

It would be trivial to add this function to the returned object:

  if (typeof app === 'function') {
    app = http.createServer(app);
    obj.address = app.address
  }

so the caller could get the port:

const tester = require('supertest')(someExpressApp)
const test = tester.get('/some/path')
    .set('link', `<${service()}/some/path>; rel="subscription"`)
const resp = await test.send()

service = () => `http://${tester.address().host}:${tester.address().port}`

All 5 comments

I think this is outside the scope of supertest. The port will be based on how you instantiate app (in your example above).
Here is a SO answer that answers for express v4 (and v3). Other answers offer more generic answers.

I think this is worth re-opening. It's a common requirement for REST services to return e.g. Location headers which would include a port.

The SO suggestion proposes:

var app = require('express')();

var listener = app.listen(8888, function(){
    console.log('Listening on port ' + listener.address().port); //Listening on port 8888
});

As far as I can see, the invocation of require('supertest')(someExpressApp) never gives access to that listener. The created server (source link) is passed in the closure to all methods but is never itself returned to the caller.

app = http.createServer(app);

It would be trivial to add this function to the returned object:

  if (typeof app === 'function') {
    app = http.createServer(app);
    obj.address = app.address
  }

so the caller could get the port:

const tester = require('supertest')(someExpressApp)
const test = tester.get('/some/path')
    .set('link', `<${service()}/some/path>; rel="subscription"`)
const resp = await test.send()

service = () => `http://${tester.address().host}:${tester.address().port}`
const request = require('supertest'); // npm i -ED supertest
const app = require('../app'); // your expressjs app
const { url } = request(app).get('/'); // next, just use url
console.debug(url); // prints: http://127.0.0.1:57516/

Don't know how the the above code worked for everyone else, but I found the url that I wanted under the request key inside the result of the GET request. I was on an older version of supertest (4.0.2) and upgraded and it's still in <return>.request.url for me. Code looked like this:

  const { request: { url: testAppBaseURL } }: any = await request(app).get('/');

Please excuse the any usage -- looked through the type declarations for both superagent and supertest and I can't find the right type, SuperAgentRequest should be the right type but it looks like there's some subclass that isn't properly represented, and the inferred class isn't right (it doesn't have the request key). This was a good chance to upgrade supertest though.

The Test object returned by request() is also referenced in the Response object. For folks landing here later, here's a stand-alone callback example using "supertest": "^6.1.3" and "express": "^4.17.1" which demonstrates four ways to get the host:

const Supertest = require('supertest')
const App = require('express')()
const ReqPath = '/hello'
const Body = 'Hello World'
App.get(ReqPath, function (req, res) { res.send(Body) })

const request = Supertest(App).get(ReqPath)
console.log(
  'request.url:', new URL(request.url).port,
  '\nrequest.host:', request.host,
)
request
  .expect('Content-Length', "" + Body.length)
  .expect(200)
  .end((err, resp) => {
    console.log(
      'request.host:', request.host,
      '\nresp.request.url:', new URL(resp.request.url).port,
      '\nresp.request.host:', resp.request.host,
    )
  })
request.url: 45633 
request.host: undefined
request.host: 127.0.0.1:45633 
resp.request.url: 45633 
resp.request.host: 127.0.0.1:45633

Note that request.host is not populated until request has been end()-ed (or awaited as in @t3hmrman's example).

Was this page helpful?
0 / 5 - 0 ratings