You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by Dmitry Potapov <po...@gmail.com> on 2014/10/06 09:35:00 UTC

Three different HttpContext in HttpAsyncService

Hello everyone,

Until today I was under a misapprehension that there is single HttpContext
travels across handlers and callbacks during request processing. Today I've
discovered that during single request processing HttpAsyncService can operate
with three different HttpContext:
 1. BasicHttpContext created in .requestReceived(). This context will have
    HTTP_RESPONSE and HTTP_CONNECTION attributes.
 2. BasicHttpContext created in .exception(). In case of HttpException thrown
    from HttpAsyncRequestHandler.handle() function, this context will be empty.
 3. SessionHttpContext created by NHttpConnectionBase.setSession(). This
    context will be passed to ConnectionReuseStrategy.keepAlive() and will have
    HTTP_CONNECTION set, but no HTTP_RESPONSE.

Is this contexts separation is intentional and there are some reasons to have
them separated and containing different set off attributes?
As for me, it seems reasonable to use NHttpConnection.getContext() in all three
cases listed above. Which pitfalls I'm missing here?

-- 
Best regards,
Dmitry Potapov

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2014-10-07 at 13:52 +0400, Dmitry Potapov wrote:
> On Tue, Oct 07, 2014 at 09:43:35AM +0200, Oleg Kalnichevski wrote:
> > On Mon, 2014-10-06 at 19:42 +0400, Dmitry Potapov wrote:
> > > On Mon, Oct 06, 2014 at 03:49:42PM +0200, Oleg Kalnichevski wrote:
> > > > Could you please put together a test case demonstrating such execution
> > > > path?
> > > Here it is: https://gist.github.com/hirthwork/45a45702a112c14b041d
> > > 
> > > I've modified NHttpFileServer example a bit, so it will throw ProtocolException
> > > if file not found.
> > > At the start of execution I'm putting timestamp into context using
> > > HttpRequestInterceptor and in ConnectionKeepAlive strategy tries to get request
> > > and timestamp from context.
> > > Everything works fine if there was no exception (context is the same as one
> > > passed to http processor).
> > > In case of exception original context is lost, so it will contain only response
> > > object.
> > > 
> > 
> > I see the problem now. If we want to support propagation of the current
> > context to the HttpAsyncService#exception method I do not see a way
> > around storing it in the State object.
> > 
> > Would you like to put together a patch?
> For now, I don't see good place where state.setContext(null) should be called.
> So, this solutions doesn't seems good to me.
> 
> I have another suggestion: in case of exception in request handler, new
> PipelineEntry with null result can be created and .responseReady(conn) can be
> called again. This solution is not ideal, but it seems to be much better than
> storing context somewhere else. Please, take a look at the attached patch.
> > 

Look pretty good to me. Please create a pull request at GitHub.

Oleg



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Dmitry Potapov <po...@gmail.com>.
On Tue, Oct 07, 2014 at 09:43:35AM +0200, Oleg Kalnichevski wrote:
> On Mon, 2014-10-06 at 19:42 +0400, Dmitry Potapov wrote:
> > On Mon, Oct 06, 2014 at 03:49:42PM +0200, Oleg Kalnichevski wrote:
> > > Could you please put together a test case demonstrating such execution
> > > path?
> > Here it is: https://gist.github.com/hirthwork/45a45702a112c14b041d
> > 
> > I've modified NHttpFileServer example a bit, so it will throw ProtocolException
> > if file not found.
> > At the start of execution I'm putting timestamp into context using
> > HttpRequestInterceptor and in ConnectionKeepAlive strategy tries to get request
> > and timestamp from context.
> > Everything works fine if there was no exception (context is the same as one
> > passed to http processor).
> > In case of exception original context is lost, so it will contain only response
> > object.
> > 
> 
> I see the problem now. If we want to support propagation of the current
> context to the HttpAsyncService#exception method I do not see a way
> around storing it in the State object.
> 
> Would you like to put together a patch?
For now, I don't see good place where state.setContext(null) should be called.
So, this solutions doesn't seems good to me.

I have another suggestion: in case of exception in request handler, new
PipelineEntry with null result can be created and .responseReady(conn) can be
called again. This solution is not ideal, but it seems to be much better than
storing context somewhere else. Please, take a look at the attached patch.
> 
> Oleg   
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> For additional commands, e-mail: dev-help@hc.apache.org
> 

Re: Three different HttpContext in HttpAsyncService

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Mon, 2014-10-06 at 19:42 +0400, Dmitry Potapov wrote:
> On Mon, Oct 06, 2014 at 03:49:42PM +0200, Oleg Kalnichevski wrote:
> > Could you please put together a test case demonstrating such execution
> > path?
> Here it is: https://gist.github.com/hirthwork/45a45702a112c14b041d
> 
> I've modified NHttpFileServer example a bit, so it will throw ProtocolException
> if file not found.
> At the start of execution I'm putting timestamp into context using
> HttpRequestInterceptor and in ConnectionKeepAlive strategy tries to get request
> and timestamp from context.
> Everything works fine if there was no exception (context is the same as one
> passed to http processor).
> In case of exception original context is lost, so it will contain only response
> object.
> 

