Exceptions in the Middleware

316 views
Skip to first unread message

Ali Kheyrollahi

unread,
Jun 23, 2014, 5:20:09 PM6/23/14
to net-http-a...@googlegroups.com
The spec makes it clear that the app can throw exception. However, it does not define that for the Middlewares.

My view is that the middlewares MUST NOT throw exceptions. This might be too strong and I can settle for SHOULD NOT but the point is any unhandled exceptions in the MW will prevent previous MWs to get a chance to intervene.

Real Scenario:

Let's say we want to put correlation Id (just some unique Id to allow debugging through different layers of application) in the response. If the request contains one, it reads the one provided from request and puts that in the response - in headers. This is ideal for a MW. Now if an exception is thrown, MW does not get a chance to do its stuff and the code has to be repeated in the error handler.

Generally I would say it is ILLEGAL for a MW to throw exception. 

scott...@gmail.com

unread,
Jun 23, 2014, 5:46:41 PM6/23/14
to net-http-a...@googlegroups.com

I totally disagree. The host should decide what to do about exceptions. We are discussing the ability for the middleware to trigger a Request.Abort action to end the request and terminate the connection immediately. https://github.com/owin/owin/issues/11

Ali Kheyrollahi

unread,
Jun 23, 2014, 6:03:26 PM6/23/14
to net-http-a...@googlegroups.com
And how are these in contradiction? This is still through a callback delegate not an exception, right?
Exception does not mean anything to anyone. The only case is application exception in which case it needs to be translated to HTTP semantics. 

scott...@gmail.com

unread,
Jun 23, 2014, 6:21:58 PM6/23/14
to net-http-a...@googlegroups.com
Not exactly, to me an exception means "something bad has happened", MW should throw exceptions and the app can decide how to handle the exception. Say you have a piece of MW that checks for a cross-site scripting token. If it doesn't find one, or it finds one that doesn't match, I'd say the MW should throw an exception. Then the app can decide whether to terminate the connection or display a message to the user.

The Request.Abort is more for use in the case of throttling requests or banning an IP from what I can tell. It's a case where the MW wants to tell the app to stop talking to a client right now.

Ali Kheyrollahi

unread,
Jun 24, 2014, 5:04:17 AM6/24/14
to net-http-a...@googlegroups.com
I believe we are defining a spec that could guide the developers to the pit of success.
MW components are HTTP intermediaries as such they need to talk HTTP. Throwing exception is not talking HTTP, it is talking RPC. MW operations are context-specific and there is no way an app could practically cater for all such cases. 

So this is for intended exceptions. For non-intended ones, MW should do their own error handling - they should not rely on app to clean after them. This leads to a better ecosystem and MWs that are responsible. Remember, these are potentially written on top of different framework.

Raising exception might need to happen but SHOULD BE very very rare such as configuration errors.


--
You received this message because you are subscribed to a topic in the Google Groups ".NET HTTP Abstractions" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/net-http-abstractions/OWtGka1qJ1Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to net-http-abstrac...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sebastien Lambla

unread,
Jun 24, 2014, 7:27:13 AM6/24/14
to net-http-a...@googlegroups.com
We’re missing the point of when exceptions are triggered in this conversation.

There is a difference between the resolving of the decorators, aka the wireup phase (app construction) and during request/responses.

At the point where middleware executes the request, it should behave as AppFunc, for post wireup, it is an AppFunc.

The wireup of middlewares is an application concern, not a request/response concern, and should behave in the most natural way for developers to realize the wireup went wrong, aka throw.

You received this message because you are subscribed to the Google Groups ".NET HTTP Abstractions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to net-http-abstrac...@googlegroups.com.

Damian Hickey

unread,
Jun 24, 2014, 8:14:57 AM6/24/14
to net-http-a...@googlegroups.com
> MW components are HTTP intermediaries as such they need to talk HTTP.

I don't agree. They are parts of a .NET pipeline whose final output is HTTP.

I'm with Scott on this. MW should be allowed to throw, with outer MW catching and handling as desired. If MW wants to have full responsibility (i.e. Nancy), that's fine, but I definitely don't want to enforce that. Pragmatically speaking, MW may still throw even if if the MW author did their very best to ensure nothing can go wrong. Indeed why would we want to restrict someone from having a single exception handling top level MW where then can decide how best to respond? 

Have you also considered the situation where an exception may be thrown after the headers have been flushed?
To unsubscribe from this group and all its topics, send an email to net-http-abstractions+unsub...@googlegroups.com.

Tugberk Ugurlu

unread,
Jun 24, 2014, 9:04:27 AM6/24/14
to net-http-a...@googlegroups.com

