Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Middleware Upgrade: Usage & Discussion #14

Closed
biofractal opened this issue Jul 9, 2015 · 7 comments
Closed

Middleware Upgrade: Usage & Discussion #14

biofractal opened this issue Jul 9, 2015 · 7 comments

Comments

@biofractal
Copy link
Contributor

@travist
@zackurben

I have been experimenting with the new middleware upgrade and I thought it might be interesting for you to see how I am using it. It is working beautifully and definitely solves the problem I was having previously where I was calling my own API via http - so that is really good news. However I have come across a potential issue that I will explain further down.

Working Example

Here is a working test example (coffeescript) of how I am currently using the middleware. I am using the async package to chain together a series of asynchronous calls:

router = require('express').Router()
async = require 'async'

router.get '/test/:key', (req, res, next) ->
    resj = req.app.resourcejs
    async.waterfall [
        (cb)->
            req.query.key = req.params.key
            resj['/api'].get.call this, req, res, ->
                return cb res.resource.status unless res.resource.status is 200
                cb null, res.resource.item[0]
        (api, cb)->
            req.body =
                key : api.key
                vid : '123'
                mac : '123'
            resj['/verification'].post.call this, req, res, ->
                return cb res.resource.status unless res.resource.status is 201
                cb null, res.resource.item
    ], (err, verification)->
        console.log 'err', err
        console.log 'verification', verification
        next()

module.exports = router

The process I am replicating here is

  1. get an api object with a given key.
    Note: the key value is a url-part and not a query param but the resourcejs uri expects a query param thusly: /api?key=[value] so I just copy the key value from req.params to req.query and it works as expected.
  2. post a new verification object based on details from the retrieved api.
    Note: I have to pack the req.body with the details of the new verification
  3. log some values and call next()

Problem

The problem I have is the final clause in the async chain. In the working example above I am just logging out some values and calling next()

    ], (err, verification)->
        console.log 'err', err
        console.log 'verification', verification
        next()

In fact I want to return the error status code, if one has been sent, or otherwise render a jade template - something like this:

    ], (err, verification)->
        return res.sendStatus err if err?
        res.render 'verify', title:'verify', vid:verification.vid

Doing this gives the error: Can't set headers after they are sent presumably because resourcejs has already sent the resource?

I would appreciate your thoughts on how I should proceed with this use-case.

@biofractal
Copy link
Contributor Author

OK, so you have thought of everything :-)

I was wandering through the resourcejs code wondering how to block the response.Maybe I would create a flag on on the req, maybe I would call that flag noResponse.

So you can imagine my surprise when I came across this line:

    respond: function(req, res, next) {
      if (req.noResponse || res.headerSent || res.headersSent) { return next(); }

So I updated my example above to:

router.get '/test4/:key', (req, res, next) ->
    req.noResponse = true
    resj = req.app.resourcejs
    async.waterfall [
        (cb)->
            req.query.key = req.params.key
            resj['/api'].get.call this, req, res, ->
                return cb res.resource.status unless res.resource.status is 200
                cb null, res.resource.item[0]
        (api, cb)->
            req.body =
                key : api.key
                vid : '123'
                mac : '123'
            resj['/verification'].post.call this, req, res, ->
                return cb res.resource.status unless res.resource.status is 201
                cb null, res.resource.item
    ], (err, verification)->
        return res.sendStatus err if err?
        res.render 'verify', title:'verify', vid:verification.vid

And everything worked beautifully. Wonderful.

So now the question is: Who is going to update the readme so all this stuff is actually documented?

@zackurben
Copy link
Contributor

@biofractal hah glad you got things worked out!

If you feel so compelled, you can submit a pr to update the README. Unfortunately I am currently swamped so I cant currently do it myself, but if you dont do it, I'll do it when I catch my breath!

Let me know what you decide.

@zackurben
Copy link
Contributor

@biofractal I just opened 2 issues to help get the ball moving: #15 and #16

I think these are key components of ResourceJS that are currently undocumented, but allow pretty seamless integration with any codebase. Having these documented throughly could ward against simple issues that arise in the future!

@travist
Copy link
Owner

travist commented Jul 9, 2015

I gave both of you access to push to this repo, so whoever does it, the other one can accept the pull request. Thanks for your help.

@zackurben
Copy link
Contributor

@travist thanks, will do!

@biofractal
Copy link
Contributor Author

Added #18 and #17 - I will take those.

@biofractal
Copy link
Contributor Author

Do we want to just create one big readme - or should we be splitting this down wiki-style?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants