Search code examples
node.jsabsolute-pathsuperagent

Superagent with absolute url prefix


I've noticed that I'm writing http://localhost everytime I want to run a node test with superagent.

import superagent from 'superagent';

const request = superagent.agent();
request
  .get('http://localhost/whatever')
  .end((err, res) => { ... });

Is there any way of avoiding the localhost part?

As far as I've gone is to avoid the request being hardcoded to the host:

const baseUrl = 'http://localhost:3030';

request
  .get(`${baseUrl}/whatever`)

But I still have to carry the baseUrl with the agent everytime.


Solution

  • TL;DR: superagent-absolute does exactly that.

    Detailed:

    You can create one abstraction layer on top of superagent.

    function superagentAbsolute(agent) {
      return baseUrl => ({
        get: url => url.startsWith('/') ? agent.get(baseUrl + url) : agent.get(url),
      });
    }
    

    ⬑ That would override the agent.get when called with a starting /

    global.request = superagentAbsolute(agent)('http://localhost:3030');
    

    Now you would need to do the same for: DELETE, HEAD, PATCH, POST and PUT.

    https://github.com/zurfyx/superagent-absolute/blob/master/index.js

    const OVERRIDE = 'delete,get,head,patch,post,put'.split(',');
    const superagentAbsolute = agent => baseUrl => (
      new Proxy(agent, {
        get(target, propertyName) {
          return (...params) => {
            if (OVERRIDE.indexOf(propertyName) !== -1 
                && params.length > 0 
                && typeof params[0] === 'string' 
                && params[0].startsWith('/')) {
              const absoluteUrl = baseUrl + params[0];
              return target[propertyName](absoluteUrl, ...params.slice(1));
            }
            return target[propertyName](...params);
          };
        },
      })
    );
    

    Or you can simply use superagent-absolute.

    const superagent = require('superagent');
    const superagentAbsolute = require('superagent-absolute');
    
    const agent = superagent.agent();
    const request = superagentAbsolute(agent)('http://localhost:3030');
    
    it('should should display "It works!"', (done) => {
      request
        .get('/') // Requests "http://localhost:3030/".
        .end((err, res) => {
          expect(res.status).to.equal(200);
          expect(res.body).to.eql({ msg: 'It works!' });
          done();
        });
    });