You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Todd W Lainhart <la...@us.ibm.com> on 2014/10/14 17:37:56 UTC

HttpContext and RequestConfig

HttpClient 4.3.5 / HttpCore 4.3.2

I've got an execution context, that while appears to be a single 
call/response to the caller, can result in multiple network calls - 
multiple CloseableHttpClient.execute(...) invocations.  Those invocations 
share HttpContext state, mainly for a shared cookie store.  The 
CloseableHttpClient has a  custom RequestConfig associated to it.

One of the invocations creates a new HttpRequest object, with its own 
RequestConfig that overrides the default.  On subsequent invocations I was 
surprised to see that the RequestConfig that I set on the request became 
the shared HttpContext's RequestConfig state, which is used in subsequent 
invocations.  Reading the source confirms this - the request's config is 
set on the "local context", which is the shared context I mentioned 
earlier.

Is this the intended behavior?  I can see it both ways.

I can work around this by clearing the request config on the context on 
that one call, but I wanted to raise the question in case I'm missing a 
concept.  I'm also not finding a "clone" or "copy" of a context, which I 
thought I had seen at one point.





Todd Lainhart
Rational software
IBM Corporation
550 King Street, Littleton, MA 01460-1250
1-978-899-4705
2-276-4705 (T/L)
lainhart@us.ibm.com

Re: HttpContext and RequestConfig

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Wed, 2014-10-15 at 10:50 -0400, Todd W Lainhart wrote:
> Thanks Oleg -
> 
> Unless I'm missing something, I was thinking that it had to be something 
> along these lines:
> 
>             /*
>              * Disable redirection for this one POST request
>              */
>             RequestConfig oldConfig = context.getRequestConfig();
>             RequestConfig newConfig = RequestConfig.custom
> ().setRedirectsEnabled(false).build();
>             context.setRequestConfig(newConfig);
>  
>             try {
>                 response = httpClient.execute(targetHost, postMethod, 
> context);
>             } finally {
>                 context.setRequestConfig(oldConfig);
>             }
>  

That certainly works, too. 

Oleg


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


Re: HttpContext and RequestConfig

Posted by Todd W Lainhart <la...@us.ibm.com>.
Thanks Oleg -

Unless I'm missing something, I was thinking that it had to be something 
along these lines:

            /*
             * Disable redirection for this one POST request
             */
            RequestConfig oldConfig = context.getRequestConfig();
            RequestConfig newConfig = RequestConfig.custom
().setRedirectsEnabled(false).build();
            context.setRequestConfig(newConfig);
 
            try {
                response = httpClient.execute(targetHost, postMethod, 
context);
            } finally {
                context.setRequestConfig(oldConfig);
            }
 



> 
> Well, in the worst case would this do the trick?
> ---
> class MyHttpContext implements HttpContext {
> 
>     private final HttpContext context;
>     private RequestConfig requestConfig;
> 
>     public MyHttpContext(final HttpContext context) {
>         super();
>         this.context = Args.notNull(context, "HTTP context");
>     }
> 
>     public Object getAttribute(final String id) {
>         if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
>             if (this.requestConfig != null) {
>                 return this.requestConfig;
>             } else {
>                 return this.context.getAttribute(id);
>             }
>         } else {
>             return this.context.getAttribute(id);
>         }
>     }
> 
>     public Object removeAttribute(final String id) {
>         if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
>             RequestConfig local = this.requestConfig;
>             this.requestConfig = null;
>             return local;
>         } else {
>             return this.context.removeAttribute(id);
>         }
>     }
> 
>     public void setAttribute(final String id, final Object obj) {
>         if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
>             this.requestConfig = (RequestConfig) obj;
>         } else {
>             this.context.setAttribute(id, obj);
>         }
>     }
> 
> }
> ---
> 
> Oleg
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
> For additional commands, e-mail: httpclient-users-help@hc.apache.org
> 

