Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
28 package ch.boye.httpclientandroidlib.client.protocol;
30 import java.io.IOException;
31 import java.net.URI;
32 import java.net.URISyntaxException;
33 import java.util.ArrayList;
34 import java.util.Date;
35 import java.util.List;
37 import ch.boye.httpclientandroidlib.annotation.Immutable;
39 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
40 /* LogFactory removed by HttpClient for Android script. */
41 import ch.boye.httpclientandroidlib.Header;
42 import ch.boye.httpclientandroidlib.HttpException;
43 import ch.boye.httpclientandroidlib.HttpHost;
44 import ch.boye.httpclientandroidlib.HttpRequest;
45 import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
46 import ch.boye.httpclientandroidlib.ProtocolException;
47 import ch.boye.httpclientandroidlib.client.CookieStore;
48 import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
49 import ch.boye.httpclientandroidlib.client.params.HttpClientParams;
50 import ch.boye.httpclientandroidlib.conn.HttpRoutedConnection;
51 import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
52 import ch.boye.httpclientandroidlib.cookie.Cookie;
53 import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
54 import ch.boye.httpclientandroidlib.cookie.CookieSpec;
55 import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry;
56 import ch.boye.httpclientandroidlib.cookie.SetCookie2;
57 import ch.boye.httpclientandroidlib.protocol.HttpContext;
58 import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
60 /**
61 * Request interceptor that matches cookies available in the current
62 * {@link CookieStore} to the request being executed and generates
63 * corresponding <code>Cookie</code> request headers.
64 * <p>
65 * The following parameters can be used to customize the behavior of this
66 * class:
67 * <ul>
68 * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#DATE_PATTERNS}</li>
69 * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#SINGLE_COOKIE_HEADER}</li>
70 * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#COOKIE_POLICY}</li>
71 * </ul>
72 *
73 * @since 4.0
74 */
75 @Immutable
76 public class RequestAddCookies implements HttpRequestInterceptor {
78 public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
80 public RequestAddCookies() {
81 super();
82 }
84 public void process(final HttpRequest request, final HttpContext context)
85 throws HttpException, IOException {
86 if (request == null) {
87 throw new IllegalArgumentException("HTTP request may not be null");
88 }
89 if (context == null) {
90 throw new IllegalArgumentException("HTTP context may not be null");
91 }
93 String method = request.getRequestLine().getMethod();
94 if (method.equalsIgnoreCase("CONNECT")) {
95 return;
96 }
98 // Obtain cookie store
99 CookieStore cookieStore = (CookieStore) context.getAttribute(
100 ClientContext.COOKIE_STORE);
101 if (cookieStore == null) {
102 this.log.debug("Cookie store not specified in HTTP context");
103 return;
104 }
106 // Obtain the registry of cookie specs
107 CookieSpecRegistry registry = (CookieSpecRegistry) context.getAttribute(
108 ClientContext.COOKIESPEC_REGISTRY);
109 if (registry == null) {
110 this.log.debug("CookieSpec registry not specified in HTTP context");
111 return;
112 }
114 // Obtain the target host (required)
115 HttpHost targetHost = (HttpHost) context.getAttribute(
116 ExecutionContext.HTTP_TARGET_HOST);
117 if (targetHost == null) {
118 this.log.debug("Target host not set in the context");
119 return;
120 }
122 // Obtain the client connection (required)
123 HttpRoutedConnection conn = (HttpRoutedConnection) context.getAttribute(
124 ExecutionContext.HTTP_CONNECTION);
125 if (conn == null) {
126 this.log.debug("HTTP connection not set in the context");
127 return;
128 }
130 String policy = HttpClientParams.getCookiePolicy(request.getParams());
131 if (this.log.isDebugEnabled()) {
132 this.log.debug("CookieSpec selected: " + policy);
133 }
135 URI requestURI;
136 if (request instanceof HttpUriRequest) {
137 requestURI = ((HttpUriRequest) request).getURI();
138 } else {
139 try {
140 requestURI = new URI(request.getRequestLine().getUri());
141 } catch (URISyntaxException ex) {
142 throw new ProtocolException("Invalid request URI: " +
143 request.getRequestLine().getUri(), ex);
144 }
145 }
147 String hostName = targetHost.getHostName();
148 int port = targetHost.getPort();
149 if (port < 0) {
150 HttpRoute route = conn.getRoute();
151 if (route.getHopCount() == 1) {
152 port = conn.getRemotePort();
153 } else {
154 // Target port will be selected by the proxy.
155 // Use conventional ports for known schemes
156 String scheme = targetHost.getSchemeName();
157 if (scheme.equalsIgnoreCase("http")) {
158 port = 80;
159 } else if (scheme.equalsIgnoreCase("https")) {
160 port = 443;
161 } else {
162 port = 0;
163 }
164 }
165 }
167 CookieOrigin cookieOrigin = new CookieOrigin(
168 hostName,
169 port,
170 requestURI.getPath(),
171 conn.isSecure());
173 // Get an instance of the selected cookie policy
174 CookieSpec cookieSpec = registry.getCookieSpec(policy, request.getParams());
175 // Get all cookies available in the HTTP state
176 List<Cookie> cookies = new ArrayList<Cookie>(cookieStore.getCookies());
177 // Find cookies matching the given origin
178 List<Cookie> matchedCookies = new ArrayList<Cookie>();
179 Date now = new Date();
180 for (Cookie cookie : cookies) {
181 if (!cookie.isExpired(now)) {
182 if (cookieSpec.match(cookie, cookieOrigin)) {
183 if (this.log.isDebugEnabled()) {
184 this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
185 }
186 matchedCookies.add(cookie);
187 }
188 } else {
189 if (this.log.isDebugEnabled()) {
190 this.log.debug("Cookie " + cookie + " expired");
191 }
192 }
193 }
194 // Generate Cookie request headers
195 if (!matchedCookies.isEmpty()) {
196 List<Header> headers = cookieSpec.formatCookies(matchedCookies);
197 for (Header header : headers) {
198 request.addHeader(header);
199 }
200 }
202 int ver = cookieSpec.getVersion();
203 if (ver > 0) {
204 boolean needVersionHeader = false;
205 for (Cookie cookie : matchedCookies) {
206 if (ver != cookie.getVersion() || !(cookie instanceof SetCookie2)) {
207 needVersionHeader = true;
208 }
209 }
211 if (needVersionHeader) {
212 Header header = cookieSpec.getVersionHeader();
213 if (header != null) {
214 // Advertise cookie version support
215 request.addHeader(header);
216 }
217 }
218 }
220 // Stick the CookieSpec and CookieOrigin instances to the HTTP context
221 // so they could be obtained by the response interceptor
222 context.setAttribute(ClientContext.COOKIE_SPEC, cookieSpec);
223 context.setAttribute(ClientContext.COOKIE_ORIGIN, cookieOrigin);
224 }
226 }