最近些的爬虫请求某代理网站时运行几天就会持续报错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.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。
以上两种方案,可根据自身情况进行选择。
相关推荐
httpclient的用法,发送get请求和post请求,设置header
5. **Cookie管理**:HttpClient支持`CookieSpecs`和`CookieStore`,用于处理服务器返回的Cookie,实现会话保持。 6. **请求和响应处理**:HttpClient允许自定义请求实体和响应处理器,支持JSON、XML等数据格式的...
try(CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost(url); StringEntity stringEntity = new StringEntity(params, Charset.forName("UTF-8")); ...
在Android开发中,HttpClient是一个常用...通过以上知识点的学习,你可以理解如何使用HttpClient进行网络请求,以及处理返回的JSON数据。但请注意,对于新的Android项目,最好遵循最新的最佳实践,使用更现代的网络库。
此外,由于HttpClient在新版本的Android中不再推荐使用,开发者常转向使用OkHttp或Android自带的HttpURLConnection,它们提供了更现代的API和更好的性能。 总的来说,这个示例项目WebDataShow是一个基础的网络请求...
HttpClient是个很不错的开源框架(org.appache.http),封装了访问http的请求头,参数,内容体,响应等等,使用起来更方面更强大。 HttpURLConnection是java的标准类,可以实现简单的基于URL请求、响应功能,什么都...
下面我们将详细探讨如何在Java中使用HttpClient来实现这一目标。 首先,我们需要导入必要的Apache HttpClient库,通常包含以下依赖: ```xml <groupId>org.apache.httpcomponents <artifactId>httpclient ...
- **创建HttpClient实例**:首先,我们需要创建一个HttpClient对象,例如使用`HttpClientBuilder`或`HttpClients.createDefault()`方法。 - **构建HttpGet请求**:使用`HttpGet`类创建一个HTTP GET请求,指定要...
6. **执行请求并获取响应**: 使用HttpClient的`execute`方法执行请求,并捕获返回的`HttpResponse`: ```java HttpResponse response = httpClient.execute(httpPost); ``` 7. **处理响应**: 你可以读取响应状态...
接下来,我们讨论如何使用HttpClient进行GET请求。GET请求通常用于获取资源,不涉及请求体: ```java CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(...
本篇文章将详细探讨如何使用HttpClient来访问Servlet,并阐述相关的核心知识点。 首先,我们需要理解Servlet的本质。Servlet是一种Java类,它扩展了服务器的功能,用于处理HTTP请求并生成响应。通常,Servlet部署在...
使用HttpClient登录网易邮箱 博文链接:https://bps.iteye.com/blog/136231
本篇将详细讲解如何使用`HttpClient`进行异步请求数据,并结合Android的`AsyncTask`来处理后台任务,避免阻塞UI线程。 首先,理解`HttpClient`的基本使用方法。`HttpClient`包含几个关键组件,如`HttpClient`实例、...
在这个场景下,"使用HttpClient调试android接口-通用方法"的标题表明我们将讨论如何使用HttpClient来调试Android应用中的API接口。下面,我们将深入探讨HttpClient的基础知识、调试技巧以及如何封装通用方法。 1. *...
本篇文章将深入探讨如何使用HttpClient方式调用URL,以及相关的知识点。 首先,HttpClient允许我们构建复杂的HTTP请求,包括GET、POST以及其他HTTP方法。使用HttpClient调用URL的基本步骤包括创建HttpClient实例、...
在使用HttpClient和HtmlParser实现网络爬虫的过程中,首先需要设置开发环境。这里推荐使用Eclipse Europa作为集成开发环境(IDE),并确保安装了JDK 1.6。在Eclipse中创建一个新的JAVA工程,并将HttpClient和...
本文将深入讲解如何使用HttpClient来发送HTTP请求,以及相关的源码分析。 首先,让我们了解HttpClient的基本用法。Apache HttpClient库提供了丰富的功能,包括GET、POST、PUT等各种HTTP方法的支持。以下是一个简单...
5. **执行请求**:现在可以使用HttpClient发送请求了,这将返回一个`HttpResponse`对象,包含服务器的响应。 ```java HttpResponse response = httpClient.execute(httpPost); ``` 6. **处理响应**:检查响应...
### 使用HttpClient发送POST请求,并获取响应内容 #### 一、简介 在现代软件开发中,尤其是在Web应用领域,客户端与服务器之间的通信是非常重要的环节。Java作为一种广泛应用的编程语言,提供了多种方式来实现这一...
1. **字符编码设置**:HttpClient默认可能不会自动处理服务器返回的字符集,因此需要明确指定编码。在发送请求时,可以使用`EntityUtils.toString(entity, "UTF-8")`来指定解码的字符集,确保与服务器响应的字符集...