/*
 * Copyright (C) 2013 Square, Inc.
 *
 * 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 okhttp3;

import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import okhttp3.internal.Util;
import okhttp3.internal.http.HttpMethod;

An HTTP request. Instances of this class are immutable if their body is null or itself immutable.
/** * An HTTP request. Instances of this class are immutable if their {@link #body} is null or itself * immutable. */
public final class Request { final HttpUrl url; final String method; final Headers headers; final @Nullable RequestBody body; final Map<Class<?>, Object> tags; private volatile @Nullable CacheControl cacheControl; // Lazily initialized. Request(Builder builder) { this.url = builder.url; this.method = builder.method; this.headers = builder.headers.build(); this.body = builder.body; this.tags = Util.immutableMap(builder.tags); } public HttpUrl url() { return url; } public String method() { return method; } public Headers headers() { return headers; } public @Nullable String header(String name) { return headers.get(name); } public List<String> headers(String name) { return headers.values(name); } public @Nullable RequestBody body() { return body; }
Returns the tag attached with Object.class as a key, or null if no tag is attached with that key.

Prior to OkHttp 3.11, this method never returned null if no tag was attached. Instead it returned either this request, or the request upon which this request was derived with newBuilder().

/** * Returns the tag attached with {@code Object.class} as a key, or null if no tag is attached with * that key. * * <p>Prior to OkHttp 3.11, this method never returned null if no tag was attached. Instead it * returned either this request, or the request upon which this request was derived with {@link * #newBuilder()}. */
public @Nullable Object tag() { return tag(Object.class); }
Returns the tag attached with type as a key, or null if no tag is attached with that key.
/** * Returns the tag attached with {@code type} as a key, or null if no tag is attached with that * key. */
public @Nullable <T> T tag(Class<? extends T> type) { return type.cast(tags.get(type)); } public Builder newBuilder() { return new Builder(this); }
Returns the cache control directives for this response. This is never null, even if this response contains no Cache-Control header.
/** * Returns the cache control directives for this response. This is never null, even if this * response contains no {@code Cache-Control} header. */
public CacheControl cacheControl() { CacheControl result = cacheControl; return result != null ? result : (cacheControl = CacheControl.parse(headers)); } public boolean isHttps() { return url.isHttps(); } @Override public String toString() { return "Request{method=" + method + ", url=" + url + ", tags=" + tags + '}'; } public static class Builder { @Nullable HttpUrl url; String method; Headers.Builder headers; @Nullable RequestBody body;
A mutable map of tags, or an immutable empty map if we don't have any.
/** A mutable map of tags, or an immutable empty map if we don't have any. */
Map<Class<?>, Object> tags = Collections.emptyMap(); public Builder() { this.method = "GET"; this.headers = new Headers.Builder(); } Builder(Request request) { this.url = request.url; this.method = request.method; this.body = request.body; this.tags = request.tags.isEmpty() ? Collections.<Class<?>, Object>emptyMap() : new LinkedHashMap<>(request.tags); this.headers = request.headers.newBuilder(); } public Builder url(HttpUrl url) { if (url == null) throw new NullPointerException("url == null"); this.url = url; return this; }
Sets the URL target of this request.
Throws:
  • IllegalArgumentException – if url is not a valid HTTP or HTTPS URL. Avoid this exception by calling HttpUrl.parse; it returns null for invalid URLs.
/** * Sets the URL target of this request. * * @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this * exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs. */
public Builder url(String url) { if (url == null) throw new NullPointerException("url == null"); // Silently replace web socket URLs with HTTP URLs. if (url.regionMatches(true, 0, "ws:", 0, 3)) { url = "http:" + url.substring(3); } else if (url.regionMatches(true, 0, "wss:", 0, 4)) { url = "https:" + url.substring(4); } return url(HttpUrl.get(url)); }
Sets the URL target of this request.
Throws:
  • IllegalArgumentException – if the scheme of url is not http or https.
/** * Sets the URL target of this request. * * @throws IllegalArgumentException if the scheme of {@code url} is not {@code http} or {@code * https}. */
public Builder url(URL url) { if (url == null) throw new NullPointerException("url == null"); return url(HttpUrl.get(url.toString())); }
Sets the header named name to value. If this request already has any headers with that name, they are all replaced.
/** * Sets the header named {@code name} to {@code value}. If this request already has any headers * with that name, they are all replaced. */
public Builder header(String name, String value) { headers.set(name, value); return this; }
Adds a header with name and value. Prefer this method for multiply-valued headers like "Cookie".

Note that for some headers including Content-Length and Content-Encoding, OkHttp may replace value with a header derived from the request body.

/** * Adds a header with {@code name} and {@code value}. Prefer this method for multiply-valued * headers like "Cookie". * * <p>Note that for some headers including {@code Content-Length} and {@code Content-Encoding}, * OkHttp may replace {@code value} with a header derived from the request body. */
public Builder addHeader(String name, String value) { headers.add(name, value); return this; }
Removes all headers named name on this builder.
/** Removes all headers named {@code name} on this builder. */
public Builder removeHeader(String name) { headers.removeAll(name); return this; }
Removes all headers on this builder and adds headers.
/** Removes all headers on this builder and adds {@code headers}. */
public Builder headers(Headers headers) { this.headers = headers.newBuilder(); return this; }
Sets this request's Cache-Control header, replacing any cache control headers already present. If cacheControl doesn't define any directives, this clears this request's cache-control headers.
/** * Sets this request's {@code Cache-Control} header, replacing any cache control headers already * present. If {@code cacheControl} doesn't define any directives, this clears this request's * cache-control headers. */
public Builder cacheControl(CacheControl cacheControl) { String value = cacheControl.toString(); if (value.isEmpty()) return removeHeader("Cache-Control"); return header("Cache-Control", value); } public Builder get() { return method("GET", null); } public Builder head() { return method("HEAD", null); } public Builder post(RequestBody body) { return method("POST", body); } public Builder delete(@Nullable RequestBody body) { return method("DELETE", body); } public Builder delete() { return delete(Util.EMPTY_REQUEST); } public Builder put(RequestBody body) { return method("PUT", body); } public Builder patch(RequestBody body) { return method("PATCH", body); } public Builder method(String method, @Nullable RequestBody body) { if (method == null) throw new NullPointerException("method == null"); if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0"); if (body != null && !HttpMethod.permitsRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must not have a request body."); } if (body == null && HttpMethod.requiresRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must have a request body."); } this.method = method; this.body = body; return this; }
Attaches tag to the request using Object.class as a key.
/** Attaches {@code tag} to the request using {@code Object.class} as a key. */
public Builder tag(@Nullable Object tag) { return tag(Object.class, tag); }
Attaches tag to the request using type as a key. Tags can be read from a request using Request.tag. Use null to remove any existing tag assigned for type.

Use this API to attach timing, debugging, or other application data to a request so that you may read it in interceptors, event listeners, or callbacks.

/** * Attaches {@code tag} to the request using {@code type} as a key. Tags can be read from a * request using {@link Request#tag}. Use null to remove any existing tag assigned for {@code * type}. * * <p>Use this API to attach timing, debugging, or other application data to a request so that * you may read it in interceptors, event listeners, or callbacks. */
public <T> Builder tag(Class<? super T> type, @Nullable T tag) { if (type == null) throw new NullPointerException("type == null"); if (tag == null) { tags.remove(type); } else { if (tags.isEmpty()) tags = new LinkedHashMap<>(); tags.put(type, type.cast(tag)); } return this; } public Request build() { if (url == null) throw new IllegalStateException("url == null"); return new Request(this); } } }