《HttpClient 官方文档》第三章 HTTP 状态管理

原文链接 译者[陈志军]

通常 HTTP 被设计为无状态,面向请求/响应的协议,对于有一些逻辑相关的请求/响应交换的有状态会话没有特别的规定。正当 HTTP 协议越来越流行和被认可,越来越多之前没有打算使用它的系统,现在也开始为了应用程序而使用它。例如电子商务应用的内容传输。因此,支持 HTTP 状态管理变得非常有必要。
NetScape(网景公司),曾经引领网页客户端和服务器端软件的发展,在他们的产品中基于专有的规范,提供了 HTTP 状态管理的支持。之后,NetScape 尝试通过发布规范草案来标准化这种机制。这些努力通过 RFC 标准促进了正式的规范定义。但是,状态管理在很多应用程序中仍然支持 Netscape 的草案而不兼容官方的标准。很多Web浏览器的主要开发人员觉得有必要保留这些极大地促进标准兼容性的草案。

3.1. HTTP cookies

一个 HTTP cookie 是 HTTP 代理或者目标服务器保持会话和交流状态信息的一个令牌或者短数据包。Netscape 工程师过去称它为 “魔力 cookie”,一个非常有粘力的名字。
HttpClient 使用 Cookie 接口来表示一个抽象 cookie 令牌。在 HTTP 中,简单的形式是指一个键/值对。通常一个 HTTP cookie 也包含一系列的属性,cookie 提供的属性有例如一个域名是否可用,源服务器上指定的url子集路径,cookie 最长的有效时间等。
SetCookie 接口表示由源服务器发送给HTTP代理的响应头中的Set-Cookie,以此来维持一个会话状态。
ClientCookie接口继承自 Cookie 接口并且自身扩展了客户端特有的功能,例如从源服务器中恢复原始的 cookie。这对于生成 Cookie 的头信息是非常重要的,因为一些特殊的 cookie 规范需要Cookie头信息中必须包含特定的属性,这些需要在 Set-Cookie 头中定义。下面是一些创建客户端 cookie 的实例:

BasicClientCookie cookie = new BasicClientCookie("name", "value");
// Set effective domain and path attributes
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
// Set attributes exactly as sent by the server
cookie.setAttribute(ClientCookie.PATH_ATTR, "/");
cookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");

3.2. Cookie 规范

CookieSpec 接口定义了一个 cookie 管理规范。下面这些是 cookie 管理规范强制的:

  • Set-Cookie 的解析规则
  • 验证解析 cookies的规则
  • 给定的主机,端口和源路径来格式化Cookie 头信息

HttpClient 附带了一些 CookieSpec 的实现规范:

  • Standard strict: State management policy compliant with the syntax and semantics of the well-behaved profile defined by RFC on6265, section 4.
  • Standard: State management policy compliant with a more relaxed profile defined by RFC 6265, section 4 intended for interoperability with existing servers that do not conform to the well behaved profile.
  • Netscape draft (obsolete): This policy conforms to the original draft specification published by Netscape Communications. It should be avoided unless absolutely necessary for compatibility with legacy code.
  • RFC 2965 (obsolete): State management policy compliant with the obsolete state management specification defined by RFC 2965. Please do not use in new applications.
  • RFC 2109 (obsolete): State management policy compliant with the obsolete state management specification defined by RFC 2109. Please do not use in new applications.
  • Browser compatibility (obsolete): This policy strives to closely mimic the (mis)behavior of older versions of browser applications such as Microsoft Internet Explorer and Mozilla FireFox. Please do not use in new applications.
  • Default: Default cookie policy is a synthetic policy that picks up either RFC 2965, RFC 2109 or Netscape draft compliant implementation based on properties of cookies sent with the HTTP response (such as version attribute, now obsolete). This policy will be deprecated in favor of the standard (RFC 6265 compliant) implementation in the next minor release of HttpClient.
  • Ignore cookies: All cookies are ignored.

在新的应用实现中,强烈建议使用Standard 或者 Standard strict两种规范。过时的规范仅仅在一些遗留的系统上为了兼容性而使用。支持的过时规范会在下一个发布的 HttpClient 主要版本中移除。

3.3. 选择 cookie 策略

Cookie 策略可以在 HTTP 客户端中设置,如果需要也可以在 HTTP 请求中重写。

RequestConfig globalConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.build();
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultRequestConfig(globalConfig)
.build();
RequestConfig localConfig = RequestConfig.copy(globalConfig)
.setCookieSpec(CookieSpecs.STANDARD_STRICT)
.build();
HttpGet httpGet = new HttpGet("/");
httpGet.setConfig(localConfig);

3.4. 自定义 cookie 策略

为了实现自定义 cookie 策略你必须实现一个 CookieSpec 接口,创建 CookieSpecProvider 的实现类,用它来初始化自定义的规范和 HttpClient 的注册工厂。一旦自定义策略被注册,它就可以像标准的 cookie 规范一些样使用。

PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.getDefault();

Registry r = RegistryBuilder.create()
.register(CookieSpecs.DEFAULT,
new DefaultCookieSpecProvider(publicSuffixMatcher))
.register(CookieSpecs.STANDARD,
new RFC6265CookieSpecProvider(publicSuffixMatcher))
.register("easy", new EasySpecProvider())
.build();

RequestConfig requestConfig = RequestConfig.custom()
.setCookieSpec("easy")
.build();

CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieSpecRegistry(r)
.setDefaultRequestConfig(requestConfig)
.build();

3.5. Cookie 持久化

HttpClient 可以和任何一个实现了CookieStore 接口的物理 cookie 一起使用。默认的 CookieStore 实现类是 BasicCookieStore,它是使用 java.utils.ArrayList 来实现的。当容器对象被进行垃圾回收时,储存在BasicClientCookie中的Cookies对象也会丢失。如果必要的话,使用者可以提供一个复杂的实现。

// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Populate cookies if needed
BasicClientCookie cookie = new BasicClientCookie("name", "value");
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// Set the store
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();

3.6. HTTP 状态管理和执行上下文

在HTTP请求执行过程中,HttpClient将下面相关状态管理对象添加到执行的上下文中:

  • Lookup instance representing the actual cookie specification registry. The value of this attribute set in the local context takes precedence over the default one.
  • CookieSpec instance representing the actual cookie specification.
  • CookieOrigin instance representing the actual details of the origin server.
  • CookieStore instance representing the actual cookie store. The value of this attribute set in the local context takes precedence over the default one.

本地HttpContext对象可以用于在请求执行之前定制HTTP状态管理的上下文,或者在请求执行后检查它的状态。开发者仍然可以使用分开的上下文来实现每一个用户(或者每一个线程)的状态管理。cookie 规范的注册,在本地上下文中定义存储的 cookie 优先于那些在 HTTP 客户端设置的默认上下文。

CloseableHttpClient httpclient =

Lookup cookieSpecReg =
CookieStore cookieStore =

HttpClientContext context = HttpClientContext.create();
context.setCookieSpecRegistry(cookieSpecReg);
context.setCookieStore(cookieStore);
HttpGet httpget = new HttpGet("http://somehost/");
CloseableHttpResponse response1 = httpclient.execute(httpget, context);

// Cookie origin details
CookieOrigin cookieOrigin = context.getCookieOrigin();
// Cookie spec used
CookieSpec cookieSpec = context.getCookieSpec();

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/113886.html

(0)
上一篇 2021年8月27日
下一篇 2021年8月27日

相关推荐

发表回复

登录后才能评论