> MW should be allowed to throw, with outer MW catching and handling as desired.

 

I have a question here though and I am exactly not sure if I’m missing something here: how would the outer MW  know which exception to handle? However, a MW is able to know how to handle 2**, 3**, 4**, 5** responses. In Scott’s cross-site scripting token example, I would prefer the MW to throw 400 instead of an exception. Then, my outer middleware can decide how to handle 400s.

 

However, I also agree that there are cases where you cannot handle that gracefully. So, that’s the actual case where a middleware would take the exception and turns it into 500 because it’s really 500.

 

What do u guys think?

 

Tugberk

To unsubscribe from this group and all its topics, send an email to net-http-abstrac...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

 

--

You received this message because you are subscribed to the Google Groups ".NET HTTP Abstractions" group.

To unsubscribe from this group and stop receiving emails from it, send an email to net-http-abstrac...@googlegroups.com.

Damian Hickey

unread,
Jun 24, 2014, 9:41:03 AM6/24/14
to net-http-a...@googlegroups.com
>  I would prefer the MW to throw 400 instead of an exception. Then, my outer middleware can decide how to handle 400s.

There is nothing stopping you from doing this. By all means, do it.

The proposal is to make it illegal for people to be able to do:

next => env => 
{
  try
  {
  await next(env);
  }
  catch(NotAuthorizedException ex) // Custom exception from *my* app.
  {
  // Set status code etc
  // Depending on useragent / accept header, use a error custom
  // error page or exception serialized as json entity.
                // Whatever, it's my app.
  }
}

I am against the proposal.


Tugberk Ugurlu

unread,
Jun 24, 2014, 9:58:32 AM6/24/14
to net-http-a...@googlegroups.com

I thought the proposal was to make throwing exceptions illegal, not catching:

 

> From Ali: My view is that the middlewares MUST NOT throw exceptions.

 

It kind of has a point where you can gracefully handle the case as it’s in Scott’s example where you can construct a 400 response. However, in cases where it’s out of your control, I’m not sure what is the right thing to do.

Ali Kheyrollahi

unread,
Jun 24, 2014, 11:12:34 AM6/24/14
to net-http-a...@googlegroups.com
 They are parts of a .NET pipeline whose final output is HTTP.

The only way these components communicate together is through the context they pass. And looking at the context will tell us it is an HTTP request/response.

Exception is RPC and is disruptive. As Tugberk said, you could have error formatters downstream that we will disrupt by exception

Honestly, how often would you throw exception?




To unsubscribe from this group and all its topics, send an email to net-http-abstrac...@googlegroups.com.

Mark Rendle

unread,
Jun 24, 2014, 11:39:37 AM6/24/14
to net-http-a...@googlegroups.com
If middleware can't throw exceptions, how are exception tracking systems like Raygun or Exceptionless supposed to work? The outer-most middlewares in my app are a Raygun exception handler that catches Exception, logs it and rethrows it, and an Exception-wrapping middleware that turns certain exceptions into HTTP error information to be returned to the user, and all others into a 500 Internal Server error.

Exceptions are how you report errors in .NET. All .NET code has to be able to throw them.

M

Mark Rendle
Founder, Zudio


--
You received this message because you are subscribed to the Google Groups ".NET HTTP Abstractions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to net-http-abstrac...@googlegroups.com.

Mark Rendle

unread,
Jun 24, 2014, 11:42:42 AM6/24/14
to net-http-a...@googlegroups.com
Honestly, how often would you throw exception?

As often as something exceptional happens. You have no way of knowing what kind of things people are going to do in middleware, so proscribing exceptions is short-sighted and artificially constraining.

The RPC vs HTTP argument is a fallacious analogy. OWIN abstracts away HTTP; once you're into an OWIN pipeline HTTP rules do not apply until you get back to the HTTP server which turns the OWIN response into HTTP.

M

Mark Rendle
Founder, Zudio


You received this message because you are subscribed to the Google Groups ".NET HTTP Abstractions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to net-http-abstrac...@googlegroups.com.

Ali Kheyrollahi

unread,
Jun 24, 2014, 3:07:51 PM6/24/14
to net-http-a...@googlegroups.com
OK, I realise I am in a minority here.

I will say 2 things and cut it off:

1) If this is supposed to take off and adopted by many and be still useful, needs to provide constraints of a good service. Look at HTTP spec and how it advises how to build successful HTTP applications and intermediaries. I want to see robust MWs flourishing and be used not in a way that I could be worried that these MWs could be breaking my application due to poor error handling. Exception MUST be truly an exception, as such I feel we need a line in there = SHOULD NOT. 

2) > The RPC vs HTTP argument is a fallacious analogy.
Really?? This context is all binding these MWs together and yet you think this is not an HTTP pipeline?

