GithubHelp home page GithubHelp logo

Comments (4)

kahmali avatar kahmali commented on June 27, 2024

Thank you very much for the kind words!

I think there may be two separate issues here (one on Restivus' end, and one on yours). I definitely intend for users to be able to handle the [low-level responses] with this.response themselves, but you are correct that there is a bug that would prevent this from happening. Let's address that first.

"Could there be a parameter that would indicate that method will not return anything and will take care of ending the response?

Restivus logs following error:

TypeError: Cannot read property 'body' of null at [object Object].Router.route.action (packages/nimble:restivus/lib/route.coffee:53:24)"

I can't think of any clean way to use a parameter in the endpoint to cause Restivus to ignore the data returned from the endpoint. If you have any suggestions (preferably with some example code), I would love to hear them. I think there may be an acceptable way around this though.

As it stands, returning null from an endpoint is treated as an error. My thought there was that something should always be returned from a REST endpoint. Of course, that was an oversight, since a user handling the low-level response should be able to return their own data and prevent Restivus from attempting to send another response, causing an error (as you suggested). Intuitively, you would think to just return null in that situation (as you did), since you've already handled the response, and after giving it some thought I think that's the right way to go.

Handling the null response instead of treating it like an error was quite straight forward, and I've already implemented and tested that on a local branch. This allows you to handle the response manually with this.response. Now, when an endpoint returns null, Restivus ensures the connection is closed and does not attempt to send any response of it's own. I even added a helper function to the endpoint context to make this look a little cleaner: this.end() (all it does is return null, but it looks a bit nicer and better declares your intention). I think it would be suitable for your needs as is, but there are still a few things to consider before publishing an update.

Right now I'm in the process of implementing some pretty handy response hooks (to allow you to call functions at predefined points before, during, and after execution of your endpoints), and one of the hooks is the onBeforeResponse(data) hook, which I would lose control over if users handled the response from within their endpoint (by calling this.response.write()). I've thought about this some and I just don't see a clean way to avoid this. Supporting the automated hook would require me to break up every endpoint action and it's response (so I could call the hook in between), which would introduce unnecessary complexity to the Restivus API. The only reasonable solution I've come up with is simply canceling my own attempt to call the hook whenever the response has already been initiated within the endpoint (I can check that with this.response.headersSent, which returns true once this.response.write() has been called). That means the user would be required to call the onBeforeResponse hook manually before beginning their response if they want the hook to be called from that endpoint with its intended behavior. If I don't cancel the hook on my end, it would have inconsistent behavior (sometimes being called after the response), and I couldn't sleep well at night if that were the case. If losing the automated endpoint hook seems like an acceptable tradeoff to you, let me know. Otherwise, if you have any suggestions on how to better handle this please let me know.

I've left it so that returning undefined from an endpoint is still an error. Is that confusing? I'm a little weary of just closing the connection when null or undefined are returned. I think that would mask errors in the REST API. I think I would prefer to continue to treat undefined as an error. What I can do is to return a more specific error there, instead of just letting the error fall through.

That was a lot to take in, but that covers the issues being caused by Restivus. As for the issue on your end:

  Restivus.addRoute 'test', { authRequired: false }, get: ->
    _this = @
    _this.response.write("test1")
    setTimeout(->
      _this.response.write("test")
      _this.response.end()
    , 1000)
    return null

"The above code writes "test1" to the client, but not "test", probably as restivus has already closed the connection."

The reason that "test" is not returned is because setTimeout() is asynchronous and your endpoint function will always return before the asynchronous callback function runs. Meteor has first- and third-party options for solving this issue. Please check out my response to Issue #11 for a detailed explanation of how to resolve this.

I will push these changes up soon for you to test out. I'll keep you posted. Let me know if any of that was unclear, or if you have any other questions or suggestions.

from meteor-restivus.

kahmali avatar kahmali commented on June 27, 2024

Sorry for not publishing this update yet. I wasn't really happy with simply returning null from an endpoint to indicate that the response had been handled manually. Returning null may be done by accident, and in that case the response would be sent back with an empty body and no indication of any error. Instead, I would prefer to continue to treat a null return value as an error. I spoke with @anthonyreid99 and we came up with a much cleaner solution. I won't bore you with the details just yet, but I should be able to implement it within the next few days and get this update out. The API should be very close to the one proposed here. I'll keep you posted. Sorry about the delay on this.

from meteor-restivus.

kahmali avatar kahmali commented on June 27, 2024

Sorry about all of those commit references. Just had to rebase a bunch to get the markdown right for the docs. Forgot that I had referenced the issue.

Anywho, the latest release, v0.6.3 (along with my suggestions above) should fix this issue. I added a section to the docs to explain how to handle the response manually from within your endpoints. The only difference is that you just need to call this.done() after you're done handling the response, and Restivus won't get in your way anymore.

Please let me know if you have any other questions or issues. Thank you for taking the time to report this!

from meteor-restivus.

blaind avatar blaind commented on June 27, 2024

Thank you!

from meteor-restivus.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.