| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package libcore.net.http; |
| |
| import java.net.URI; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Parsed HTTP request headers. |
| */ |
| public final class RequestHeaders { |
| private final URI uri; |
| private final RawHeaders headers; |
| |
| /** Don't use a cache to satisfy this request. */ |
| private boolean noCache; |
| private int maxAgeSeconds = -1; |
| private int maxStaleSeconds = -1; |
| private int minFreshSeconds = -1; |
| |
| /** |
| * This field's name "only-if-cached" is misleading. It actually means "do |
| * not use the network". It is set by a client who only wants to make a |
| * request if it can be fully satisfied by the cache. Cached responses that |
| * would require validation (ie. conditional gets) are not permitted if this |
| * header is set. |
| */ |
| private boolean onlyIfCached; |
| |
| /** |
| * True if the request contains an authorization field. Although this isn't |
| * necessarily a shared cache, it follows the spec's strict requirements for |
| * shared caches. |
| */ |
| private boolean hasAuthorization; |
| |
| private int contentLength = -1; |
| private String transferEncoding; |
| private String userAgent; |
| private String host; |
| private String connection; |
| private String acceptEncoding; |
| private String contentType; |
| private String ifModifiedSince; |
| private String ifNoneMatch; |
| private String proxyAuthorization; |
| |
| public RequestHeaders(URI uri, RawHeaders headers) { |
| this.uri = uri; |
| this.headers = headers; |
| |
| HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() { |
| @Override public void handle(String directive, String parameter) { |
| if (directive.equalsIgnoreCase("no-cache")) { |
| noCache = true; |
| } else if (directive.equalsIgnoreCase("max-age")) { |
| maxAgeSeconds = HeaderParser.parseSeconds(parameter); |
| } else if (directive.equalsIgnoreCase("max-stale")) { |
| maxStaleSeconds = HeaderParser.parseSeconds(parameter); |
| } else if (directive.equalsIgnoreCase("min-fresh")) { |
| minFreshSeconds = HeaderParser.parseSeconds(parameter); |
| } else if (directive.equalsIgnoreCase("only-if-cached")) { |
| onlyIfCached = true; |
| } |
| } |
| }; |
| |
| for (int i = 0; i < headers.length(); i++) { |
| String fieldName = headers.getFieldName(i); |
| String value = headers.getValue(i); |
| if ("Cache-Control".equalsIgnoreCase(fieldName)) { |
| HeaderParser.parseCacheControl(value, handler); |
| } else if ("Pragma".equalsIgnoreCase(fieldName)) { |
| if (value.equalsIgnoreCase("no-cache")) { |
| noCache = true; |
| } |
| } else if ("If-None-Match".equalsIgnoreCase(fieldName)) { |
| ifNoneMatch = value; |
| } else if ("If-Modified-Since".equalsIgnoreCase(fieldName)) { |
| ifModifiedSince = value; |
| } else if ("Authorization".equalsIgnoreCase(fieldName)) { |
| hasAuthorization = true; |
| } else if ("Content-Length".equalsIgnoreCase(fieldName)) { |
| try { |
| contentLength = Integer.parseInt(value); |
| } catch (NumberFormatException ignored) { |
| } |
| } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) { |
| transferEncoding = value; |
| } else if ("User-Agent".equalsIgnoreCase(fieldName)) { |
| userAgent = value; |
| } else if ("Host".equalsIgnoreCase(fieldName)) { |
| host = value; |
| } else if ("Connection".equalsIgnoreCase(fieldName)) { |
| connection = value; |
| } else if ("Accept-Encoding".equalsIgnoreCase(fieldName)) { |
| acceptEncoding = value; |
| } else if ("Content-Type".equalsIgnoreCase(fieldName)) { |
| contentType = value; |
| } else if ("Proxy-Authorization".equalsIgnoreCase(fieldName)) { |
| proxyAuthorization = value; |
| } |
| } |
| } |
| |
| public boolean isChunked() { |
| return "chunked".equalsIgnoreCase(transferEncoding); |
| } |
| |
| public boolean hasConnectionClose() { |
| return "close".equalsIgnoreCase(connection); |
| } |
| |
| public URI getUri() { |
| return uri; |
| } |
| |
| public RawHeaders getHeaders() { |
| return headers; |
| } |
| |
| public boolean isNoCache() { |
| return noCache; |
| } |
| |
| public int getMaxAgeSeconds() { |
| return maxAgeSeconds; |
| } |
| |
| public int getMaxStaleSeconds() { |
| return maxStaleSeconds; |
| } |
| |
| public int getMinFreshSeconds() { |
| return minFreshSeconds; |
| } |
| |
| public boolean isOnlyIfCached() { |
| return onlyIfCached; |
| } |
| |
| public boolean hasAuthorization() { |
| return hasAuthorization; |
| } |
| |
| public int getContentLength() { |
| return contentLength; |
| } |
| |
| public String getTransferEncoding() { |
| return transferEncoding; |
| } |
| |
| public String getUserAgent() { |
| return userAgent; |
| } |
| |
| public String getHost() { |
| return host; |
| } |
| |
| public String getConnection() { |
| return connection; |
| } |
| |
| public String getAcceptEncoding() { |
| return acceptEncoding; |
| } |
| |
| public String getContentType() { |
| return contentType; |
| } |
| |
| public String getIfModifiedSince() { |
| return ifModifiedSince; |
| } |
| |
| public String getIfNoneMatch() { |
| return ifNoneMatch; |
| } |
| |
| public String getProxyAuthorization() { |
| return proxyAuthorization; |
| } |
| |
| public void setChunked() { |
| if (this.transferEncoding != null) { |
| headers.removeAll("Transfer-Encoding"); |
| } |
| headers.add("Transfer-Encoding", "chunked"); |
| this.transferEncoding = "chunked"; |
| } |
| |
| public void setContentLength(int contentLength) { |
| if (this.contentLength != -1) { |
| headers.removeAll("Content-Length"); |
| } |
| headers.add("Content-Length", Integer.toString(contentLength)); |
| this.contentLength = contentLength; |
| } |
| |
| public void setUserAgent(String userAgent) { |
| if (this.userAgent != null) { |
| headers.removeAll("User-Agent"); |
| } |
| headers.add("User-Agent", userAgent); |
| this.userAgent = userAgent; |
| } |
| |
| public void setHost(String host) { |
| if (this.host != null) { |
| headers.removeAll("Host"); |
| } |
| headers.add("Host", host); |
| this.host = host; |
| } |
| |
| public void setConnection(String connection) { |
| if (this.connection != null) { |
| headers.removeAll("Connection"); |
| } |
| headers.add("Connection", connection); |
| this.connection = connection; |
| } |
| |
| public void setAcceptEncoding(String acceptEncoding) { |
| if (this.acceptEncoding != null) { |
| headers.removeAll("Accept-Encoding"); |
| } |
| headers.add("Accept-Encoding", acceptEncoding); |
| this.acceptEncoding = acceptEncoding; |
| } |
| |
| public void setContentType(String contentType) { |
| if (this.contentType != null) { |
| headers.removeAll("Content-Type"); |
| } |
| headers.add("Content-Type", contentType); |
| this.contentType = contentType; |
| } |
| |
| public void setIfModifiedSince(Date date) { |
| if (ifModifiedSince != null) { |
| headers.removeAll("If-Modified-Since"); |
| } |
| String formattedDate = HttpDate.format(date); |
| headers.add("If-Modified-Since", formattedDate); |
| ifModifiedSince = formattedDate; |
| } |
| |
| public void setIfNoneMatch(String ifNoneMatch) { |
| if (this.ifNoneMatch != null) { |
| headers.removeAll("If-None-Match"); |
| } |
| headers.add("If-None-Match", ifNoneMatch); |
| this.ifNoneMatch = ifNoneMatch; |
| } |
| |
| /** |
| * Returns true if the request contains conditions that save the server from |
| * sending a response that the client has locally. When the caller adds |
| * conditions, this cache won't participate in the request. |
| */ |
| public boolean hasConditions() { |
| return ifModifiedSince != null || ifNoneMatch != null; |
| } |
| |
| public void addCookies(Map<String, List<String>> allCookieHeaders) { |
| for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) { |
| String key = entry.getKey(); |
| if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) { |
| headers.addAll(key, entry.getValue()); |
| } |
| } |
| } |
| } |