RequestAddCookies.java revision 069490a5ca2fd1988d29daf45d892f47ad665115
1/*
2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java $
3 * $Revision: 673450 $
4 * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
5 *
6 * ====================================================================
7 * Licensed to the Apache Software Foundation (ASF) under one
8 * or more contributor license agreements.  See the NOTICE file
9 * distributed with this work for additional information
10 * regarding copyright ownership.  The ASF licenses this file
11 * to you under the Apache License, Version 2.0 (the
12 * "License"); you may not use this file except in compliance
13 * with the License.  You may obtain a copy of the License at
14 *
15 *   http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing,
18 * software distributed under the License is distributed on an
19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 * KIND, either express or implied.  See the License for the
21 * specific language governing permissions and limitations
22 * under the License.
23 * ====================================================================
24 *
25 * This software consists of voluntary contributions made by many
26 * individuals on behalf of the Apache Software Foundation.  For more
27 * information on the Apache Software Foundation, please see
28 * <http://www.apache.org/>.
29 *
30 */
31
32package org.apache.http.client.protocol;
33
34import java.io.IOException;
35import java.net.URI;
36import java.net.URISyntaxException;
37import java.util.ArrayList;
38import java.util.List;
39
40import org.apache.commons.logging.Log;
41import org.apache.commons.logging.LogFactory;
42import org.apache.http.Header;
43import org.apache.http.HttpException;
44import org.apache.http.HttpHost;
45import org.apache.http.HttpRequest;
46import org.apache.http.HttpRequestInterceptor;
47import org.apache.http.ProtocolException;
48import org.apache.http.client.CookieStore;
49import org.apache.http.client.methods.HttpUriRequest;
50import org.apache.http.client.params.HttpClientParams;
51import org.apache.http.conn.ManagedClientConnection;
52import org.apache.http.cookie.Cookie;
53import org.apache.http.cookie.CookieOrigin;
54import org.apache.http.cookie.CookieSpec;
55import org.apache.http.cookie.CookieSpecRegistry;
56import org.apache.http.protocol.HttpContext;
57import org.apache.http.protocol.ExecutionContext;
58
59/**
60 * Request interceptor that matches cookies available in the current
61 * {@link CookieStore} to the request being executed and generates
62 * corresponding cookierequest headers.
63 *
64 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
65 *
66 * @version $Revision: 673450 $
67 *
68 * @since 4.0
69 */
70public class RequestAddCookies implements HttpRequestInterceptor {
71
72    private final Log log = LogFactory.getLog(getClass());
73
74    public RequestAddCookies() {
75        super();
76    }
77
78    public void process(final HttpRequest request, final HttpContext context)
79            throws HttpException, IOException {
80        if (request == null) {
81            throw new IllegalArgumentException("HTTP request may not be null");
82        }
83        if (context == null) {
84            throw new IllegalArgumentException("HTTP context may not be null");
85        }
86
87        // Obtain cookie store
88        CookieStore cookieStore = (CookieStore) context.getAttribute(
89                ClientContext.COOKIE_STORE);
90        if (cookieStore == null) {
91            this.log.info("Cookie store not available in HTTP context");
92            return;
93        }
94
95        // Obtain the registry of cookie specs
96        CookieSpecRegistry registry= (CookieSpecRegistry) context.getAttribute(
97                ClientContext.COOKIESPEC_REGISTRY);
98        if (registry == null) {
99            this.log.info("CookieSpec registry not available in HTTP context");
100            return;
101        }
102
103        // Obtain the target host (required)
104        HttpHost targetHost = (HttpHost) context.getAttribute(
105                ExecutionContext.HTTP_TARGET_HOST);
106        if (targetHost == null) {
107            throw new IllegalStateException("Target host not specified in HTTP context");
108        }
109
110        // Obtain the client connection (required)
111        ManagedClientConnection conn = (ManagedClientConnection) context.getAttribute(
112                ExecutionContext.HTTP_CONNECTION);
113        if (conn == null) {
114            throw new IllegalStateException("Client connection not specified in HTTP context");
115        }
116
117        String policy = HttpClientParams.getCookiePolicy(request.getParams());
118        if (this.log.isDebugEnabled()) {
119            this.log.debug("CookieSpec selected: " + policy);
120        }
121
122        URI requestURI;
123        if (request instanceof HttpUriRequest) {
124            requestURI = ((HttpUriRequest) request).getURI();
125        } else {
126            try {
127                requestURI = new URI(request.getRequestLine().getUri());
128            } catch (URISyntaxException ex) {
129                throw new ProtocolException("Invalid request URI: " +
130                        request.getRequestLine().getUri(), ex);
131            }
132        }
133
134        String hostName = targetHost.getHostName();
135        int port = targetHost.getPort();
136        if (port < 0) {
137            port = conn.getRemotePort();
138        }
139
140        CookieOrigin cookieOrigin = new CookieOrigin(
141                hostName,
142                port,
143                requestURI.getPath(),
144                conn.isSecure());
145
146        // Get an instance of the selected cookie policy
147        CookieSpec cookieSpec = registry.getCookieSpec(policy, request.getParams());
148        // Get all cookies available in the HTTP state
149        List<Cookie> cookies = new ArrayList<Cookie>(cookieStore.getCookies());
150        // Find cookies matching the given origin
151        List<Cookie> matchedCookies = new ArrayList<Cookie>();
152        for (Cookie cookie : cookies) {
153            if (cookieSpec.match(cookie, cookieOrigin)) {
154                if (this.log.isDebugEnabled()) {
155                    this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
156                }
157                matchedCookies.add(cookie);
158            }
159        }
160        // Generate Cookie request headers
161        if (!matchedCookies.isEmpty()) {
162            List<Header> headers = cookieSpec.formatCookies(matchedCookies);
163            for (Header header : headers) {
164                request.addHeader(header);
165            }
166        }
167
168        int ver = cookieSpec.getVersion();
169        if (ver > 0) {
170            boolean needVersionHeader = false;
171            for (Cookie cookie : matchedCookies) {
172                if (ver != cookie.getVersion()) {
173                    needVersionHeader = true;
174                }
175            }
176
177            if (needVersionHeader) {
178                Header header = cookieSpec.getVersionHeader();
179                if (header != null) {
180                    // Advertise cookie version support
181                    request.addHeader(header);
182                }
183            }
184        }
185
186        // Stick the CookieSpec and CookieOrigin instances to the HTTP context
187        // so they could be obtained by the response interceptor
188        context.setAttribute(ClientContext.COOKIE_SPEC, cookieSpec);
189        context.setAttribute(ClientContext.COOKIE_ORIGIN, cookieOrigin);
190    }
191
192}
193