I see the problem now. If we want to support propagation of the current
context to the HttpAsyncService#exception method I do not see a way
around storing it in the State object.

Would you like to put together a patch?

Oleg   




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Dmitry Potapov <po...@gmail.com>.
On Mon, Oct 06, 2014 at 03:49:42PM +0200, Oleg Kalnichevski wrote:
> Could you please put together a test case demonstrating such execution
> path?
Here it is: https://gist.github.com/hirthwork/45a45702a112c14b041d

I've modified NHttpFileServer example a bit, so it will throw ProtocolException
if file not found.
At the start of execution I'm putting timestamp into context using
HttpRequestInterceptor and in ConnectionKeepAlive strategy tries to get request
and timestamp from context.
Everything works fine if there was no exception (context is the same as one
passed to http processor).
In case of exception original context is lost, so it will contain only response
object.

-- 
Best regards,
Dmitry Potapov

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Mon, 2014-10-06 at 17:22 +0400, Dmitry Potapov wrote:
> > On 06 окт. 2014 г., at 16:36, Oleg Kalnichevski <ol...@apache.org> wrote:
> > 
> >> On Mon, 2014-10-06 at 15:18 +0400, Dmitry Potapov wrote:
> >>> On Mon, Oct 06, 2014 at 11:19:12AM +0200, Oleg Kalnichevski wrote:
> >>> On Mon, 2014-10-06 at 11:35 +0400, Dmitry Potapov wrote:
> > 
> > ...
> > 
> >>> 
> >>> Point (2) is really a fringe case intended to ensure there is a context
> >>> of _some_ sort even in case an exception is caught before the session is
> >>> fully set up.
> >> So, here the focal point of my efforts. In case of complete request consumption
> >> setIncoming will be called with null argument and request context will be moved
> >> to pipeline entry. Right before request handling pipeline entry will be polled
> >> from queue, so, no global references to request context will left. So, there is
> >> no way how HttpAsyncService.handleException() or
> >> ConnectionReuseStrategy.keepAlive() can receive actual request context.
> >> The question is: how to extend request context lifetime?
> > 
> > The request and the context associated with it are still present in the
> > request pipeline, aren't they? If there is no incoming request and the
> > pipeline contains one entry only it should be safe to assume that entry
> > be the actual request.
> > 
> >> For now the only solution I see is to store context somewhere else, like State,
> >> for instance. But this doesn't seems to be a good solution. Will think on this
> >> a bit more.
> >> Please, let me know if you have any good ideas where context can be stored.
> >> 
> > 
> > Why not taking it from the pipeline?
> Pipeline queue will be empty in .exception() function, because pipeline entry will be polled from queue right before calling handler.handle(...)

Dmitry

Could you please put together a test case demonstrating such execution
path?

Oleg 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Dmitry Potapov <po...@gmail.com>.
> On 06 окт. 2014 г., at 16:36, Oleg Kalnichevski <ol...@apache.org> wrote:
> 
>> On Mon, 2014-10-06 at 15:18 +0400, Dmitry Potapov wrote:
>>> On Mon, Oct 06, 2014 at 11:19:12AM +0200, Oleg Kalnichevski wrote:
>>> On Mon, 2014-10-06 at 11:35 +0400, Dmitry Potapov wrote:
> 
> ...
> 
>>> 
>>> Point (2) is really a fringe case intended to ensure there is a context
>>> of _some_ sort even in case an exception is caught before the session is
>>> fully set up.
>> So, here the focal point of my efforts. In case of complete request consumption
>> setIncoming will be called with null argument and request context will be moved
>> to pipeline entry. Right before request handling pipeline entry will be polled
>> from queue, so, no global references to request context will left. So, there is
>> no way how HttpAsyncService.handleException() or
>> ConnectionReuseStrategy.keepAlive() can receive actual request context.
>> The question is: how to extend request context lifetime?
> 
> The request and the context associated with it are still present in the
> request pipeline, aren't they? If there is no incoming request and the
> pipeline contains one entry only it should be safe to assume that entry
> be the actual request.
> 
>> For now the only solution I see is to store context somewhere else, like State,
>> for instance. But this doesn't seems to be a good solution. Will think on this
>> a bit more.
>> Please, let me know if you have any good ideas where context can be stored.
>> 
> 
> Why not taking it from the pipeline?
Pipeline queue will be empty in .exception() function, because pipeline entry will be polled from queue right before calling handler.handle(...)
> Oleg
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> For additional commands, e-mail: dev-help@hc.apache.org
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Mon, 2014-10-06 at 15:18 +0400, Dmitry Potapov wrote:
> On Mon, Oct 06, 2014 at 11:19:12AM +0200, Oleg Kalnichevski wrote:
> > On Mon, 2014-10-06 at 11:35 +0400, Dmitry Potapov wrote:

...

> > 
> > Point (2) is really a fringe case intended to ensure there is a context
> > of _some_ sort even in case an exception is caught before the session is
> > fully set up.
> So, here the focal point of my efforts. In case of complete request consumption
> setIncoming will be called with null argument and request context will be moved
> to pipeline entry. Right before request handling pipeline entry will be polled
> from queue, so, no global references to request context will left. So, there is
> no way how HttpAsyncService.handleException() or
> ConnectionReuseStrategy.keepAlive() can receive actual request context.
> The question is: how to extend request context lifetime?

