`
energykey
  • 浏览: 597472 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

使用httpclient返回 header too long

阅读更多
最近些的爬虫请求某代理网站时运行几天就会持续报错400,header too long,google无答案,于是看了下源码,主要原因为cookie的累积导致(可以理解为你的浏览器很久没有清理缓存),以下为排查过程,解决方案见文章最后。
httclient请求调用链路:
org.apache.http.impl.client.InternalHttpClient#doExecute
org.apache.http.impl.client.InternalHttpClient#setupContext
if (context.getAttribute(HttpClientContext.COOKIE_STORE) == null) {
    context.setAttribute(HttpClientContext.COOKIE_STORE, this.cookieStore);
}
 
如果没有显示设置cooki_store,取this(httpclient)的成员变量cookieStore,而通常我们httpClient只有1个实例,那么cookieStore也等同于是单例的。
org.apache.http.impl.execchain.RedirectExec#execute:108
org.apache.http.impl.execchain.RetryExec#execute:86
org.apache.http.impl.execchain.ProtocolExec#execute
org.apache.http.impl.execchain.MainClientExec#execute
org.apache.http.protocol.HttpRequestExecutor#execute
conn.sendRequestHeader(request);
 org.apache.http.protocol.HttpRequestExecutor#doSendRequest
org.apache.http.impl.conn.CPoolProxy#sendRequestHeader
org.apache.http.impl.io.AbstractMessageWriter#write
Cookie的发送:
for (final HeaderIterator it = message.headerIterator(); it.hasNext(); ) {
final Header header = it.nextHeader();
    this.sessionBuffer.writeLine
        (lineFormatter.formatHeader(this.lineBuf, header));
}
 
Cookie的保存:
org.apache.http.impl.execchain.ProtocolExec#execute:200
org.apache.http.HttpResponseInterceptor#process
org.apache.http.client.protocol.ResponseProcessCookies#process
org.apache.http.client.protocol.ResponseProcessCookies#processCookies:114
cookieStore.addCookie(cookie);
 
/**
 * Adds an {@link Cookie HTTP cookie}, replacing any existing equivalent cookies.
 * If the given cookie has already expired it will not be added, but existing
 * values will still be removed.
 *
 * @param cookie the {@link Cookie cookie} to be added
 *
 * @see #addCookies(Cookie[])
 *
 */
public synchronized void addCookie(final Cookie cookie) {
if (cookie != null) {
// first remove any old cookie that is equivalent
cookies.remove(cookie);
        if (!cookie.isExpired(new Date())) {
cookies.add(cookie);
}
    }
}
 
注意到这里添加一个cookie时会先移除,然后判断cookie是否已经失效,没有失效才会add,这样看是不会出问题的,那问题到底出在哪里?而通过调试发现我们的第三方网站的sessionID的cookie的name居然是会变的!导致老的cookie无法删除,越积越多。
解决方案①:禁用cookie
CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager)
                              .setRetryHandler(retryHandler).setDefaultRequestConfig(config).disableCookieManagement().build();
 disableCookieManagement()方法会停止发送和接收cookie。
/**
 * Disables state (cookie) management.
 * <p/>
* Please note this value can be overridden by the {@link #setHttpProcessor(
 * org.apache.http.protocol.HttpProcessor)} method.
 */
public final HttpClientBuilder disableCookieManagement() {
this.cookieManagementDisabled = true;
    return this;
}
 
启用后org.apache.http.protocol.ImmutableHttpProcessor#responseInterceptors response拦截器里不再包含ResponseProcessCookies这一拦截器,不再执行存储cookie操作,观察后续请求,header里也不再包含cookie字段。
拦截器注册代码:org.apache.http.impl.client.HttpClientBuilder#build:839
if (!cookieManagementDisabled) {
    b.add(new RequestAddCookies());
}
if (!cookieManagementDisabled) {
    b.add(new ResponseProcessCookies());
}
 
解放方案②:设置单独的context
HttpClientContext context = HttpClientContext.create();
context.setCookieStore(new BasicCookieStore());
CloseableHttpResponse response = httpClient.execute(httpGet, context);
 
设置后因为context的cookieStore不为null,将不再默认取httpclient的成员变量cookiestore。
以上两种方案,可根据自身情况进行选择。
0
1
分享到:
评论

相关推荐

    httpclient用法,发送get和post请求,设置header

    httpclient的用法,发送get请求和post请求,设置header

    使用HttpClient必须的jar包

    5. **Cookie管理**:HttpClient支持`CookieSpecs`和`CookieStore`,用于处理服务器返回的Cookie,实现会话保持。 6. **请求和响应处理**:HttpClient允许自定义请求实体和响应处理器,支持JSON、XML等数据格式的...

    java使用HttpClient通过url下载文件到本地

    - **创建HttpClient实例**:首先,我们需要创建一个HttpClient对象,例如使用`HttpClientBuilder`或`HttpClients.createDefault()`方法。 - **构建HttpGet请求**:使用`HttpGet`类创建一个HTTP GET请求,指定要...

    SpringBoot使用httpclient发送Post请求时

    try(CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost(url); StringEntity stringEntity = new StringEntity(params, Charset.forName("UTF-8")); ...

    一个使用HttpClient调用天气预报接口的例程

    在Android开发中,HttpClient是一个常用...通过以上知识点的学习,你可以理解如何使用HttpClient进行网络请求,以及处理返回的JSON数据。但请注意,对于新的Android项目,最好遵循最新的最佳实践,使用更现代的网络库。

    使用HttpClient获取网页html源代码.zip

    此外,由于HttpClient在新版本的Android中不再推荐使用,开发者常转向使用OkHttp或Android自带的HttpURLConnection,它们提供了更现代的API和更好的性能。 总的来说,这个示例项目WebDataShow是一个基础的网络请求...

    使用HttpClient下载图片

    HttpClient是个很不错的开源框架(org.appache.http),封装了访问http的请求头,参数,内容体,响应等等,使用起来更方面更强大。 HttpURLConnection是java的标准类,可以实现简单的基于URL请求、响应功能,什么都...

    Java 使用HttpClient保持SESSION状态

    下面我们将详细探讨如何在Java中使用HttpClient来实现这一目标。 首先,我们需要导入必要的Apache HttpClient库,通常包含以下依赖: ```xml &lt;groupId&gt;org.apache.httpcomponents &lt;artifactId&gt;httpclient ...

    HttpClient 调用WebService示例

    6. **执行请求并获取响应**: 使用HttpClient的`execute`方法执行请求,并捕获返回的`HttpResponse`: ```java HttpResponse response = httpClient.execute(httpPost); ``` 7. **处理响应**: 你可以读取响应状态...

    使用httpclient访问servlet

    本篇文章将详细探讨如何使用HttpClient来访问Servlet,并阐述相关的核心知识点。 首先,我们需要理解Servlet的本质。Servlet是一种Java类,它扩展了服务器的功能,用于处理HTTP请求并生成响应。通常,Servlet部署在...

    HttpClient模拟get,post请求并发送请求参数(json等)

    接下来,我们讨论如何使用HttpClient进行GET请求。GET请求通常用于获取资源,不涉及请求体: ```java CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(...

    使用HttpClient登录网易邮箱

    使用HttpClient登录网易邮箱 博文链接:https://bps.iteye.com/blog/136231

    使用HttpClient异步请求数据

    本篇将详细讲解如何使用`HttpClient`进行异步请求数据,并结合Android的`AsyncTask`来处理后台任务,避免阻塞UI线程。 首先,理解`HttpClient`的基本使用方法。`HttpClient`包含几个关键组件,如`HttpClient`实例、...

    使用HttpClient调试android接口-通用方法

    在这个场景下,"使用HttpClient调试android接口-通用方法"的标题表明我们将讨论如何使用HttpClient来调试Android应用中的API接口。下面,我们将深入探讨HttpClient的基础知识、调试技巧以及如何封装通用方法。 1. *...

    httpclient方式调用url

    本篇文章将深入探讨如何使用HttpClient方式调用URL,以及相关的知识点。 首先,HttpClient允许我们构建复杂的HTTP请求,包括GET、POST以及其他HTTP方法。使用HttpClient调用URL的基本步骤包括创建HttpClient实例、...

    使用 HttpClient 和 HtmlParser 实现简易网络爬虫

    在使用HttpClient和HtmlParser实现网络爬虫的过程中,首先需要设置开发环境。这里推荐使用Eclipse Europa作为集成开发环境(IDE),并确保安装了JDK 1.6。在Eclipse中创建一个新的JAVA工程,并将HttpClient和...

    java使用HttpClient发送http请求

    本文将深入讲解如何使用HttpClient来发送HTTP请求,以及相关的源码分析。 首先,让我们了解HttpClient的基本用法。Apache HttpClient库提供了丰富的功能,包括GET、POST、PUT等各种HTTP方法的支持。以下是一个简单...

    使用httpclient模拟表单提交

    5. **执行请求**:现在可以使用HttpClient发送请求了,这将返回一个`HttpResponse`对象,包含服务器的响应。 ```java HttpResponse response = httpClient.execute(httpPost); ``` 6. **处理响应**:检查响应...

    使用HttpClient发送POST请求,并获取响应内容(附详细步骤).txt

    ### 使用HttpClient发送POST请求,并获取响应内容 #### 一、简介 在现代软件开发中,尤其是在Web应用领域,客户端与服务器之间的通信是非常重要的环节。Java作为一种广泛应用的编程语言,提供了多种方式来实现这一...

    彻底解决httpClient乱码问题

    1. **字符编码设置**:HttpClient默认可能不会自动处理服务器返回的字符集,因此需要明确指定编码。在发送请求时,可以使用`EntityUtils.toString(entity, "UTF-8")`来指定解码的字符集,确保与服务器响应的字符集...

Global site tag (gtag.js) - Google Analytics