Better status code for Rack::Cascade

19 views
Skip to first unread message

Josh Peek

unread,
Jan 28, 2009, 5:50:10 PM1/28/09
to Rack Development
There are many complaints about 404 being used as the status code to
continue down the rack cascade. Like "what if you want to return a
true 404". It seems like there should be a more appropriate status
code for this.

Yehuda Katz recommend "417 Expectation Failed"

Yehuda Katz

unread,
Jan 28, 2009, 5:54:15 PM1/28/09
to rack-...@googlegroups.com
Just a quick excerpt from the spec:

The expectation given in an Expect request-header field (see section 14.20) could not be met by this server, or, if the server is a proxy, the server has unambiguous evidence that the request could not be met by the next-hop server.

I think we should be treating Rack middleware, for the purpose of the HTTP spec, as a proxy. In that context, 417 is the right error code.

-- Yehuda
--
Yehuda Katz
Developer | Engine Yard
(ph) 718.877.1325

Matt Todd

unread,
Jan 28, 2009, 6:14:03 PM1/28/09
to rack-...@googlegroups.com
+1
--
Matt Todd
Highgroove Studios
www.highgroove.com
cell: 404-314-2612
blog: maraby.org

Scout - Web Monitoring and Reporting Software
www.scoutapp.com

Christian Neukirchen

unread,
Jan 28, 2009, 6:42:10 PM1/28/09
to rack-...@googlegroups.com
Josh Peek <jo...@joshpeek.com> writes:

Rack::Cascade is a hack that probably should be avoided. I use 404
because then you can layer apps that were not written for use with
Cascade in mind (you can easily override the statuses).

--
Christian Neukirchen <chneuk...@gmail.com> http://chneukirchen.org

Yehuda Katz

unread,
Jan 28, 2009, 6:52:13 PM1/28/09
to rack-...@googlegroups.com
I think that middleware should be considered proxies and return 417 if they know that the next-hop can't return a useful value. The problem with using 404 is that it makes it impossible to return an *actual* 404.

-- Yehuda

Jeremy Kemper

unread,
Jan 28, 2009, 7:35:34 PM1/28/09
to rack-...@googlegroups.com
On Wed, Jan 28, 2009 at 3:52 PM, Yehuda Katz <wyc...@gmail.com> wrote:
> I think that middleware should be considered proxies and return 417 if they
> know that the next-hop can't return a useful value. The problem with using
> 404 is that it makes it impossible to return an *actual* 404.

The problem with using any HTTP status is that it makes it impossible
to return that status.

As long as middlewares must return a special response, how about using
Ruby programming instead (like throw/catch) instead of an HTTP
convention?

jeremy

Ezra Zygmuntowicz

unread,
Jan 28, 2009, 7:38:23 PM1/28/09
to rack-...@googlegroups.com

Or take a clue form raggi's async rack stuff and return a negative
number for status that means cascade so it will never conflict with
any real http status codes.

Cheers-
-Ezra

Daniel N

unread,
Jan 28, 2009, 8:27:15 PM1/28/09
to rack-...@googlegroups.com

+1 on not using any http status code.  even a symbol would be good, although rack would eventually have to deal with that if it were the last in the chain.

 

Scytrin dai Kinthra

unread,
Jan 28, 2009, 8:48:26 PM1/28/09
to rack-...@googlegroups.com
I'd argue with not using Rack::Cascade with the default catch codes
unless you're specifically looking for a fall over solution. Like
Rack::File first and then default to your app to create and return the
static file or do another type of dynamic request.

Alternately, I could see a 417 being an appropriate type of default
catch code. I like the idea of Rack middle ware treated as interal
proxies.

--
stadik.net

Matt Todd

unread,
Jan 28, 2009, 9:06:10 PM1/28/09
to rack-...@googlegroups.com
417 is an acceptable HTTP response code to use, but if we decide that cascading should be done without these, I think an Exception should be raised. If an endpoint doesn't know how to do something that is expected of it, I believe that an exception is appropriate. An HTTP response code is just a way of communicating exceptional state, correct?

Matt

James Tucker

unread,
Jan 29, 2009, 5:38:22 AM1/29/09
to rack-...@googlegroups.com

On 29 Jan 2009, at 02:06, Matt Todd wrote:

> 417 is an acceptable HTTP response code to use, but if we decide
> that cascading should be done without these, I think an Exception
> should be raised. If an endpoint doesn't know how to do something
> that is expected of it, I believe that an exception is appropriate.
> An HTTP response code is just a way of communicating exceptional
> state, correct?
>
> Matt

The reason I eventually settled on -1 for async stuff is in several
parts:

- Ruby will very likely never have an unsigned numeric type.
- HTTP Status codes will very likely never become signed numerals.
- Using actual HTTP status codes, appropriate or not, stops them
from being used in a 'regular' manner from an application.

I was using HTTPs CONTINUE originally, to prevent http servers from
doing a terminate response and close connection.

