Manual request dispatching

89 views
Skip to first unread message

Nick Daugherty

unread,
Aug 15, 2011, 12:03:27 AM8/15/11
to Express
Hello all, just joined; express is great. Question:

Is it possible to manually create a request object and then run it
through express, without having an actual http request come from the
browser?

Use case: I'm working on a web socket library built on socket.io that
can take requests for a certain url and return the html that it would
render, had the browser requested the uri via regular http. Basically
take regular http requests out of the picture and run all page
requests through web sockets...after the initial load. Of course, if
the browser DOES do an http request for the url, the server needs to
respond normally (standard expressjs usage).

So on the server, I need to setup socket.io to handle messages and
respond with the correct response. In the interest of keeping
everything DRY, I need to use the already defined express routes to
handle the request. I found app.handle(req, res), and have tried to
create new request and response objects to pass in, but have so far
been unsuccessful in using it.

Any thoughts?

vision media [ Tj Holowaychuk ]

unread,
Aug 15, 2011, 6:18:54 AM8/15/11
to expre...@googlegroups.com
unfortunately not very easily right now, you could emit a "request" on the app, and if you crafted the objects properly it would kinda work but node doesn't really facilitate this sort of functionality too well right now (for mocking requests etc)


--
You received this message because you are subscribed to the Google Groups "Express" group.
To post to this group, send email to expre...@googlegroups.com.
To unsubscribe from this group, send email to express-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/express-js?hl=en.




--
Tj Holowaychuk
Vision Media
President & Creative Lead

Joshua Cohen

unread,
Aug 15, 2011, 10:16:42 AM8/15/11
to expre...@googlegroups.com
I'd probably lean towards refactoring the code so a request isn't necessary. I.e. extract a function that takes as input whatever properties from the request you need, and returns the rendered markup and call that from whatever variety of code paths you have. From the request-initiated code path, you grab the properties from the request before invoking, from the socket.io (or tests, etc.) code paths, you get at the necessary input parameters however else you can...

vision media [ Tj Holowaychuk ]

unread,
Aug 15, 2011, 11:26:55 AM8/15/11
to expre...@googlegroups.com
Well technically you should be able to just create a new IncomingRequest object, I haven't tried personally but that's not really a goal of Express, we want to be performant and cover the most common use-cases, if it can be done without making the source a) slower b) significantly more difficult to read then I'm all for it, but to be honest I prefer not to mock when possible in tests so it's not something I have personal interest for but l would consider it.

vision media [ Tj Holowaychuk ]

unread,
Aug 15, 2011, 11:28:24 AM8/15/11
to expre...@googlegroups.com
plus why use web-sockets in place of xhr? that's what xhr is designed to be, a request/response

Joshua Cohen

unread,
Aug 15, 2011, 11:39:53 AM8/15/11
to expre...@googlegroups.com
Yeah, it just seems like what Nick is doing falls under Law of Demeter (http://en.wikipedia.org/wiki/Law_of_Demeter). I.e. instead of passing in the request and using some unknown set of properties from it, explicitly pass in the properties that are necessary. I know it's not necessarily idiomatic to javascript where option hashes and the like are de rigueur, but it's a good general practice guideline to keep in mind regardless. I could, of course, be overstating the benefits of refactoring since I haven't actually seen the code in question :).

TJ Holowaychuk

unread,
Aug 15, 2011, 11:42:57 AM8/15/11
to expre...@googlegroups.com
The main problem with going that route is then you form an abstraction on top of Node, which is what we used to have when Node was extremely unstable (<= 0.2.x), but now that Node is not changing too much it's not worth it 

-- 
TJ Holowaychuk

Joshua Cohen

unread,
Aug 15, 2011, 11:50:57 AM8/15/11
to expre...@googlegroups.com
I'd argue an abstraction is good in this case since the code seems to have two separate origin points. It seems like you'd have two options:

1) Abstraction: explicitly take the Request object out of the picture for the functionality in question.
2) Mocking: manually construct a Request object and remember to correctly populate it with the same properties whenever requirements change, be they on the node side (which is, as you say, relatively unlikely going forward), or within the app itself (which I cannot say how likely it would be in this particular use case).

The first just seems more maintainable to me over time :). It also seems less likely to break due to an incomplete manual construction of the Request object in the latter.

vision media [ Tj Holowaychuk ]

unread,
Aug 15, 2011, 11:59:57 AM8/15/11
to expre...@googlegroups.com
The whole point of Express though is to be a thin layer on top of Node, not to add overhead and/or duplicate all of Node's core functionality. Having our own Request#write() just delegate to IncomingMessage#write() etc would be muuuuuuch more difficult to maintain

Joshua Cohen

unread,
Aug 15, 2011, 12:02:23 PM8/15/11
to expre...@googlegroups.com
I'm not saying this should be added to Express, I'm just saying in Nick's case, this might be a good way to organize his particular Express app ;).

TJ Holowaychuk

unread,
Aug 15, 2011, 12:03:28 PM8/15/11
to expre...@googlegroups.com
Ah :) I see

-- 
TJ Holowaychuk

Nick Daugherty

unread,
Aug 15, 2011, 3:44:28 PM8/15/11
to Express
All good points...without knowing too much about Express and Node's
internals, in a perfect world the routing could be de-coupled from the
browser request...but that might not be entirely possible.

I was originally manually creating IncomingMessage and OutgoingMessage
objects to pass to app.handle(), but that didn't work out very well.

If there is no good way to do it this, would it be possible to access
the routes using app.lookup() or app.match(), and then call the
returned method with crafted IncomingMessage and OutgoingMessage
objects?
Reply all
Reply to author
Forward
0 new messages