ResponseProcessCookies.java revision d42abb2fd917184764daf22f5f299e848b8701d7
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/client/protocol/ResponseProcessCookies.java $
3391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * $Revision: 673450 $
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt *
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * ====================================================================
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Licensed to the Apache Software Foundation (ASF) under one
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or more contributor license agreements.  See the NOTICE file
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * distributed with this work for additional information
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * regarding copyright ownership.  The ASF licenses this file
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to you under the Apache License, Version 2.0 (the
127832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * "License"); you may not use this file except in compliance
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with the License.  You may obtain a copy of the License at
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *   http://www.apache.org/licenses/LICENSE-2.0
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Unless required by applicable law or agreed to in writing,
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * software distributed under the License is distributed on an
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * KIND, either express or implied.  See the License for the
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * specific language governing permissions and limitations
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * under the License.
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ====================================================================
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This software consists of voluntary contributions made by many
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * individuals on behalf of the Apache Software Foundation.  For more
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information on the Apache Software Foundation, please see
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <http://www.apache.org/>.
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtpackage org.apache.http.client.protocol;
33051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtimport java.io.IOException;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport java.util.List;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport org.apache.commons.logging.Log;
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtimport org.apache.commons.logging.LogFactory;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport org.apache.http.Header;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport org.apache.http.HeaderIterator;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport org.apache.http.HttpException;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport org.apache.http.HttpResponse;
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtimport org.apache.http.HttpResponseInterceptor;
441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtimport org.apache.http.client.CookieStore;
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport org.apache.http.cookie.Cookie;
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport org.apache.http.cookie.CookieOrigin;
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport org.apache.http.cookie.CookieSpec;
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport org.apache.http.cookie.MalformedCookieException;
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtimport org.apache.http.cookie.SM;
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport org.apache.http.protocol.HttpContext;
51391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Response interceptor that populates the current {@link CookieStore} with data
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * contained in response cookies received in the given the HTTP response.
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @version $Revision: 673450 $
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @since 4.0
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @deprecated Please use {@link java.net.URL#openConnection} instead.
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *     for further details.
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt@Deprecated
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpublic class ResponseProcessCookies implements HttpResponseInterceptor {
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private final Log log = LogFactory.getLog(getClass());
701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public ResponseProcessCookies() {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        super();
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    public void process(final HttpResponse response, final HttpContext context)
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            throws HttpException, IOException {
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (response == null) {
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            throw new IllegalArgumentException("HTTP request may not be null");
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (context == null) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            throw new IllegalArgumentException("HTTP context may not be null");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
83f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
84f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt        // Obtain cookie store
85f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt        CookieStore cookieStore = (CookieStore) context.getAttribute(
86f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt                ClientContext.COOKIE_STORE);
87f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt        if (cookieStore == null) {
88f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt            this.log.info("Cookie store not available in HTTP context");
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        // Obtain actual CookieSpec instance
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        CookieSpec cookieSpec = (CookieSpec) context.getAttribute(
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                ClientContext.COOKIE_SPEC);
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        if (cookieSpec == null) {
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            this.log.info("CookieSpec not available in HTTP context");
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            return;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        }
9834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt        // Obtain actual CookieOrigin instance
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        CookieOrigin cookieOrigin = (CookieOrigin) context.getAttribute(
10004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt                ClientContext.COOKIE_ORIGIN);
10104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        if (cookieOrigin == null) {
10204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            this.log.info("CookieOrigin not available in HTTP context");
10304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            return;
10404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        }
10504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        HeaderIterator it = response.headerIterator(SM.SET_COOKIE);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        processCookies(it, cookieSpec, cookieOrigin, cookieStore);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        // see if the cookie spec supports cookie versioning.
10904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt        if (cookieSpec.getVersion() > 0) {
11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            // process set-cookie2 headers.
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            // Cookie2 will replace equivalent Cookie instances
11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt            it = response.headerIterator(SM.SET_COOKIE2);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            processCookies(it, cookieSpec, cookieOrigin, cookieStore);
1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt        }
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    private void processCookies(
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            final HeaderIterator iterator,
1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt            final CookieSpec cookieSpec,
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            final CookieOrigin cookieOrigin,
121391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt            final CookieStore cookieStore) {
122391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt        while (iterator.hasNext()) {
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            Header header = iterator.nextHeader();
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt            try {
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                List<Cookie> cookies = cookieSpec.parse(header, cookieOrigin);
1267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                for (Cookie cookie : cookies) {
1277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                    try {
1287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        cookieSpec.validate(cookie, cookieOrigin);
1297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        cookieStore.addCookie(cookie);
1307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt
1317832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        if (this.log.isDebugEnabled()) {
1327832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            // BEGIN android-changed
1337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            this.log.debug("Cookie accepted: \""
1347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                                    + cookieToString(cookie) + "\". ");
1357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            // END android-changed
1367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        }
1377832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                    } catch (MalformedCookieException ex) {
1387832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        if (this.log.isWarnEnabled()) {
1397832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            // BEGIN android-changed
1407832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            this.log.warn("Cookie rejected: \""
1417832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                                    + cookieToString(cookie) + "\". " + ex.getMessage());
1427832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                            // END android-changed
1437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt                        }
144051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                    }
145051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                }
146051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt            } catch (MalformedCookieException ex) {
147051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                if (this.log.isWarnEnabled()) {
148051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                    this.log.warn("Invalid cookie header: \""
149051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                            + header + "\". " + ex.getMessage());
150051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt                }
151d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt            }
152d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt        }
153d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt    }
154d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
155d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt    // BEGIN android-added
156d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt    /**
157d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt     * Don't log the cookie's value; that's potentially sensitive information.
158d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt     */
159d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt    private String cookieToString(Cookie cookie) {
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt        return cookie.getClass().getSimpleName()
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                + "[version=" + cookie.getVersion()
1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt                + ",name=" + cookie.getName()
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                + ",domain=" + cookie.getDomain()
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                + ",path=" + cookie.getPath()
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                + ",expiry=" + cookie.getExpiryDate()
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                + "]";
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    }
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    // END android-added
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt