grape icon indicating copy to clipboard operation
grape copied to clipboard

Support aborting requests via a Rack::Response#finish

Open elliotlarson opened this issue 10 years ago • 6 comments

I have a post endpoint where I'd like to conditionally return a custom Rack::Response, like so:

post do
  if some_condition?
    hash_of_contextually_relevant_goodness = { foo: 'bar' }
    Rack::Response.new(
      [hash_of_contextually_relevant_goodness], 
      418, 
      { 'Content-Type' => 'application/json' }
    ).finish
  else
    # do some object creation stuff
  end
end

However, this returns the following response body:

[
    418,
    {
        "Content-Length": "13",
        "Content-Type": "application/json"
    },
    {
        "block": {},
        "body": {
            "block": null,
            "body": [
                "{:foo=>\"bar\"}"
            ],
            "chunked": false,
            "header": {
                "Content-Length": "13",
                "Content-Type": "application/json"
            },
            "length": 13,
            "status": 418,
            "writer": {}
        },
        "closed": false
    }
]

It looks like the response is doubling up. What is the correct way to return a custom Rack::Response from my endpoint?

elliotlarson avatar Oct 22 '15 18:10 elliotlarson

The problem is that it's going through a formatter. Before we figure out how to shortcut Grape in this case, I bet you can solve this by just doing status 418 and returning [hash_of...] as is. No?

dblock avatar Oct 22 '15 21:10 dblock

Ah, fantastic! Yes, that totally works.

Thank you.

elliotlarson avatar Oct 22 '15 21:10 elliotlarson

I've renamed this to "Support aborting requests via a Rack::Response.finish`, and labeled this as a feature. I am not sure we want this, but it's a valid thing.

dblock avatar Oct 22 '15 21:10 dblock

Right, it seems like it would be "a valid thing". I kind of assumed you could just circumvent the Grape response with your own Rack::Response. However, your suggestion solves the one use case where I wanted to do this. I can't really think of another use case.

elliotlarson avatar Oct 22 '15 22:10 elliotlarson

@dblock Would be good to Grape handle it. We have a use case where Grape works as a Gateway forwarding the request to another Service and having it like:

route :any, '*service_path' do
  forward(request)
end

seems cleaner than:

route :any, '*service_path' do
  response = forward(request)

  response.headers.each { |k, v| header k, v }
  status response.status
  body   response.body.first
end

danillos avatar Aug 06 '19 11:08 danillos

I see, @danillos open to PRs.

dblock avatar Aug 07 '19 16:08 dblock