35

I have an ExpressJS routing for my API and I want to call it from within NodeJS

var api = require('./routes/api')
app.use('/api', api);

and inside my ./routes/api.js file

var express = require('express');
var router = express.Router();
router.use('/update', require('./update'));  
module.exports = router;

so if I want to call /api/update/something/:withParam from my front end its all find, but I need to call this from within another aspect of my NodeJS script without having to redefine the whole function again in 2nd location

I have tried using the HTTP module from inside but I just get a "ECONNREFUSED" error

http.get('/api/update/something/:withParam', function(res) {
   console.log("Got response: " + res.statusCode);
   res.resume();
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});

I understand the idea behind Express is to create routes, but how do I internally call them

FrickeFresh
  • 1,688
  • 1
  • 19
  • 31

5 Answers5

41

The 'usual' or 'correct' way to handle this would be to have the function you want to call broken out by itself, detached from any route definitions. Perhaps in its own module, but not necessarily. Then just call it wherever you need it. Like so:

function updateSomething(thing) {
    return myDb.save(thing);
}

// elsewhere:
router.put('/api/update/something/:withParam', function(req, res) {
    updateSomething(req.params.withParam)
    .then(function() { res.send(200, 'ok'); });
});

// another place:
function someOtherFunction() {
    // other code...
    updateSomething(...);
    // ..
}
bchociej
  • 1,369
  • 9
  • 12
  • 2
    Ya, after doing some more digging, I kinda realized this was probably the only way to go about it. I wasn't sure if Express had a built in "call your own route" type of function going for it. Thanks – FrickeFresh Aug 15 '16 at 03:34
  • If you do not need to call subsequent middleware, this will do the trick – nextt1 Oct 05 '21 at 10:16
11

This is an easy way to do an internal redirect in Express 4:

The function that magic can do is: app._router.handle()

Testing: We make a request to home "/" and redirect it to otherPath "/other/path"

var app = express()

function otherPath(req, res, next) {
  return res.send('ok')
}

function home(req, res, next) {
  req.url = '/other/path'
  /* Uncomment the next line if you want to change the method */
  // req.method = 'POST'
  return app._router.handle(req, res, next)
}

app.get('/other/path', otherPath)
app.get('/', home)
Andres Separ
  • 3,144
  • 1
  • 19
  • 17
  • 4
    I get `TypeError: Cannot read property 'handle' of undefined` – golimar Nov 05 '20 at 15:48
  • Note that setting `req.url` as in `req.url = '/other/path'` will remove any querystring parameters: if you want to preserve them, possibly best to parse and reform the url in some (safe) way. – phhu Jul 21 '22 at 10:46
3

I've made a dedicated middleware for this : uest.

Available within req it allows you to req.uest another route (from a given route).

It forwards original cookies to subsequent requests, and keeps req.session in sync across requests, for ex:

app.post('/login', async (req, res, next) => {
  const {username, password} = req.body

  const {body: session} = await req.uest({
    method: 'POST',
    url: '/api/sessions',
    body: {username, password}
  }).catch(next)

  console.log(`Welcome back ${session.user.firstname}!`

  res.redirect('/profile')
})

It supports Promise, await and error-first callback.

See the README for more details

abernier
  • 27,030
  • 20
  • 83
  • 114
0

Separate your app and server files with the app being imported into the server file.

In the place you want to call your app internally, you can import you app as well as 'request' from 'supertest'. Then you can write

request(app).post('/someroute').send({
  id: 'ecf8d501-5abe-46a9-984e-e081ac925def',
  etc....
});`
0

This is another way.

const app = require('express')()
const axios = require('axios')
const log = console.log

const PORT = 3000
const URL = 'http://localhost:' + PORT
const apiPath = (path) => URL + path

app.get('/a', (req, res) => {
    res.json('yoy')
})

app.get('/b', async (req, res) => {
    let a = await axios.get(apiPath('/a'))
    res.json(a.data)
})

app.listen(PORT)
Sahil Rajput
  • 318
  • 4
  • 17