The request and the context associated with it are still present in the
request pipeline, aren't they? If there is no incoming request and the
pipeline contains one entry only it should be safe to assume that entry
be the actual request.

> For now the only solution I see is to store context somewhere else, like State,
> for instance. But this doesn't seems to be a good solution. Will think on this
> a bit more.
> Please, let me know if you have any good ideas where context can be stored.
> 

Why not taking it from the pipeline?

Oleg



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Dmitry Potapov <po...@gmail.com>.
On Mon, Oct 06, 2014 at 11:19:12AM +0200, Oleg Kalnichevski wrote:
> On Mon, 2014-10-06 at 11:35 +0400, Dmitry Potapov wrote:
> > Hello everyone,
> > 
> > Until today I was under a misapprehension that there is single HttpContext
> > travels across handlers and callbacks during request processing. Today I've
> > discovered that during single request processing HttpAsyncService can operate
> > with three different HttpContext:
> >  1. BasicHttpContext created in .requestReceived(). This context will have
> >     HTTP_RESPONSE and HTTP_CONNECTION attributes.
> >  2. BasicHttpContext created in .exception(). In case of HttpException thrown
> >     from HttpAsyncRequestHandler.handle() function, this context will be empty.
> >  3. SessionHttpContext created by NHttpConnectionBase.setSession(). This
> >     context will be passed to ConnectionReuseStrategy.keepAlive() and will have
> >     HTTP_CONNECTION set, but no HTTP_RESPONSE.
> > 
> > Is this contexts separation is intentional and there are some reasons to have
> > them separated and containing different set off attributes?
> > As for me, it seems reasonable to use NHttpConnection.getContext() in all three
> > cases listed above. Which pitfalls I'm missing here?
> > 
> 
> Dmitry
> 
> HTTP sessions can span across multiple connections (this is especially
> applicable to the client side where it is pretty common) and the same
> persistent connection can be used by multiple logical sessions. So,
> HttpCore attempts to maintain a clear distinction between connection
> contexts and execution contexts, which are often not the same. 
OK, I got it. The separation between connection context and request context is
not clear to me.

> 
> Point (2) is really a fringe case intended to ensure there is a context
> of _some_ sort even in case an exception is caught before the session is
> fully set up.
So, here the focal point of my efforts. In case of complete request consumption
setIncoming will be called with null argument and request context will be moved
to pipeline entry. Right before request handling pipeline entry will be polled
from queue, so, no global references to request context will left. So, there is
no way how HttpAsyncService.handleException() or
ConnectionReuseStrategy.keepAlive() can receive actual request context.
The question is: how to extend request context lifetime?
For now the only solution I see is to store context somewhere else, like State,
for instance. But this doesn't seems to be a good solution. Will think on this
a bit more.
Please, let me know if you have any good ideas where context can be stored.

> 
> Point (3) sounds like a bug to me. However, it does not seem to be the
> case in the latest revisions of trunk and 4.3.x. If I missed something
> please do let me know or, better yet, submit a pull request ;-)
This is my bug, sorry. I have worked on dirty trunk after trying to fix (2).
> 
> Oleg 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
> For additional commands, e-mail: dev-help@hc.apache.org
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Re: Three different HttpContext in HttpAsyncService

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Mon, 2014-10-06 at 11:35 +0400, Dmitry Potapov wrote:
> Hello everyone,
> 
> Until today I was under a misapprehension that there is single HttpContext
> travels across handlers and callbacks during request processing. Today I've
> discovered that during single request processing HttpAsyncService can operate
> with three different HttpContext:
>  1. BasicHttpContext created in .requestReceived(). This context will have
>     HTTP_RESPONSE and HTTP_CONNECTION attributes.
>  2. BasicHttpContext created in .exception(). In case of HttpException thrown
>     from HttpAsyncRequestHandler.handle() function, this context will be empty.
>  3. SessionHttpContext created by NHttpConnectionBase.setSession(). This
>     context will be passed to ConnectionReuseStrategy.keepAlive() and will have
>     HTTP_CONNECTION set, but no HTTP_RESPONSE.
> 
> Is this contexts separation is intentional and there are some reasons to have
> them separated and containing different set off attributes?
> As for me, it seems reasonable to use NHttpConnection.getContext() in all three
> cases listed above. Which pitfalls I'm missing here?
> 

Dmitry

HTTP sessions can span across multiple connections (this is especially
applicable to the client side where it is pretty common) and the same
persistent connection can be used by multiple logical sessions. So,
HttpCore attempts to maintain a clear distinction between connection
contexts and execution contexts, which are often not the same. 

Point (2) is really a fringe case intended to ensure there is a context
of _some_ sort even in case an exception is caught before the session is
fully set up.

Point (3) sounds like a bug to me. However, it does not seem to be the
case in the latest revisions of trunk and 4.3.x. If I missed something
please do let me know or, better yet, submit a pull request ;-)

Oleg 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org