• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.libraries.entitlement.http;
18 
19 import static com.android.libraries.entitlement.utils.DebugUtils.logPii;
20 
21 import com.google.common.collect.ImmutableList;
22 
23 import java.net.HttpCookie;
24 import java.util.List;
25 
26 /**
27  * Simple cookie management.
28  *
29  * <p>Use {@link #parseSetCookieHeaders} to parse the "Set-Cookie" headers in HTTP responses
30  * from the server, and use {@link #toCookieHeaders} to generate the "Cookie" headers in
31  * follow-up HTTP requests.
32  */
33 public class HttpCookieJar {
34     private final ImmutableList<HttpCookie> mCookies;
35 
HttpCookieJar(ImmutableList<HttpCookie> cookies)36     private HttpCookieJar(ImmutableList<HttpCookie> cookies) {
37         mCookies = cookies;
38     }
39 
40     /**
41      * Parses the "Set-Cookie" headers in HTTP responses from servers.
42      */
parseSetCookieHeaders(List<String> rawCookies)43     public static HttpCookieJar parseSetCookieHeaders(List<String> rawCookies) {
44         ImmutableList.Builder<HttpCookie> parsedCookies = ImmutableList.builder();
45         for (String rawCookie : rawCookies) {
46             List<HttpCookie> cookies = parseCookiesSafely(rawCookie);
47             parsedCookies.addAll(cookies);
48         }
49         return new HttpCookieJar(parsedCookies.build());
50     }
51 
52     /**
53      * Returns the cookies as "Cookie" headers in HTTP requests to servers.
54      */
toCookieHeaders()55     public ImmutableList<String> toCookieHeaders() {
56         ImmutableList.Builder<String> cookieHeader = ImmutableList.builder();
57         for (HttpCookie cookie : mCookies) {
58             cookieHeader.add(removeObsoleteCookieAttributes(cookie).toString());
59         }
60         return cookieHeader.build();
61     }
62 
parseCookiesSafely(String rawCookie)63     private static List<HttpCookie> parseCookiesSafely(String rawCookie) {
64         try {
65             return HttpCookie.parse(rawCookie);
66         } catch (IllegalArgumentException e) {
67             logPii("Failed to parse cookie: " + rawCookie);
68             return ImmutableList.of();
69         }
70     }
71 
72     /**
73      * Removes some attributes of the cookie that should not be set in HTTP requests.
74      *
75      * <p>Unfortunately, {@link HttpCookie#toString()} preserves some cookie attributes:
76      * Domain, Path, and Port as per RFC 2965. Such behavior is obsoleted by the RFC 6265.
77      *
78      * <p>To be clear, Domain and Path are valid attributes by RFC 6265, but cookie attributes
79      * be set in HTTP request "Cookie" headers.
80      */
removeObsoleteCookieAttributes(HttpCookie cookie)81     private static HttpCookie removeObsoleteCookieAttributes(HttpCookie cookie) {
82         cookie.setDomain(null);
83         cookie.setPath(null);
84         cookie.setPortlist(null);
85         return cookie;
86     }
87 }
88