I suppose since I do not have an ally (perhaps other than Tugberk) this case is closed - unless someone else has a different opinion.

Ali Kheyrollahi

unread,
Jun 25, 2014, 2:41:19 AM6/25/14
to net-http-a...@googlegroups.com
Now before closing this, we talked a few scenarios where this can be disruptive.

Can you give me only 3 scenarios where a MW will throw an exception, other than configuration issues (as Seb said not during request/response) and serious security breaches.

Mark Rendle

unread,
Jun 25, 2014, 5:03:53 AM6/25/14
to net-http-a...@googlegroups.com
Look, Ali, it's very simple: any middleware that does anything non-trivial is liable to encounter error conditions that it needs to report. The best way for it to report these in an OWIN pipeline is to throw an exception which can then be logged to Raygun or Exceptionless or Airbrake or SLAB or whatever by another piece of middleware further up the pipeline. So prohibiting exceptions effectively prevents proper and efficient error logging. Is that what you want?

Since you asked, here are some examples:

1. Authentication middleware might be unable to access a resource (database, web service, whatever) it needs to perform authentication. This applies to any middleware that depends on an external resource: session, caching, whatever.
2. In-line compiler middleware (e.g. Sass/Less or a JS minifier) could very well encounter an error during compilation.
3. An HTML manipulator such as pagespeed_mod or a Flasher could encounter invalid HTML.

That's three generic examples, for each of which there will hopefully be lots of different variations and implementations in the future.

I could go on (and on), but to save me the time, just go and look at the range of Node.js middleware at https://github.com/senchalabs/connect/wiki and consider all the possible errors that could occur within those for which the only reasonable HTTP response is "500 Internal Server Error", because all of those should be throwing exceptions in an OWIN pipeline.

So, can we please put this one to sleep now?

Mark

Mark Rendle
Founder, Zudio

Mark Rendle

unread,
Jun 25, 2014, 5:06:43 AM6/25/14
to net-http-a...@googlegroups.com
Oh, we're doing bold now, are we? OK then: It is not an HTTP pipeline because the communication between components in the pipeline is not constrained by the HTTP standards, it is using an IDictionary<string, object> context object which can have literally anything stuck in it.

Mark Rendle
Founder, Zudio

Garry Shutler

unread,
Jun 25, 2014, 5:23:08 AM6/25/14
to net-http-abstractions
Long time lurker *waves*

The entire concept of never being able to throw an exception whilst handling a request is quite frankly hilarious.

If that were to be a specified constraint you'd be insisting on every middleware having a try-catch(Exception) block. At that point it would be sensible for the spec to change for the host to take that boilerplate burden off the implementor and wrap every middleware call to do that for them. Then you'd end up in a situation where the middleware could legitimately throw anyway!

So should middlewares be able to throw? Yes. The question is more whether exceptions are valid flow control between middlewares, and I think Mark has outlined well why they are.

Ali Kheyrollahi

unread,
Jun 25, 2014, 6:25:32 AM6/25/14
to net-http-a...@googlegroups.com
Cool down guys. 
Mark, we have different opinions but if discussing it causing you to frustrate, happy to completely pull out.
My point was, if I have multiple MWs that need to work regardless of the success of the request (one that adds a unique correlation Id, one that calculates how long a request has taken, one that does tracing, one that formats the HTTP errors in a consistent way, one that adds special headers) how do we ensure these MWs are all triggered. 

But well, I think this case is closed.


Sebastien Lambla

unread,
Jun 25, 2014, 7:06:25 AM6/25/14
to net-http-a...@googlegroups.com
Bugs, impossible conditions, IO. Enforcing no exception would force anyone doing IO to wrap try catch everywhere, catch everything and all return their own 500s.

Mark Rendle

unread,
Jun 25, 2014, 7:27:00 AM6/25/14
to net-http-a...@googlegroups.com
My point was, if I have multiple MWs that need to work regardless of the success of the request (one that adds a unique correlation Id, one that calculates how long a request has taken, one that does tracing, one that formats the HTTP errors in a consistent way, one that adds special headers) how do we ensure these MWs are all triggered.

Those middlewares need to decide on a use-case basis whether they are still relevant in the case of an exception further down the line, and if they are, they need to use try/catch or try/finally blocks. Many of them won't be relevant (e.g. compressors and other response modifiers).

We should add something (non-normative?) to the spec, or to the guidelines for middleware authors, saying as much.

M

P.S. Sorry if I was rude, I'm in the middle of a hypomanic episode and it affects my ability to interact with people.


Mark Rendle
Founder, Zudio
Reply all
Reply to author
Forward
0 new messages