• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 libcore.net.http;
18 
19 import java.net.URI;
20 import java.util.Date;
21 import java.util.List;
22 import java.util.Map;
23 
24 /**
25  * Parsed HTTP request headers.
26  */
27 public final class RequestHeaders {
28     private final URI uri;
29     private final RawHeaders headers;
30 
31     /** Don't use a cache to satisfy this request. */
32     private boolean noCache;
33     private int maxAgeSeconds = -1;
34     private int maxStaleSeconds = -1;
35     private int minFreshSeconds = -1;
36 
37     /**
38      * This field's name "only-if-cached" is misleading. It actually means "do
39      * not use the network". It is set by a client who only wants to make a
40      * request if it can be fully satisfied by the cache. Cached responses that
41      * would require validation (ie. conditional gets) are not permitted if this
42      * header is set.
43      */
44     private boolean onlyIfCached;
45 
46     /**
47      * True if the request contains an authorization field. Although this isn't
48      * necessarily a shared cache, it follows the spec's strict requirements for
49      * shared caches.
50      */
51     private boolean hasAuthorization;
52 
53     private int contentLength = -1;
54     private String transferEncoding;
55     private String userAgent;
56     private String host;
57     private String connection;
58     private String acceptEncoding;
59     private String contentType;
60     private String ifModifiedSince;
61     private String ifNoneMatch;
62     private String proxyAuthorization;
63 
RequestHeaders(URI uri, RawHeaders headers)64     public RequestHeaders(URI uri, RawHeaders headers) {
65         this.uri = uri;
66         this.headers = headers;
67 
68         HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
69             @Override public void handle(String directive, String parameter) {
70                 if (directive.equalsIgnoreCase("no-cache")) {
71                     noCache = true;
72                 } else if (directive.equalsIgnoreCase("max-age")) {
73                     maxAgeSeconds = HeaderParser.parseSeconds(parameter);
74                 } else if (directive.equalsIgnoreCase("max-stale")) {
75                     maxStaleSeconds = HeaderParser.parseSeconds(parameter);
76                 } else if (directive.equalsIgnoreCase("min-fresh")) {
77                     minFreshSeconds = HeaderParser.parseSeconds(parameter);
78                 } else if (directive.equalsIgnoreCase("only-if-cached")) {
79                     onlyIfCached = true;
80                 }
81             }
82         };
83 
84         for (int i = 0; i < headers.length(); i++) {
85             String fieldName = headers.getFieldName(i);
86             String value = headers.getValue(i);
87             if ("Cache-Control".equalsIgnoreCase(fieldName)) {
88                 HeaderParser.parseCacheControl(value, handler);
89             } else if ("Pragma".equalsIgnoreCase(fieldName)) {
90                 if (value.equalsIgnoreCase("no-cache")) {
91                     noCache = true;
92                 }
93             } else if ("If-None-Match".equalsIgnoreCase(fieldName)) {
94                 ifNoneMatch = value;
95             } else if ("If-Modified-Since".equalsIgnoreCase(fieldName)) {
96                 ifModifiedSince = value;
97             } else if ("Authorization".equalsIgnoreCase(fieldName)) {
98                 hasAuthorization = true;
99             } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
100                 try {
101                     contentLength = Integer.parseInt(value);
102                 } catch (NumberFormatException ignored) {
103                 }
104             } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
105                 transferEncoding = value;
106             } else if ("User-Agent".equalsIgnoreCase(fieldName)) {
107                 userAgent = value;
108             } else if ("Host".equalsIgnoreCase(fieldName)) {
109                 host = value;
110             } else if ("Connection".equalsIgnoreCase(fieldName)) {
111                 connection = value;
112             } else if ("Accept-Encoding".equalsIgnoreCase(fieldName)) {
113                 acceptEncoding = value;
114             } else if ("Content-Type".equalsIgnoreCase(fieldName)) {
115                 contentType = value;
116             } else if ("Proxy-Authorization".equalsIgnoreCase(fieldName)) {
117                 proxyAuthorization = value;
118             }
119         }
120     }
121 
isChunked()122     public boolean isChunked() {
123         return "chunked".equalsIgnoreCase(transferEncoding);
124     }
125 
hasConnectionClose()126     public boolean hasConnectionClose() {
127         return "close".equalsIgnoreCase(connection);
128     }
129 
getUri()130     public URI getUri() {
131         return uri;
132     }
133 
getHeaders()134     public RawHeaders getHeaders() {
135         return headers;
136     }
137 
isNoCache()138     public boolean isNoCache() {
139         return noCache;
140     }
141 
getMaxAgeSeconds()142     public int getMaxAgeSeconds() {
143         return maxAgeSeconds;
144     }
145 
getMaxStaleSeconds()146     public int getMaxStaleSeconds() {
147         return maxStaleSeconds;
148     }
149 
getMinFreshSeconds()150     public int getMinFreshSeconds() {
151         return minFreshSeconds;
152     }
153 
isOnlyIfCached()154     public boolean isOnlyIfCached() {
155         return onlyIfCached;
156     }
157 
hasAuthorization()158     public boolean hasAuthorization() {
159         return hasAuthorization;
160     }
161 
getContentLength()162     public int getContentLength() {
163         return contentLength;
164     }
165 
getTransferEncoding()166     public String getTransferEncoding() {
167         return transferEncoding;
168     }
169 
getUserAgent()170     public String getUserAgent() {
171         return userAgent;
172     }
173 
getHost()174     public String getHost() {
175         return host;
176     }
177 
getConnection()178     public String getConnection() {
179         return connection;
180     }
181 
getAcceptEncoding()182     public String getAcceptEncoding() {
183         return acceptEncoding;
184     }
185 
getContentType()186     public String getContentType() {
187         return contentType;
188     }
189 
getIfModifiedSince()190     public String getIfModifiedSince() {
191         return ifModifiedSince;
192     }
193 
getIfNoneMatch()194     public String getIfNoneMatch() {
195         return ifNoneMatch;
196     }
197 
getProxyAuthorization()198     public String getProxyAuthorization() {
199         return proxyAuthorization;
200     }
201 
setChunked()202     public void setChunked() {
203         if (this.transferEncoding != null) {
204             headers.removeAll("Transfer-Encoding");
205         }
206         headers.add("Transfer-Encoding", "chunked");
207         this.transferEncoding = "chunked";
208     }
209 
setContentLength(int contentLength)210     public void setContentLength(int contentLength) {
211         if (this.contentLength != -1) {
212             headers.removeAll("Content-Length");
213         }
214         headers.add("Content-Length", Integer.toString(contentLength));
215         this.contentLength = contentLength;
216     }
217 
setUserAgent(String userAgent)218     public void setUserAgent(String userAgent) {
219         if (this.userAgent != null) {
220             headers.removeAll("User-Agent");
221         }
222         headers.add("User-Agent", userAgent);
223         this.userAgent = userAgent;
224     }
225 
setHost(String host)226     public void setHost(String host) {
227         if (this.host != null) {
228             headers.removeAll("Host");
229         }
230         headers.add("Host", host);
231         this.host = host;
232     }
233 
setConnection(String connection)234     public void setConnection(String connection) {
235         if (this.connection != null) {
236             headers.removeAll("Connection");
237         }
238         headers.add("Connection", connection);
239         this.connection = connection;
240     }
241 
setAcceptEncoding(String acceptEncoding)242     public void setAcceptEncoding(String acceptEncoding) {
243         if (this.acceptEncoding != null) {
244             headers.removeAll("Accept-Encoding");
245         }
246         headers.add("Accept-Encoding", acceptEncoding);
247         this.acceptEncoding = acceptEncoding;
248     }
249 
setContentType(String contentType)250     public void setContentType(String contentType) {
251         if (this.contentType != null) {
252             headers.removeAll("Content-Type");
253         }
254         headers.add("Content-Type", contentType);
255         this.contentType = contentType;
256     }
257 
setIfModifiedSince(Date date)258     public void setIfModifiedSince(Date date) {
259         if (ifModifiedSince != null) {
260             headers.removeAll("If-Modified-Since");
261         }
262         String formattedDate = HttpDate.format(date);
263         headers.add("If-Modified-Since", formattedDate);
264         ifModifiedSince = formattedDate;
265     }
266 
setIfNoneMatch(String ifNoneMatch)267     public void setIfNoneMatch(String ifNoneMatch) {
268         if (this.ifNoneMatch != null) {
269             headers.removeAll("If-None-Match");
270         }
271         headers.add("If-None-Match", ifNoneMatch);
272         this.ifNoneMatch = ifNoneMatch;
273     }
274 
275     /**
276      * Returns true if the request contains conditions that save the server from
277      * sending a response that the client has locally. When the caller adds
278      * conditions, this cache won't participate in the request.
279      */
hasConditions()280     public boolean hasConditions() {
281         return ifModifiedSince != null || ifNoneMatch != null;
282     }
283 
addCookies(Map<String, List<String>> allCookieHeaders)284     public void addCookies(Map<String, List<String>> allCookieHeaders) {
285         for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) {
286             String key = entry.getKey();
287             if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) {
288                 headers.addAll(key, entry.getValue());
289             }
290         }
291     }
292 }
293