The problem is, there are some situations (mostly proxy related) where
an app genuinely wants to send a 100 out. Sure, none of the OSS stuff
I've seen uses this, but someone on this ML does.

Matt Todd

unread,
Jan 29, 2009, 11:15:06 AM1/29/09
to rack-...@googlegroups.com
class PotentialEndpoint
  def self.call(env)
    if env["PATH_INFO"] =~ PATTERN
      [200, {"Content-Type" => "text/plain"}, []]
    else
      raise Pass
    end
  end
end

A better name for the exception would of course be preferred.

Thoughts?

Matt



Nicolás Sanguinetti

unread,
Jan 29, 2009, 11:18:45 AM1/29/09
to rack-...@googlegroups.com
Rack::Next? (thinking of the `next` keyword to skip the current
iteration in a loop)

Rack::PassThru, Rack::Skip, Rack::MiddlewareSkippingFactoryFactoryFactory ?

Magnus Holm

unread,
Jan 29, 2009, 11:19:13 AM1/29/09
to rack-...@googlegroups.com
Why not a "throw :pass"? Do we need the backtrace an exception would generate (which also is quite expensive)?

//Magnus Holm

Joshua Peek

unread,
Jan 29, 2009, 11:19:52 AM1/29/09
to rack-...@googlegroups.com
The nice thing about returning an actual status code is that the
endpoint can be used standalone. You don't have to design a special
"potential endpoint".

Matt Todd

unread,
Jan 29, 2009, 11:33:40 AM1/29/09
to rack-...@googlegroups.com
This is why the 404 makes sense... if you take the app out of the Cascade cycle then you'd actually want it to return 404 Not Found...

Perhaps we could use a header like rack.cascade.passthru and automatically set it to true unless it's already set in the response hash (which, in this case, it would be false nearly 100% of the time)... then cascade can decide whether to treat the 404 as a passthrough or an actual 404. Cascade can also remove all traces of rack.cascade.passthru from the response.

Thoughts?

Matt

James Tucker

unread,
Jan 29, 2009, 12:22:12 PM1/29/09
to rack-...@googlegroups.com

On 29 Jan 2009, at 16:19, Magnus Holm wrote:

> Why not a "throw :pass"? Do we need the backtrace an exception would
> generate (which also is quite expensive)?
>
> //Magnus Holm

When I benched this, the difference between unrolling a stack via
throw and via an exception is comparable.

IMO both are not acceptable for flow control.

James Tucker

unread,
Jan 29, 2009, 12:23:54 PM1/29/09
to rack-...@googlegroups.com

class App
  def call(env)
    return [env['rack.cascade.code'], {}, []] unless can_service?(env)
  end
end

Matt Todd

unread,
Jan 29, 2009, 1:17:42 PM1/29/09
to rack-...@googlegroups.com
class App
  def call(env)
    return [env['rack.cascade.code'], {}, []] unless can_service?(env)
  end
end

+1

One improvement would be to change it to env['rack.unserviceable.code'] or something which would be 404 normally but then Cascade would change this to -1 or whatever and handle it internally.

Matt

Yehuda Katz

unread,
Jan 29, 2009, 2:10:58 PM1/29/09
to rack-...@googlegroups.com
Again, I'd like to put forth for consideration the idea that Rack middleware is effectively a proxy. In that context, returning a 417 makes perfect sense and isn't going to conflict with a real app (an *application* should never return a 417).

-- Yehuda

James Tucker

unread,
Jan 30, 2009, 5:27:25 AM1/30/09
to rack-...@googlegroups.com
On 29 Jan 2009, at 19:10, Yehuda Katz wrote:

Again, I'd like to put forth for consideration the idea that Rack middleware is effectively a proxy. In that context, returning a 417 makes perfect sense and isn't going to conflict with a real app (an *application* should never return a 417).

As I said, this prevents real proxying style operations to be used simply from within a rack application. This is the same story as I went through with using HTTP 100 Continue for the async stuff.

On Thu, Jan 29, 2009 at 10:17 AM, Matt Todd <chio...@gmail.com> wrote:

One improvement would be to change it to env['rack.unserviceable.code'] or something which would be 404 normally but then Cascade would change this to -1 or whatever and handle it internally.

Anything other than -1 would be great, at the moment we're using that in the async api.

Daniel N

unread,
Feb 4, 2009, 6:17:22 PM2/4/09
to rack-...@googlegroups.com

Hey Guys,

Did we end up coming up for anything here?  I think this is really important to get right, and any use of http codes limits the ability of a rack app to fully utilize HTTP.

I'd really like to get a decision on this one if we can get there.

Cheers
Daniel

Scytrin dai Kinthra

unread,
Feb 8, 2009, 11:34:11 PM2/8/09
to rack-...@googlegroups.com
I'd suggest adding a ticket to
http://rack.lighthouseapp.com/projects/22435-rack/overview if the
issue is pressing.

--
stadik.net

Reply all
Reply to author
Forward
0 new messages