2

I'm curious if there is any way to issue an internal request in express without going through all the actual overhead of a real request. An example probably shows the motivation better:

app.get("/pages/:page", funciton(req, res)
{
    database_get(req.params.page, function(result)
    {
        // "Page" has an internal data reference, which we want to inline with the actual data:
        request(result.user_href, function(user_response)
        {
            result.user = user.response.json;
            res.send(result);
        });
    });
});

/// ....

app.get("/user/:name", function() ... );

So what we have here is a route whose data requires making another request to get further data. I'd like to access it by just doing something like app.go_get(user_href) instead of the heavy weight actual request. Now, I've asked around and the going strategy seems to be "split out your logic". However, it actually requires me to duplicate the logic, since the recursive data is referenced properly through URLs (as in the example above). So I end up having to do my own routing and duplicating routes everywhere.

erbridge
  • 1,376
  • 12
  • 27
  • 1
    if you are planing in using that routes functionality some other places then you should create a module to contain a named function to perform the operation that way you can call the function simply invoking the module from any place in your app – Dayan Moreno Leon Jan 05 '15 at 23:26
  • 1
    I believe I covered why this option wasn't viable for me (although I may be misunderstanding your response). Basically, the route is *part of the functionality*, and thus can't be put into a separate module without writing a route parser: The data is something like data = { href: some_url }. So I need to be able to do get_data_at_url(data.some_url), hence needing the routing to take place. – Francisco Ryan Tolmasky I Jan 05 '15 at 23:39
  • 1
    if you control the router you can do something like app.get(module.myroute) where myroute=function(req,res){} inside the module then anywhere you can do. unless your route handler uses module variables, you should be ok. for using this function you can build your req and response streams just like node would – Dayan Moreno Leon Jan 06 '15 at 00:27
  • 1
    duplicates https://stackoverflow.com/q/38946943/133327 – abernier Dec 28 '19 at 21:25
  • Does this answer your question? [Calling Express Route internally from inside NodeJS](https://stackoverflow.com/questions/38946943/calling-express-route-internally-from-inside-nodejs) – abernier Dec 29 '19 at 11:53

2 Answers2

0

Can you avoid the overhead of a real request? No. If you need the href from the first request in order to go to get a user object, you absolutely need to follow that link by making a second "real request."

If you have a database of users, you CAN avoid the request by including the user's ID on the page, and making a regular database call instead of following your own href.

Demo refactor on splitting out logic:

// Keep as little logic as possible in your routes:
app.get('/page/:page', function(req, res){
  var pageId = req.params.page;
  makePage(pageId, function(err, result){
    if(err){ return res.send(500) }
    res.send(result)
  }) 
})

// Abstract anything with a bunch of callback hell:
function makePage(pageId, callback){
  database_get(pageId, function(result) {
    // Since it's only now you know where to get the user info, the second request is acceptable
    // But abstract it:
    getUserByHref(result.user_href, function(err, data){
      if(err){return callback(err)};
      result.user = data.json;
      callback(null, result);
    });
  });
}

// Also abstract anything used more than once:
function getUserByHref(href, callback){
  request(href, function(err, response, body){
    if(response.statusCode != 200){
      return callback(err);
    }
    var user = JSON.parse(body);
    return callback(null, user);
  })
}

// It sounds like you don't have local users
// If you did, you would abstract the database call, and use getUserById
function getUserById(id, callback){
  db.fetch(id, function(err, data){
    return callback(err, data);
  })
}
Plato
  • 10,812
  • 2
  • 41
  • 61
  • 1
    So the idea is that the js object could contain any amount of internal refs to different resources, so you can't know whether to use getUserByHref or getCartByHref without... routing. The href in the json are designed to be able to grab the data from the client with an xmlhttprequest, its just that you can also speed things up by preloading them on initial load. What's needed is a obj.value = express.load(obj.href) analog to the client's obj.value = xmlhttprequest(obj.href). I don't expect a solution (I believe you it doesn't exist), just seems weird that this isn't supported. – Francisco Ryan Tolmasky I Jan 06 '15 at 00:49
  • 1
    Sounds like your best option is abstracting the href-following request code into `getAnythingByHref` then invoke it in your routes as appropriate like I do in `makePage()` – Plato Jan 06 '15 at 01:25
  • 1
    Yeah, so implement a route parser, which is what getAnythingByHref would be. – Francisco Ryan Tolmasky I Jan 06 '15 at 02:34
0

I've made a dedicated middleware for this uest, see my detailed answer here: https://stackoverflow.com/a/59514893/133327

abernier
  • 27,030
  • 20
  • 83
  • 114