Re: HttpContext and RequestConfig

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Wed, 2014-10-15 at 09:50 -0400, Todd W Lainhart wrote:
> > 
> > What one might do instead of cloning a context is to wrap it with a
> > decorator and discard the decorator along with all local modifications.
> > 
> 
> Thanks.  I'll have to think on this - I'm not sure that it will solve this 
> problem.  The problem is that I want the HttpContext passed between 
> execute(...) invocations to maintain/accumulate state for those 
> invocations (e.g. cookies, redirects list) - just not inherit the 
> RequestConfig state on individual requests where it's been applied.
> 
>   -- Todd

Well, in the worst case would this do the trick?
---
class MyHttpContext implements HttpContext {

    private final HttpContext context;
    private RequestConfig requestConfig;

    public MyHttpContext(final HttpContext context) {
        super();
        this.context = Args.notNull(context, "HTTP context");
    }

    public Object getAttribute(final String id) {
        if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
            if (this.requestConfig != null) {
                return this.requestConfig;
            } else {
                return this.context.getAttribute(id);
            }
        } else {
            return this.context.getAttribute(id);
        }
    }

    public Object removeAttribute(final String id) {
        if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
            RequestConfig local = this.requestConfig;
            this.requestConfig = null;
            return local;
        } else {
            return this.context.removeAttribute(id);
        }
    }

    public void setAttribute(final String id, final Object obj) {
        if (HttpClientContext.REQUEST_CONFIG.equals(id)) {
            this.requestConfig = (RequestConfig) obj;
        } else {
            this.context.setAttribute(id, obj);
        }
    }

}
---

Oleg


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


Re: HttpContext and RequestConfig

Posted by Todd W Lainhart <la...@us.ibm.com>.
> 
> What one might do instead of cloning a context is to wrap it with a
> decorator and discard the decorator along with all local modifications.
> 

Thanks.  I'll have to think on this - I'm not sure that it will solve this 
problem.  The problem is that I want the HttpContext passed between 
execute(...) invocations to maintain/accumulate state for those 
invocations (e.g. cookies, redirects list) - just not inherit the 
RequestConfig state on individual requests where it's been applied.

  -- Todd

Re: HttpContext and RequestConfig

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2014-10-14 at 11:37 -0400, Todd W Lainhart wrote:
> HttpClient 4.3.5 / HttpCore 4.3.2
> 
> I've got an execution context, that while appears to be a single 
> call/response to the caller, can result in multiple network calls - 
> multiple CloseableHttpClient.execute(...) invocations.  Those invocations 
> share HttpContext state, mainly for a shared cookie store.  The 
> CloseableHttpClient has a  custom RequestConfig associated to it.
> 
> One of the invocations creates a new HttpRequest object, with its own 
> RequestConfig that overrides the default.  On subsequent invocations I was 
> surprised to see that the RequestConfig that I set on the request became 
> the shared HttpContext's RequestConfig state, which is used in subsequent 
> invocations.  Reading the source confirms this - the request's config is 
> set on the "local context", which is the shared context I mentioned 
> earlier.
> 
> Is this the intended behavior?  I can see it both ways.
> 

Hi Todd

I find it reasonable that the last request config stays in the context
and gets propagated to subsequent requests within the same context. So,
it was intended. 

> I can work around this by clearing the request config on the context on 
> that one call, but I wanted to raise the question in case I'm missing a 
> concept.  I'm also not finding a "clone" or "copy" of a context, which I 
> thought I had seen at one point.
> 

Deprecated HttpParams supports #copy, but I do not think HttpContext
implementations ever supported #copy or #clone.  

What one might do instead of cloning a context is to wrap it with a
decorator and discard the decorator along with all local modifications.

---
public final class DefaultedHttpContext implements HttpContext {

    private final HttpContext local;
    private final HttpContext defaults;

    public DefaultedHttpContext(final HttpContext local, final
HttpContext defaults) {
        super();
        this.local = Args.notNull(local, "HTTP context");
        this.defaults = defaults;
    }

    public Object getAttribute(final String id) {
        final Object obj = this.local.getAttribute(id);
        if (obj == null) {
            return this.defaults.getAttribute(id);
        } else {
            return obj;
        }
    }

    public Object removeAttribute(final String id) {
        return this.local.removeAttribute(id);
    }

    public void setAttribute(final String id, final Object obj) {
        this.local.setAttribute(id, obj);
    }

}
---

Oleg


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