connectionSpecs() {
118 | return connectionSpecs;
119 | }
120 |
121 | /**
122 | * Returns this address's proxy selector. Only used if the proxy is null. If none of this
123 | * selector's proxies are reachable, a direct connection will be attempted.
124 | */
125 | public ProxySelector proxySelector() {
126 | return proxySelector;
127 | }
128 |
129 | /**
130 | * Returns this address's explicitly-specified HTTP proxy, or null to delegate to the {@linkplain
131 | * #proxySelector proxy selector}.
132 | */
133 | public Proxy proxy() {
134 | return proxy;
135 | }
136 |
137 | /** Returns the SSL socket factory, or null if this is not an HTTPS address. */
138 | public SSLSocketFactory sslSocketFactory() {
139 | return sslSocketFactory;
140 | }
141 |
142 | /** Returns the hostname verifier, or null if this is not an HTTPS address. */
143 | public HostnameVerifier hostnameVerifier() {
144 | return hostnameVerifier;
145 | }
146 |
147 | /** Returns this address's certificate pinner, or null if this is not an HTTPS address. */
148 | public CertificatePinner certificatePinner() {
149 | return certificatePinner;
150 | }
151 |
152 | @Override public boolean equals(Object other) {
153 | if (other instanceof Address) {
154 | Address that = (Address) other;
155 | return this.url.equals(that.url)
156 | && this.dns.equals(that.dns)
157 | && this.proxyAuthenticator.equals(that.proxyAuthenticator)
158 | && this.protocols.equals(that.protocols)
159 | && this.connectionSpecs.equals(that.connectionSpecs)
160 | && this.proxySelector.equals(that.proxySelector)
161 | && equal(this.proxy, that.proxy)
162 | && equal(this.sslSocketFactory, that.sslSocketFactory)
163 | && equal(this.hostnameVerifier, that.hostnameVerifier)
164 | && equal(this.certificatePinner, that.certificatePinner);
165 | }
166 | return false;
167 | }
168 |
169 | @Override public int hashCode() {
170 | int result = 17;
171 | result = 31 * result + url.hashCode();
172 | result = 31 * result + dns.hashCode();
173 | result = 31 * result + proxyAuthenticator.hashCode();
174 | result = 31 * result + protocols.hashCode();
175 | result = 31 * result + connectionSpecs.hashCode();
176 | result = 31 * result + proxySelector.hashCode();
177 | result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
178 | result = 31 * result + (sslSocketFactory != null ? sslSocketFactory.hashCode() : 0);
179 | result = 31 * result + (hostnameVerifier != null ? hostnameVerifier.hashCode() : 0);
180 | result = 31 * result + (certificatePinner != null ? certificatePinner.hashCode() : 0);
181 | return result;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Authenticator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * Responds to an authentication challenge from either a remote web server or a proxy server.
22 | * Implementations may either attempt to satisfy the challenge by returning a request that includes
23 | * an authorization header, or they may refuse the challenge by returning null. In this case the
24 | * unauthenticated response will be returned to the caller that triggered it.
25 | *
26 | * When authentication is requested by an origin server, the response code is 401 and the
27 | * implementation should respond with a new request that sets the "Authorization" header.
28 | *
{@code
29 | *
30 | * String credential = Credentials.basic(...)
31 | * return response.request().newBuilder()
32 | * .header("Authorization", credential)
33 | * .build();
34 | * }
35 | *
36 | * Whn authentication is requested by a proxy server, the response code is 407 and the
37 | * implementation should respond with a new request that sets the "Proxy-Authorization" header.
38 | *
{@code
39 | *
40 | * String credential = Credentials.basic(...)
41 | * return response.request().newBuilder()
42 | * .header("Proxy-Authorization", credential)
43 | * .build();
44 | * }
45 | *
46 | * Applications may configure OkHttp with an authenticator for origin servers, or proxy servers,
47 | * or both.
48 | */
49 | public interface Authenticator {
50 | /** An authenticator that knows no credentials and makes no attempt to authenticate. */
51 | Authenticator NONE = new Authenticator() {
52 | @Override public Request authenticate(Route route, Response response) {
53 | return null;
54 | }
55 | };
56 |
57 | /**
58 | * Returns a request that includes a credential to satisfy an authentication challenge in {@code
59 | * response}. Returns null if the challenge cannot be satisfied.
60 | */
61 | Request authenticate(Route route, Response response) throws IOException;
62 | }
63 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Call.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * A call is a request that has been prepared for execution. A call can be canceled. As this object
22 | * represents a single request/response pair (stream), it cannot be executed twice.
23 | */
24 | public interface Call {
25 | /** Returns the original request that initiated this call. */
26 | Request request();
27 |
28 | /**
29 | * Invokes the request immediately, and blocks until the response can be processed or is in
30 | * error.
31 | *
32 | *
The caller may read the response body with the response's {@link Response#body} method. To
33 | * facilitate connection recycling, callers should always {@link ResponseBody#close() close the
34 | * response body}.
35 | *
36 | *
Note that transport-layer success (receiving a HTTP response code, headers and body) does
37 | * not necessarily indicate application-layer success: {@code response} may still indicate an
38 | * unhappy HTTP response code like 404 or 500.
39 | *
40 | * @throws IOException if the request could not be executed due to cancellation, a connectivity
41 | * problem or timeout. Because networks can fail during an exchange, it is possible that the
42 | * remote server accepted the request before the failure.
43 | * @throws IllegalStateException when the call has already been executed.
44 | */
45 | Response execute() throws IOException;
46 |
47 | /**
48 | * Schedules the request to be executed at some point in the future.
49 | *
50 | *
The {@link OkHttpClient#dispatcher dispatcher} defines when the request will run: usually
51 | * immediately unless there are several other requests currently being executed.
52 | *
53 | *
This client will later call back {@code responseCallback} with either an HTTP response or a
54 | * failure exception. If you {@link #cancel} a request before it completes the callback will not
55 | * be invoked.
56 | *
57 | * @throws IllegalStateException when the call has already been executed.
58 | */
59 | void enqueue(Callback responseCallback);
60 |
61 | /** Cancels the request, if possible. Requests that are already complete cannot be canceled. */
62 | void cancel();
63 |
64 | /**
65 | * Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain
66 | * #enqueue(Callback) enqueued}. It is an error to execute a call more than once.
67 | */
68 | boolean isExecuted();
69 |
70 | boolean isCanceled();
71 |
72 | interface Factory {
73 | Call newCall(Request request);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Callback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 |
20 | public interface Callback {
21 | /**
22 | * Called when the request could not be executed due to cancellation, a connectivity problem or
23 | * timeout. Because networks can fail during an exchange, it is possible that the remote server
24 | * accepted the request before the failure.
25 | */
26 | void onFailure(Call call, IOException e);
27 |
28 | /**
29 | * Called when the HTTP response was successfully returned by the remote server. The callback may
30 | * proceed to read the response body with {@link Response#body}. The response is still live until
31 | * its response body is closed with {@code response.body().close()}. The recipient of the callback
32 | * may even consume the response body on another thread.
33 | *
34 | *
Note that transport-layer success (receiving a HTTP response code, headers and body) does
35 | * not necessarily indicate application-layer success: {@code response} may still indicate an
36 | * unhappy HTTP response code like 404 or 500.
37 | */
38 | void onResponse(Call call, Response response) throws IOException;
39 | }
40 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Challenge.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import okhttp3.internal.Util;
19 |
20 | /** An RFC 2617 challenge. */
21 | public final class Challenge {
22 | private final String scheme;
23 | private final String realm;
24 |
25 | public Challenge(String scheme, String realm) {
26 | this.scheme = scheme;
27 | this.realm = realm;
28 | }
29 |
30 | /** Returns the authentication scheme, like {@code Basic}. */
31 | public String scheme() {
32 | return scheme;
33 | }
34 |
35 | /** Returns the protection space. */
36 | public String realm() {
37 | return realm;
38 | }
39 |
40 | @Override public boolean equals(Object o) {
41 | return o instanceof Challenge
42 | && Util.equal(scheme, ((Challenge) o).scheme)
43 | && Util.equal(realm, ((Challenge) o).realm);
44 | }
45 |
46 | @Override public int hashCode() {
47 | int result = 29;
48 | result = 31 * result + (realm != null ? realm.hashCode() : 0);
49 | result = 31 * result + (scheme != null ? scheme.hashCode() : 0);
50 | return result;
51 | }
52 |
53 | @Override public String toString() {
54 | return scheme + " realm=\"" + realm + "\"";
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Connection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package okhttp3;
18 |
19 | import java.net.Socket;
20 |
21 | /**
22 | * The sockets and streams of an HTTP, HTTPS, or HTTPS+SPDY connection. May be used for multiple
23 | * HTTP request/response exchanges. Connections may be direct to the origin server or via a proxy.
24 | *
25 | *
Typically instances of this class are created, connected and exercised automatically by the
26 | * HTTP client. Applications may use this class to monitor HTTP connections as members of a
27 | * {@linkplain ConnectionPool connection pool}.
28 | *
29 | *
Do not confuse this class with the misnamed {@code HttpURLConnection}, which isn't so much a
30 | * connection as a single request/response exchange.
31 | *
32 | *
Modern TLS
33 | *
34 | * There are tradeoffs when selecting which options to include when negotiating a secure
35 | * connection to a remote host. Newer TLS options are quite useful:
36 | *
37 | *
38 | * - Server Name Indication (SNI) enables one IP address to negotiate secure connections for
39 | * multiple domain names.
40 | *
- Application Layer Protocol Negotiation (ALPN) enables the HTTPS port (443) to be used for
41 | * different HTTP and SPDY protocols.
42 | *
43 | *
44 | * Unfortunately, older HTTPS servers refuse to connect when such options are presented. Rather
45 | * than avoiding these options entirely, this class allows a connection to be attempted with modern
46 | * options and then retried without them should the attempt fail.
47 | *
48 | *
Connection Reuse
49 | *
50 | * Each connection can carry a varying number streams, depending on the underlying protocol being
51 | * used. HTTP/1.x connections can carry either zero or one streams. HTTP/2 connections can carry any
52 | * number of streams, dynamically configured with {@code SETTINGS_MAX_CONCURRENT_STREAMS}. A
53 | * connection currently carrying zero streams is an idle stream. We keep it alive because reusing an
54 | * existing connection is typically faster than establishing a new one.
55 | *
56 | *
When a single logical call requires multiple streams due to redirects or authorization
57 | * challenges, we prefer to use the same physical connection for all streams in the sequence. There
58 | * are potential performance and behavior consequences to this preference. To support this feature,
59 | * this class separates allocations from streams. An allocation is created by a call,
60 | * used for one or more streams, and then released. An allocated connection won't be stolen by other
61 | * calls while a redirect or authorization challenge is being handled.
62 | *
63 | *
When the maximum concurrent streams limit is reduced, some allocations will be rescinded.
64 | * Attempting to create new streams on these allocations will fail.
65 | *
66 | *
Note that an allocation may be released before its stream is completed. This is intended to
67 | * make bookkeeping easier for the caller: releasing the allocation as soon as the terminal stream
68 | * has been found. But only complete the stream once its data stream has been exhausted.
69 | */
70 | public interface Connection {
71 | /** Returns the route used by this connection. */
72 | Route route();
73 |
74 | /**
75 | * Returns the socket that this connection is using. Returns an {@linkplain
76 | * javax.net.ssl.SSLSocket SSL socket} if this connection is HTTPS. If this is an HTTP/2 or SPDY
77 | * connection the socket may be shared by multiple concurrent calls.
78 | */
79 | Socket socket();
80 |
81 | /**
82 | * Returns the TLS handshake used to establish this connection, or null if the connection is not
83 | * HTTPS.
84 | */
85 | Handshake handshake();
86 |
87 | /**
88 | * Returns the protocol negotiated by this connection, or {@link Protocol#HTTP_1_1} if no protocol
89 | * has been negotiated. This method returns {@link Protocol#HTTP_1_1} even if the remote peer is
90 | * using {@link Protocol#HTTP_1_0}.
91 | */
92 | Protocol protocol();
93 | }
94 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/CookieJar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | /**
22 | * Provides policy and persistence for HTTP cookies.
23 | *
24 | *
As policy, implementations of this interface are responsible for selecting which cookies to
25 | * accept and which to reject. A reasonable policy is to reject all cookies, though that may be
26 | * interfere with session-based authentication schemes that require cookies.
27 | *
28 | *
As persistence, implementations of this interface must also provide storage of cookies. Simple
29 | * implementations may store cookies in memory; sophisticated ones may use the file system or
30 | * database to hold accepted cookies. The cookie storage model specifies
32 | * policies for updating and expiring cookies.
33 | */
34 | public interface CookieJar {
35 | /** A cookie jar that never accepts any cookies. */
36 | CookieJar NO_COOKIES = new CookieJar() {
37 | @Override public void saveFromResponse(HttpUrl url, List cookies) {
38 | }
39 |
40 | @Override public List loadForRequest(HttpUrl url) {
41 | return Collections.emptyList();
42 | }
43 | };
44 |
45 | /**
46 | * Saves {@code cookies} from an HTTP response to this store according to this jar's policy.
47 | *
48 | * Note that this method may be called a second time for a single HTTP response if the response
49 | * includes a trailer. For this obscure HTTP feature, {@code cookies} contains only the trailer's
50 | * cookies.
51 | */
52 | void saveFromResponse(HttpUrl url, List cookies);
53 |
54 | /**
55 | * Load cookies from the jar for an HTTP request to {@code url}. This method returns a possibly
56 | * empty list of cookies for the network request.
57 | *
58 | * Simple implementations will return the accepted cookies that have not yet expired and that
59 | * {@linkplain Cookie#matches match} {@code url}.
60 | */
61 | List loadForRequest(HttpUrl url);
62 | }
63 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Credentials.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.UnsupportedEncodingException;
19 | import okio.ByteString;
20 |
21 | /** Factory for HTTP authorization credentials. */
22 | public final class Credentials {
23 | private Credentials() {
24 | }
25 |
26 | /** Returns an auth credential for the Basic scheme. */
27 | public static String basic(String userName, String password) {
28 | try {
29 | String usernameAndPassword = userName + ":" + password;
30 | byte[] bytes = usernameAndPassword.getBytes("ISO-8859-1");
31 | String encoded = ByteString.of(bytes).base64();
32 | return "Basic " + encoded;
33 | } catch (UnsupportedEncodingException e) {
34 | throw new AssertionError();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Dispatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.util.ArrayDeque;
19 | import java.util.ArrayList;
20 | import java.util.Collections;
21 | import java.util.Deque;
22 | import java.util.Iterator;
23 | import java.util.List;
24 | import java.util.concurrent.ExecutorService;
25 | import java.util.concurrent.SynchronousQueue;
26 | import java.util.concurrent.ThreadPoolExecutor;
27 | import java.util.concurrent.TimeUnit;
28 | import okhttp3.RealCall.AsyncCall;
29 | import okhttp3.internal.Util;
30 |
31 | /**
32 | * Policy on when async requests are executed.
33 | *
34 | * Each dispatcher uses an {@link ExecutorService} to run calls internally. If you supply your
35 | * own executor, it should be able to run {@linkplain #getMaxRequests the configured maximum} number
36 | * of calls concurrently.
37 | */
38 | public final class Dispatcher {
39 | private int maxRequests = 64;
40 | private int maxRequestsPerHost = 5;
41 |
42 | /** Executes calls. Created lazily. */
43 | private ExecutorService executorService;
44 |
45 | /** Ready async calls in the order they'll be run. */
46 | private final Deque readyAsyncCalls = new ArrayDeque<>();
47 |
48 | /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
49 | private final Deque runningAsyncCalls = new ArrayDeque<>();
50 |
51 | /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
52 | private final Deque runningSyncCalls = new ArrayDeque<>();
53 |
54 | public Dispatcher(ExecutorService executorService) {
55 | this.executorService = executorService;
56 | }
57 |
58 | public Dispatcher() {
59 | }
60 |
61 | public synchronized ExecutorService executorService() {
62 | if (executorService == null) {
63 | executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
64 | new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
65 | }
66 | return executorService;
67 | }
68 |
69 | /**
70 | * Set the maximum number of requests to execute concurrently. Above this requests queue in
71 | * memory, waiting for the running calls to complete.
72 | *
73 | * If more than {@code maxRequests} requests are in flight when this is invoked, those requests
74 | * will remain in flight.
75 | */
76 | public synchronized void setMaxRequests(int maxRequests) {
77 | if (maxRequests < 1) {
78 | throw new IllegalArgumentException("max < 1: " + maxRequests);
79 | }
80 | this.maxRequests = maxRequests;
81 | promoteCalls();
82 | }
83 |
84 | public synchronized int getMaxRequests() {
85 | return maxRequests;
86 | }
87 |
88 | /**
89 | * Set the maximum number of requests for each host to execute concurrently. This limits requests
90 | * by the URL's host name. Note that concurrent requests to a single IP address may still exceed
91 | * this limit: multiple hostnames may share an IP address or be routed through the same HTTP
92 | * proxy.
93 | *
94 | *
If more than {@code maxRequestsPerHost} requests are in flight when this is invoked, those
95 | * requests will remain in flight.
96 | */
97 | public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) {
98 | if (maxRequestsPerHost < 1) {
99 | throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost);
100 | }
101 | this.maxRequestsPerHost = maxRequestsPerHost;
102 | promoteCalls();
103 | }
104 |
105 | public synchronized int getMaxRequestsPerHost() {
106 | return maxRequestsPerHost;
107 | }
108 |
109 | synchronized void enqueue(AsyncCall call) {
110 | if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
111 | runningAsyncCalls.add(call);
112 | executorService().execute(call);
113 | } else {
114 | readyAsyncCalls.add(call);
115 | }
116 | }
117 |
118 | /**
119 | * Cancel all calls currently enqueued or executing. Includes calls executed both {@linkplain
120 | * Call#execute() synchronously} and {@linkplain Call#enqueue asynchronously}.
121 | */
122 | public synchronized void cancelAll() {
123 | for (AsyncCall call : readyAsyncCalls) {
124 | call.cancel();
125 | }
126 |
127 | for (AsyncCall call : runningAsyncCalls) {
128 | call.cancel();
129 | }
130 |
131 | for (RealCall call : runningSyncCalls) {
132 | call.cancel();
133 | }
134 | }
135 |
136 | /** Used by {@code AsyncCall#run} to signal completion. */
137 | synchronized void finished(AsyncCall call) {
138 | if (!runningAsyncCalls.remove(call)) throw new AssertionError("AsyncCall wasn't running!");
139 | promoteCalls();
140 | }
141 |
142 | private void promoteCalls() {
143 | if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
144 | if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
145 |
146 | for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
147 | AsyncCall call = i.next();
148 |
149 | if (runningCallsForHost(call) < maxRequestsPerHost) {
150 | i.remove();
151 | runningAsyncCalls.add(call);
152 | executorService().execute(call);
153 | }
154 |
155 | if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
156 | }
157 | }
158 |
159 | /** Returns the number of running calls that share a host with {@code call}. */
160 | private int runningCallsForHost(AsyncCall call) {
161 | int result = 0;
162 | for (AsyncCall c : runningAsyncCalls) {
163 | if (c.host().equals(call.host())) result++;
164 | }
165 | return result;
166 | }
167 |
168 | /** Used by {@code Call#execute} to signal it is in-flight. */
169 | synchronized void executed(RealCall call) {
170 | runningSyncCalls.add(call);
171 | }
172 |
173 | /** Used by {@code Call#execute} to signal completion. */
174 | synchronized void finished(Call call) {
175 | if (!runningSyncCalls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
176 | }
177 |
178 | /** Returns a snapshot of the calls currently awaiting execution. */
179 | public synchronized List queuedCalls() {
180 | List result = new ArrayList<>();
181 | for (AsyncCall asyncCall : readyAsyncCalls) {
182 | result.add(asyncCall.get());
183 | }
184 | return Collections.unmodifiableList(result);
185 | }
186 |
187 | /** Returns a snapshot of the calls currently being executed. */
188 | public synchronized List runningCalls() {
189 | List result = new ArrayList<>();
190 | result.addAll(runningSyncCalls);
191 | for (AsyncCall asyncCall : runningAsyncCalls) {
192 | result.add(asyncCall.get());
193 | }
194 | return Collections.unmodifiableList(result);
195 | }
196 |
197 | public synchronized int queuedCallsCount() {
198 | return readyAsyncCalls.size();
199 | }
200 |
201 | public synchronized int runningCallsCount() {
202 | return runningAsyncCalls.size() + runningSyncCalls.size();
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Dns.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.net.InetAddress;
19 | import java.net.UnknownHostException;
20 | import java.util.Arrays;
21 | import java.util.List;
22 |
23 | /**
24 | * A domain name service that resolves IP addresses for host names. Most applications will use the
25 | * {@linkplain #SYSTEM system DNS service}, which is the default. Some applications may provide
26 | * their own implementation to use a different DNS server, to prefer IPv6 addresses, to prefer IPv4
27 | * addresses, or to force a specific known IP address.
28 | *
29 | * Implementations of this interface must be safe for concurrent use.
30 | */
31 | public interface Dns {
32 | /**
33 | * A DNS that uses {@link InetAddress#getAllByName} to ask the underlying operating system to
34 | * lookup IP addresses. Most custom {@link Dns} implementations should delegate to this instance.
35 | */
36 | Dns SYSTEM = new Dns() {
37 | @Override public List lookup(String hostname) throws UnknownHostException {
38 | if (hostname == null) throw new UnknownHostException("hostname == null");
39 | return Arrays.asList(InetAddress.getAllByName(hostname));
40 | }
41 | };
42 |
43 | /**
44 | * Returns the IP addresses of {@code hostname}, in the order they will be attempted by OkHttp. If
45 | * a connection to an address fails, OkHttp will retry the connection with the next address until
46 | * either a connection is made, the set of IP addresses is exhausted, or a limit is exceeded.
47 | */
48 | List lookup(String hostname) throws UnknownHostException;
49 | }
50 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/FormBody.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import okhttp3.internal.Util;
22 | import okio.Buffer;
23 | import okio.BufferedSink;
24 |
25 | import static okhttp3.HttpUrl.FORM_ENCODE_SET;
26 | import static okhttp3.HttpUrl.percentDecode;
27 |
28 | public final class FormBody extends RequestBody {
29 | private static final MediaType CONTENT_TYPE =
30 | MediaType.parse("application/x-www-form-urlencoded");
31 |
32 | private final List encodedNames;
33 | private final List encodedValues;
34 |
35 | private FormBody(List encodedNames, List encodedValues) {
36 | this.encodedNames = Util.immutableList(encodedNames);
37 | this.encodedValues = Util.immutableList(encodedValues);
38 | }
39 |
40 | /** The number of key-value pairs in this form-encoded body. */
41 | public int size() {
42 | return encodedNames.size();
43 | }
44 |
45 | public String encodedName(int index) {
46 | return encodedNames.get(index);
47 | }
48 |
49 | public String name(int index) {
50 | return percentDecode(encodedName(index), true);
51 | }
52 |
53 | public String encodedValue(int index) {
54 | return encodedValues.get(index);
55 | }
56 |
57 | public String value(int index) {
58 | return percentDecode(encodedValue(index), true);
59 | }
60 |
61 | @Override public MediaType contentType() {
62 | return CONTENT_TYPE;
63 | }
64 |
65 | @Override public long contentLength() {
66 | return writeOrCountBytes(null, true);
67 | }
68 |
69 | @Override public void writeTo(BufferedSink sink) throws IOException {
70 | writeOrCountBytes(sink, false);
71 | }
72 |
73 | /**
74 | * Either writes this request to {@code sink} or measures its content length. We have one method
75 | * do double-duty to make sure the counting and content are consistent, particularly when it comes
76 | * to awkward operations like measuring the encoded length of header strings, or the
77 | * length-in-digits of an encoded integer.
78 | */
79 | private long writeOrCountBytes(BufferedSink sink, boolean countBytes) {
80 | long byteCount = 0L;
81 |
82 | Buffer buffer;
83 | if (countBytes) {
84 | buffer = new Buffer();
85 | } else {
86 | buffer = sink.buffer();
87 | }
88 |
89 | for (int i = 0, size = encodedNames.size(); i < size; i++) {
90 | if (i > 0) buffer.writeByte('&');
91 | buffer.writeUtf8(encodedNames.get(i));
92 | buffer.writeByte('=');
93 | buffer.writeUtf8(encodedValues.get(i));
94 | }
95 |
96 | if (countBytes) {
97 | byteCount = buffer.size();
98 | buffer.clear();
99 | }
100 |
101 | return byteCount;
102 | }
103 |
104 | public static final class Builder {
105 | private final List names = new ArrayList<>();
106 | private final List values = new ArrayList<>();
107 |
108 | public Builder add(String name, String value) {
109 | names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, false, false, true, true));
110 | values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, false, false, true, true));
111 | return this;
112 | }
113 |
114 | public Builder addEncoded(String name, String value) {
115 | names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, true, false, true, true));
116 | values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, true, false, true, true));
117 | return this;
118 | }
119 |
120 | public FormBody build() {
121 | return new FormBody(names, values);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Handshake.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 okhttp3;
18 |
19 | import java.security.Principal;
20 | import java.security.cert.Certificate;
21 | import java.security.cert.X509Certificate;
22 | import java.util.Collections;
23 | import java.util.List;
24 | import javax.net.ssl.SSLPeerUnverifiedException;
25 | import javax.net.ssl.SSLSession;
26 | import okhttp3.internal.Util;
27 |
28 | /**
29 | * A record of a TLS handshake. For HTTPS clients, the client is local and the remote server
30 | * is its peer.
31 | *
32 | * This value object describes a completed handshake. Use {@link ConnectionSpec} to set policy
33 | * for new handshakes.
34 | */
35 | public final class Handshake {
36 | private final TlsVersion tlsVersion;
37 | private final CipherSuite cipherSuite;
38 | private final List peerCertificates;
39 | private final List localCertificates;
40 |
41 | private Handshake(TlsVersion tlsVersion, CipherSuite cipherSuite,
42 | List peerCertificates, List localCertificates) {
43 | this.tlsVersion = tlsVersion;
44 | this.cipherSuite = cipherSuite;
45 | this.peerCertificates = peerCertificates;
46 | this.localCertificates = localCertificates;
47 | }
48 |
49 | public static Handshake get(SSLSession session) {
50 | String cipherSuiteString = session.getCipherSuite();
51 | if (cipherSuiteString == null) throw new IllegalStateException("cipherSuite == null");
52 | CipherSuite cipherSuite = CipherSuite.forJavaName(cipherSuiteString);
53 |
54 | String tlsVersionString = session.getProtocol();
55 | if (tlsVersionString == null) throw new IllegalStateException("tlsVersion == null");
56 | TlsVersion tlsVersion = TlsVersion.forJavaName(tlsVersionString);
57 |
58 | Certificate[] peerCertificates;
59 | try {
60 | peerCertificates = session.getPeerCertificates();
61 | } catch (SSLPeerUnverifiedException ignored) {
62 | peerCertificates = null;
63 | }
64 | List peerCertificatesList = peerCertificates != null
65 | ? Util.immutableList(peerCertificates)
66 | : Collections.emptyList();
67 |
68 | Certificate[] localCertificates = session.getLocalCertificates();
69 | List localCertificatesList = localCertificates != null
70 | ? Util.immutableList(localCertificates)
71 | : Collections.emptyList();
72 |
73 | return new Handshake(tlsVersion, cipherSuite, peerCertificatesList, localCertificatesList);
74 | }
75 |
76 | public static Handshake get(TlsVersion tlsVersion, CipherSuite cipherSuite,
77 | List peerCertificates, List localCertificates) {
78 | if (cipherSuite == null) throw new IllegalArgumentException("cipherSuite == null");
79 | return new Handshake(tlsVersion, cipherSuite, Util.immutableList(peerCertificates),
80 | Util.immutableList(localCertificates));
81 | }
82 |
83 | /**
84 | * Returns the TLS version used for this connection. May return null if the response was cached
85 | * with a version of OkHttp prior to 3.0.
86 | */
87 | public TlsVersion tlsVersion() {
88 | return tlsVersion;
89 | }
90 |
91 | /** Returns the cipher suite used for the connection. */
92 | public CipherSuite cipherSuite() {
93 | return cipherSuite;
94 | }
95 |
96 | /** Returns a possibly-empty list of certificates that identify the remote peer. */
97 | public List peerCertificates() {
98 | return peerCertificates;
99 | }
100 |
101 | /** Returns the remote peer's principle, or null if that peer is anonymous. */
102 | public Principal peerPrincipal() {
103 | return !peerCertificates.isEmpty()
104 | ? ((X509Certificate) peerCertificates.get(0)).getSubjectX500Principal()
105 | : null;
106 | }
107 |
108 | /** Returns a possibly-empty list of certificates that identify this peer. */
109 | public List localCertificates() {
110 | return localCertificates;
111 | }
112 |
113 | /** Returns the local principle, or null if this peer is anonymous. */
114 | public Principal localPrincipal() {
115 | return !localCertificates.isEmpty()
116 | ? ((X509Certificate) localCertificates.get(0)).getSubjectX500Principal()
117 | : null;
118 | }
119 |
120 | @Override public boolean equals(Object other) {
121 | if (!(other instanceof Handshake)) return false;
122 | Handshake that = (Handshake) other;
123 | return Util.equal(cipherSuite, that.cipherSuite)
124 | && cipherSuite.equals(that.cipherSuite)
125 | && peerCertificates.equals(that.peerCertificates)
126 | && localCertificates.equals(that.localCertificates);
127 | }
128 |
129 | @Override public int hashCode() {
130 | int result = 17;
131 | result = 31 * result + (tlsVersion != null ? tlsVersion.hashCode() : 0);
132 | result = 31 * result + cipherSuite.hashCode();
133 | result = 31 * result + peerCertificates.hashCode();
134 | result = 31 * result + localCertificates.hashCode();
135 | return result;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Interceptor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * Observes, modifies, and potentially short-circuits requests going out and the corresponding
22 | * requests coming back in. Typically interceptors will be used to add, remove, or transform headers
23 | * on the request or response.
24 | */
25 | public interface Interceptor {
26 | Response intercept(Chain chain) throws IOException;
27 |
28 | interface Chain {
29 | Request request();
30 |
31 | Response proceed(Request request) throws IOException;
32 |
33 | Connection connection();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/MediaType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.nio.charset.Charset;
19 | import java.util.Locale;
20 | import java.util.regex.Matcher;
21 | import java.util.regex.Pattern;
22 |
23 | /**
24 | * An RFC 2045 Media Type, appropriate to describe
25 | * the content type of an HTTP request or response body.
26 | */
27 | public final class MediaType {
28 | private static final String TOKEN = "([a-zA-Z0-9-!#$%&'*+.^_`{|}~]+)";
29 | private static final String QUOTED = "\"([^\"]*)\"";
30 | private static final Pattern TYPE_SUBTYPE = Pattern.compile(TOKEN + "/" + TOKEN);
31 | private static final Pattern PARAMETER = Pattern.compile(
32 | ";\\s*(?:" + TOKEN + "=(?:" + TOKEN + "|" + QUOTED + "))?");
33 |
34 | private final String mediaType;
35 | private final String type;
36 | private final String subtype;
37 | private final String charset;
38 |
39 | private MediaType(String mediaType, String type, String subtype, String charset) {
40 | this.mediaType = mediaType;
41 | this.type = type;
42 | this.subtype = subtype;
43 | this.charset = charset;
44 | }
45 |
46 | /**
47 | * Returns a media type for {@code string}, or null if {@code string} is not a well-formed media
48 | * type.
49 | */
50 | public static MediaType parse(String string) {
51 | Matcher typeSubtype = TYPE_SUBTYPE.matcher(string);
52 | if (!typeSubtype.lookingAt()) return null;
53 | String type = typeSubtype.group(1).toLowerCase(Locale.US);
54 | String subtype = typeSubtype.group(2).toLowerCase(Locale.US);
55 |
56 | String charset = null;
57 | Matcher parameter = PARAMETER.matcher(string);
58 | for (int s = typeSubtype.end(); s < string.length(); s = parameter.end()) {
59 | parameter.region(s, string.length());
60 | if (!parameter.lookingAt()) return null; // This is not a well-formed media type.
61 |
62 | String name = parameter.group(1);
63 | if (name == null || !name.equalsIgnoreCase("charset")) continue;
64 | String charsetParameter = parameter.group(2) != null
65 | ? parameter.group(2) // Value is a token.
66 | : parameter.group(3); // Value is a quoted string.
67 | if (charset != null && !charsetParameter.equalsIgnoreCase(charset)) {
68 | throw new IllegalArgumentException("Multiple different charsets: " + string);
69 | }
70 | charset = charsetParameter;
71 | }
72 |
73 | return new MediaType(string, type, subtype, charset);
74 | }
75 |
76 | /**
77 | * Returns the high-level media type, such as "text", "image", "audio", "video", or
78 | * "application".
79 | */
80 | public String type() {
81 | return type;
82 | }
83 |
84 | /**
85 | * Returns a specific media subtype, such as "plain" or "png", "mpeg", "mp4" or "xml".
86 | */
87 | public String subtype() {
88 | return subtype;
89 | }
90 |
91 | /**
92 | * Returns the charset of this media type, or null if this media type doesn't specify a charset.
93 | */
94 | public Charset charset() {
95 | return charset != null ? Charset.forName(charset) : null;
96 | }
97 |
98 | /**
99 | * Returns the charset of this media type, or {@code defaultValue} if this media type doesn't
100 | * specify a charset.
101 | */
102 | public Charset charset(Charset defaultValue) {
103 | return charset != null ? Charset.forName(charset) : defaultValue;
104 | }
105 |
106 | /**
107 | * Returns the encoded media type, like "text/plain; charset=utf-8", appropriate for use in a
108 | * Content-Type header.
109 | */
110 | @Override public String toString() {
111 | return mediaType;
112 | }
113 |
114 | @Override public boolean equals(Object o) {
115 | return o instanceof MediaType && ((MediaType) o).mediaType.equals(mediaType);
116 | }
117 |
118 | @Override public int hashCode() {
119 | return mediaType.hashCode();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Protocol.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * Protocols that OkHttp implements for ALPN selection.
23 | *
24 | * Protocol vs Scheme
Despite its name, {@link java.net.URL#getProtocol()} returns the
25 | * {@linkplain java.net.URI#getScheme() scheme} (http, https, etc.) of the URL, not the protocol
26 | * (http/1.1, spdy/3.1, etc.). OkHttp uses the word protocol to identify how HTTP messages
27 | * are framed.
28 | */
29 | public enum Protocol {
30 | /**
31 | * An obsolete plaintext framing that does not use persistent sockets by default.
32 | */
33 | HTTP_1_0("http/1.0"),
34 |
35 | /**
36 | * A plaintext framing that includes persistent connections.
37 | *
38 | * This version of OkHttp implements RFC
39 | * 2616, and tracks revisions to that spec.
40 | */
41 | HTTP_1_1("http/1.1"),
42 |
43 | /**
44 | * Chromium's binary-framed protocol that includes header compression, multiplexing multiple
45 | * requests on the same socket, and server-push. HTTP/1.1 semantics are layered on SPDY/3.
46 | *
47 | *
This version of OkHttp implements SPDY 3 draft 3.1. Future
49 | * releases of OkHttp may use this identifier for a newer draft of the SPDY spec.
50 | */
51 | SPDY_3("spdy/3.1"),
52 |
53 | /**
54 | * The IETF's binary-framed protocol that includes header compression, multiplexing multiple
55 | * requests on the same socket, and server-push. HTTP/1.1 semantics are layered on HTTP/2.
56 | *
57 | *
HTTP/2 requires deployments of HTTP/2 that use TLS 1.2 support {@linkplain
58 | * CipherSuite#TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} , present in Java 8+ and Android 5+. Servers
59 | * that enforce this may send an exception message including the string {@code
60 | * INADEQUATE_SECURITY}.
61 | */
62 | HTTP_2("h2");
63 |
64 | private final String protocol;
65 |
66 | Protocol(String protocol) {
67 | this.protocol = protocol;
68 | }
69 |
70 | /**
71 | * Returns the protocol identified by {@code protocol}.
72 | *
73 | * @throws IOException if {@code protocol} is unknown.
74 | */
75 | public static Protocol get(String protocol) throws IOException {
76 | // Unroll the loop over values() to save an allocation.
77 | if (protocol.equals(HTTP_1_0.protocol)) return HTTP_1_0;
78 | if (protocol.equals(HTTP_1_1.protocol)) return HTTP_1_1;
79 | if (protocol.equals(HTTP_2.protocol)) return HTTP_2;
80 | if (protocol.equals(SPDY_3.protocol)) return SPDY_3;
81 | throw new IOException("Unexpected protocol: " + protocol);
82 | }
83 |
84 | /**
85 | * Returns the string used to identify this protocol for ALPN, like "http/1.1", "spdy/3.1" or
86 | * "h2".
87 | */
88 | @Override public String toString() {
89 | return protocol;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Request.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.net.URI;
19 | import java.net.URL;
20 | import java.util.List;
21 | import okhttp3.internal.http.HttpMethod;
22 |
23 | /**
24 | * An HTTP request. Instances of this class are immutable if their {@link #body} is null or itself
25 | * immutable.
26 | */
27 | public final class Request {
28 | private final HttpUrl url;
29 | private final String method;
30 | private final Headers headers;
31 | private final RequestBody body;
32 | private final Object tag;
33 |
34 | private volatile URI javaNetUri; // Lazily initialized.
35 | private volatile CacheControl cacheControl; // Lazily initialized.
36 |
37 | private Request(Builder builder) {
38 | this.url = builder.url;
39 | this.method = builder.method;
40 | this.headers = builder.headers.build();
41 | this.body = builder.body;
42 | this.tag = builder.tag != null ? builder.tag : this;
43 | }
44 |
45 | public HttpUrl url() {
46 | return url;
47 | }
48 |
49 | public String method() {
50 | return method;
51 | }
52 |
53 | public Headers headers() {
54 | return headers;
55 | }
56 |
57 | public String header(String name) {
58 | return headers.get(name);
59 | }
60 |
61 | public List headers(String name) {
62 | return headers.values(name);
63 | }
64 |
65 | public RequestBody body() {
66 | return body;
67 | }
68 |
69 | public Object tag() {
70 | return tag;
71 | }
72 |
73 | public Builder newBuilder() {
74 | return new Builder(this);
75 | }
76 |
77 | /**
78 | * Returns the cache control directives for this response. This is never null, even if this
79 | * response contains no {@code Cache-Control} header.
80 | */
81 | public CacheControl cacheControl() {
82 | CacheControl result = cacheControl;
83 | return result != null ? result : (cacheControl = CacheControl.parse(headers));
84 | }
85 |
86 | public boolean isHttps() {
87 | return url.isHttps();
88 | }
89 |
90 | @Override public String toString() {
91 | return "Request{method="
92 | + method
93 | + ", url="
94 | + url
95 | + ", tag="
96 | + (tag != this ? tag : null)
97 | + '}';
98 | }
99 |
100 | public static class Builder {
101 | private HttpUrl url;
102 | private String method;
103 | private Headers.Builder headers;
104 | private RequestBody body;
105 | private Object tag;
106 |
107 | public Builder() {
108 | this.method = "GET";
109 | this.headers = new Headers.Builder();
110 | }
111 |
112 | private Builder(Request request) {
113 | this.url = request.url;
114 | this.method = request.method;
115 | this.body = request.body;
116 | this.tag = request.tag;
117 | this.headers = request.headers.newBuilder();
118 | }
119 |
120 | public Builder url(HttpUrl url) {
121 | if (url == null) throw new IllegalArgumentException("url == null");
122 | this.url = url;
123 | return this;
124 | }
125 |
126 | /**
127 | * Sets the URL target of this request.
128 | *
129 | * @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this
130 | * exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs.
131 | */
132 | public Builder url(String url) {
133 | if (url == null) throw new IllegalArgumentException("url == null");
134 |
135 | // Silently replace websocket URLs with HTTP URLs.
136 | if (url.regionMatches(true, 0, "ws:", 0, 3)) {
137 | url = "http:" + url.substring(3);
138 | } else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
139 | url = "https:" + url.substring(4);
140 | }
141 |
142 | HttpUrl parsed = HttpUrl.parse(url);
143 | if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
144 | return url(parsed);
145 | }
146 |
147 | /**
148 | * Sets the URL target of this request.
149 | *
150 | * @throws IllegalArgumentException if the scheme of {@code url} is not {@code http} or {@code
151 | * https}.
152 | */
153 | public Builder url(URL url) {
154 | if (url == null) throw new IllegalArgumentException("url == null");
155 | HttpUrl parsed = HttpUrl.get(url);
156 | if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
157 | return url(parsed);
158 | }
159 |
160 | /**
161 | * Sets the header named {@code name} to {@code value}. If this request already has any headers
162 | * with that name, they are all replaced.
163 | */
164 | public Builder header(String name, String value) {
165 | headers.set(name, value);
166 | return this;
167 | }
168 |
169 | /**
170 | * Adds a header with {@code name} and {@code value}. Prefer this method for multiply-valued
171 | * headers like "Cookie".
172 | *
173 | * Note that for some headers including {@code Content-Length} and {@code Content-Encoding},
174 | * OkHttp may replace {@code value} with a header derived from the request body.
175 | */
176 | public Builder addHeader(String name, String value) {
177 | headers.add(name, value);
178 | return this;
179 | }
180 |
181 | public Builder removeHeader(String name) {
182 | headers.removeAll(name);
183 | return this;
184 | }
185 |
186 | /** Removes all headers on this builder and adds {@code headers}. */
187 | public Builder headers(Headers headers) {
188 | this.headers = headers.newBuilder();
189 | return this;
190 | }
191 |
192 | /**
193 | * Sets this request's {@code Cache-Control} header, replacing any cache control headers already
194 | * present. If {@code cacheControl} doesn't define any directives, this clears this request's
195 | * cache-control headers.
196 | */
197 | public Builder cacheControl(CacheControl cacheControl) {
198 | String value = cacheControl.toString();
199 | if (value.isEmpty()) return removeHeader("Cache-Control");
200 | return header("Cache-Control", value);
201 | }
202 |
203 | public Builder get() {
204 | return method("GET", null);
205 | }
206 |
207 | public Builder head() {
208 | return method("HEAD", null);
209 | }
210 |
211 | public Builder post(RequestBody body) {
212 | return method("POST", body);
213 | }
214 |
215 | public Builder delete(RequestBody body) {
216 | return method("DELETE", body);
217 | }
218 |
219 | public Builder delete() {
220 | return delete(RequestBody.create(null, new byte[0]));
221 | }
222 |
223 | public Builder put(RequestBody body) {
224 | return method("PUT", body);
225 | }
226 |
227 | public Builder patch(RequestBody body) {
228 | return method("PATCH", body);
229 | }
230 |
231 | public Builder method(String method, RequestBody body) {
232 | if (method == null || method.length() == 0) {
233 | throw new IllegalArgumentException("method == null || method.length() == 0");
234 | }
235 | if (body != null && !HttpMethod.permitsRequestBody(method)) {
236 | throw new IllegalArgumentException("method " + method + " must not have a request body.");
237 | }
238 | if (body == null && HttpMethod.requiresRequestBody(method)) {
239 | throw new IllegalArgumentException("method " + method + " must have a request body.");
240 | }
241 | this.method = method;
242 | this.body = body;
243 | return this;
244 | }
245 |
246 | /**
247 | * Attaches {@code tag} to the request. It can be used later to cancel the request. If the tag
248 | * is unspecified or null, the request is canceled by using the request itself as the tag.
249 | */
250 | public Builder tag(Object tag) {
251 | this.tag = tag;
252 | return this;
253 | }
254 |
255 | public Request build() {
256 | if (url == null) throw new IllegalStateException("url == null");
257 | return new Request(this);
258 | }
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/RequestBody.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.nio.charset.Charset;
21 | import okhttp3.internal.Util;
22 | import okio.BufferedSink;
23 | import okio.ByteString;
24 | import okio.Okio;
25 | import okio.Source;
26 |
27 | public abstract class RequestBody {
28 | /** Returns the Content-Type header for this body. */
29 | public abstract MediaType contentType();
30 |
31 | /**
32 | * Returns the number of bytes that will be written to {@code out} in a call to {@link #writeTo},
33 | * or -1 if that count is unknown.
34 | */
35 | public long contentLength() throws IOException {
36 | return -1;
37 | }
38 |
39 | /** Writes the content of this request to {@code out}. */
40 | public abstract void writeTo(BufferedSink sink) throws IOException;
41 |
42 | /**
43 | * Returns a new request body that transmits {@code content}. If {@code contentType} is non-null
44 | * and lacks a charset, this will use UTF-8.
45 | */
46 | public static RequestBody create(MediaType contentType, String content) {
47 | Charset charset = Util.UTF_8;
48 | if (contentType != null) {
49 | charset = contentType.charset();
50 | if (charset == null) {
51 | charset = Util.UTF_8;
52 | contentType = MediaType.parse(contentType + "; charset=utf-8");
53 | }
54 | }
55 | byte[] bytes = content.getBytes(charset);
56 | return create(contentType, bytes);
57 | }
58 |
59 | /** Returns a new request body that transmits {@code content}. */
60 | public static RequestBody create(final MediaType contentType, final ByteString content) {
61 | return new RequestBody() {
62 | @Override public MediaType contentType() {
63 | return contentType;
64 | }
65 |
66 | @Override public long contentLength() throws IOException {
67 | return content.size();
68 | }
69 |
70 | @Override public void writeTo(BufferedSink sink) throws IOException {
71 | sink.write(content);
72 | }
73 | };
74 | }
75 |
76 | /** Returns a new request body that transmits {@code content}. */
77 | public static RequestBody create(final MediaType contentType, final byte[] content) {
78 | return create(contentType, content, 0, content.length);
79 | }
80 |
81 | /** Returns a new request body that transmits {@code content}. */
82 | public static RequestBody create(final MediaType contentType, final byte[] content,
83 | final int offset, final int byteCount) {
84 | if (content == null) throw new NullPointerException("content == null");
85 | Util.checkOffsetAndCount(content.length, offset, byteCount);
86 | return new RequestBody() {
87 | @Override public MediaType contentType() {
88 | return contentType;
89 | }
90 |
91 | @Override public long contentLength() {
92 | return byteCount;
93 | }
94 |
95 | @Override public void writeTo(BufferedSink sink) throws IOException {
96 | sink.write(content, offset, byteCount);
97 | }
98 | };
99 | }
100 |
101 | /** Returns a new request body that transmits the content of {@code file}. */
102 | public static RequestBody create(final MediaType contentType, final File file) {
103 | if (file == null) throw new NullPointerException("content == null");
104 |
105 | return new RequestBody() {
106 | @Override public MediaType contentType() {
107 | return contentType;
108 | }
109 |
110 | @Override public long contentLength() {
111 | return file.length();
112 | }
113 |
114 | @Override public void writeTo(BufferedSink sink) throws IOException {
115 | Source source = null;
116 | try {
117 | source = Okio.source(file);
118 | sink.writeAll(source);
119 | } finally {
120 | Util.closeQuietly(source);
121 | }
122 | }
123 | };
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/ResponseBody.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.io.Closeable;
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.io.InputStreamReader;
22 | import java.io.Reader;
23 | import java.nio.charset.Charset;
24 | import okhttp3.internal.Util;
25 | import okio.Buffer;
26 | import okio.BufferedSource;
27 |
28 | import static okhttp3.internal.Util.UTF_8;
29 |
30 | /**
31 | * A one-shot stream from the origin server to the client application with the raw bytes of the
32 | * response body. Each response body is supported by an active connection to the webserver. This
33 | * imposes both obligations and limits on the client application.
34 | *
35 | *
The response body must be closed.
36 | *
37 | * Each response body is backed by a limited resource like a socket (live network responses) or
38 | * an open file (for cached responses). Failing to close the response body will leak these resources
39 | * and may ultimately cause the application to slow down or crash. Close the response body by
40 | * calling either {@link ResponseBody#close close()}, {@link InputStream#close()
41 | * byteStream().close()}, or {@link Reader#close() reader().close()}. The {@link #bytes()} and
42 | * {@link #string()} methods both close the response body automatically.
43 | *
44 | *
The response body can be consumed only once.
45 | *
46 | * This class may be used to stream very large responses. For example, it is possible to use this
47 | * class to read a response that is larger than the entire memory allocated to the current process.
48 | * It can even stream a response larger than the total storage on the current device, which is a
49 | * common requirement for video streaming applications.
50 | *
51 | *
Because this class does not buffer the full response in memory, the application may not
52 | * re-read the bytes of the response. Use this one shot to read the entire response into memory with
53 | * {@link #bytes()} or {@link #string()}. Or stream the response with either {@link #source()},
54 | * {@link #byteStream()}, or {@link #charStream()}.
55 | */
56 | public abstract class ResponseBody implements Closeable {
57 | /** Multiple calls to {@link #charStream()} must return the same instance. */
58 | private Reader reader;
59 |
60 | public abstract MediaType contentType();
61 |
62 | /**
63 | * Returns the number of bytes in that will returned by {@link #bytes}, or {@link #byteStream}, or
64 | * -1 if unknown.
65 | */
66 | public abstract long contentLength();
67 |
68 | public final InputStream byteStream() {
69 | return source().inputStream();
70 | }
71 |
72 | public abstract BufferedSource source();
73 |
74 | public final byte[] bytes() throws IOException {
75 | long contentLength = contentLength();
76 | if (contentLength > Integer.MAX_VALUE) {
77 | throw new IOException("Cannot buffer entire body for content length: " + contentLength);
78 | }
79 |
80 | BufferedSource source = source();
81 | byte[] bytes;
82 | try {
83 | bytes = source.readByteArray();
84 | } finally {
85 | Util.closeQuietly(source);
86 | }
87 | if (contentLength != -1 && contentLength != bytes.length) {
88 | throw new IOException("Content-Length and stream length disagree");
89 | }
90 | return bytes;
91 | }
92 |
93 | /**
94 | * Returns the response as a character stream decoded with the charset of the Content-Type header.
95 | * If that header is either absent or lacks a charset, this will attempt to decode the response
96 | * body as UTF-8.
97 | */
98 | public final Reader charStream() {
99 | Reader r = reader;
100 | return r != null ? r : (reader = new InputStreamReader(byteStream(), charset()));
101 | }
102 |
103 | /**
104 | * Returns the response as a string decoded with the charset of the Content-Type header. If that
105 | * header is either absent or lacks a charset, this will attempt to decode the response body as
106 | * UTF-8.
107 | */
108 | public final String string() throws IOException {
109 | return new String(bytes(), charset().name());
110 | }
111 |
112 | private Charset charset() {
113 | MediaType contentType = contentType();
114 | return contentType != null ? contentType.charset(UTF_8) : UTF_8;
115 | }
116 |
117 | @Override public void close() {
118 | Util.closeQuietly(source());
119 | }
120 |
121 | /**
122 | * Returns a new response body that transmits {@code content}. If {@code contentType} is non-null
123 | * and lacks a charset, this will use UTF-8.
124 | */
125 | public static ResponseBody create(MediaType contentType, String content) {
126 | Charset charset = UTF_8;
127 | if (contentType != null) {
128 | charset = contentType.charset();
129 | if (charset == null) {
130 | charset = UTF_8;
131 | contentType = MediaType.parse(contentType + "; charset=utf-8");
132 | }
133 | }
134 | Buffer buffer = new Buffer().writeString(content, charset);
135 | return create(contentType, buffer.size(), buffer);
136 | }
137 |
138 | /** Returns a new response body that transmits {@code content}. */
139 | public static ResponseBody create(final MediaType contentType, byte[] content) {
140 | Buffer buffer = new Buffer().write(content);
141 | return create(contentType, content.length, buffer);
142 | }
143 |
144 | /** Returns a new response body that transmits {@code content}. */
145 | public static ResponseBody create(
146 | final MediaType contentType, final long contentLength, final BufferedSource content) {
147 | if (content == null) throw new NullPointerException("source == null");
148 | return new ResponseBody() {
149 | @Override public MediaType contentType() {
150 | return contentType;
151 | }
152 |
153 | @Override public long contentLength() {
154 | return contentLength;
155 | }
156 |
157 | @Override public BufferedSource source() {
158 | return content;
159 | }
160 | };
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/Route.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3;
17 |
18 | import java.net.InetSocketAddress;
19 | import java.net.Proxy;
20 |
21 | /**
22 | * The concrete route used by a connection to reach an abstract origin server. When creating a
23 | * connection the client has many options:
24 | *
25 | *
26 | * - HTTP proxy: a proxy server may be explicitly configured for the client.
27 | * Otherwise the {@linkplain java.net.ProxySelector proxy selector} is used. It may return
28 | * multiple proxies to attempt.
29 | *
- IP address: whether connecting directly to an origin server or a proxy,
30 | * opening a socket requires an IP address. The DNS server may return multiple IP addresses
31 | * to attempt.
32 | *
33 | *
34 | * Each route is a specific selection of these options.
35 | */
36 | public final class Route {
37 | final Address address;
38 | final Proxy proxy;
39 | final InetSocketAddress inetSocketAddress;
40 |
41 | public Route(Address address, Proxy proxy, InetSocketAddress inetSocketAddress) {
42 | if (address == null) {
43 | throw new NullPointerException("address == null");
44 | }
45 | if (proxy == null) {
46 | throw new NullPointerException("proxy == null");
47 | }
48 | if (inetSocketAddress == null) {
49 | throw new NullPointerException("inetSocketAddress == null");
50 | }
51 | this.address = address;
52 | this.proxy = proxy;
53 | this.inetSocketAddress = inetSocketAddress;
54 | }
55 |
56 | public Address address() {
57 | return address;
58 | }
59 |
60 | /**
61 | * Returns the {@link Proxy} of this route.
62 | *
63 | * Warning: This may disagree with {@link Address#proxy} when it is null. When
64 | * the address's proxy is null, the proxy selector is used.
65 | */
66 | public Proxy proxy() {
67 | return proxy;
68 | }
69 |
70 | public InetSocketAddress socketAddress() {
71 | return inetSocketAddress;
72 | }
73 |
74 | /**
75 | * Returns true if this route tunnels HTTPS through an HTTP proxy. See RFC 2817, Section 5.2.
77 | */
78 | public boolean requiresTunnel() {
79 | return address.sslSocketFactory != null && proxy.type() == Proxy.Type.HTTP;
80 | }
81 |
82 | @Override public boolean equals(Object obj) {
83 | if (obj instanceof Route) {
84 | Route other = (Route) obj;
85 | return address.equals(other.address)
86 | && proxy.equals(other.proxy)
87 | && inetSocketAddress.equals(other.inetSocketAddress);
88 | }
89 | return false;
90 | }
91 |
92 | @Override public int hashCode() {
93 | int result = 17;
94 | result = 31 * result + address.hashCode();
95 | result = 31 * result + proxy.hashCode();
96 | result = 31 * result + inetSocketAddress.hashCode();
97 | return result;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/TlsVersion.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3;
17 |
18 | /**
19 | * Versions of TLS that can be offered when negotiating a secure socket. See {@link
20 | * javax.net.ssl.SSLSocket#setEnabledProtocols}.
21 | */
22 | public enum TlsVersion {
23 | TLS_1_2("TLSv1.2"), // 2008.
24 | TLS_1_1("TLSv1.1"), // 2006.
25 | TLS_1_0("TLSv1"), // 1999.
26 | SSL_3_0("SSLv3"), // 1996.
27 | ;
28 |
29 | final String javaName;
30 |
31 | TlsVersion(String javaName) {
32 | this.javaName = javaName;
33 | }
34 |
35 | public static TlsVersion forJavaName(String javaName) {
36 | switch (javaName) {
37 | case "TLSv1.2":
38 | return TLS_1_2;
39 | case "TLSv1.1":
40 | return TLS_1_1;
41 | case "TLSv1":
42 | return TLS_1_0;
43 | case "SSLv3":
44 | return SSL_3_0;
45 | }
46 | throw new IllegalArgumentException("Unexpected TLS version: " + javaName);
47 | }
48 |
49 | public String javaName() {
50 | return javaName;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/ConnectionSpecSelector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 okhttp3.internal;
18 |
19 | import java.io.IOException;
20 | import java.io.InterruptedIOException;
21 | import java.net.ProtocolException;
22 | import java.net.UnknownServiceException;
23 | import java.security.cert.CertificateException;
24 | import java.util.Arrays;
25 | import java.util.List;
26 | import javax.net.ssl.SSLHandshakeException;
27 | import javax.net.ssl.SSLPeerUnverifiedException;
28 | import javax.net.ssl.SSLProtocolException;
29 | import javax.net.ssl.SSLSocket;
30 | import okhttp3.ConnectionSpec;
31 |
32 | /**
33 | * Handles the connection spec fallback strategy: When a secure socket connection fails due to a
34 | * handshake / protocol problem the connection may be retried with different protocols. Instances
35 | * are stateful and should be created and used for a single connection attempt.
36 | */
37 | public final class ConnectionSpecSelector {
38 |
39 | private final List connectionSpecs;
40 | private int nextModeIndex;
41 | private boolean isFallbackPossible;
42 | private boolean isFallback;
43 |
44 | public ConnectionSpecSelector(List connectionSpecs) {
45 | this.nextModeIndex = 0;
46 | this.connectionSpecs = connectionSpecs;
47 | }
48 |
49 | /**
50 | * Configures the supplied {@link SSLSocket} to connect to the specified host using an appropriate
51 | * {@link ConnectionSpec}. Returns the chosen {@link ConnectionSpec}, never {@code null}.
52 | *
53 | * @throws IOException if the socket does not support any of the TLS modes available
54 | */
55 | public ConnectionSpec configureSecureSocket(SSLSocket sslSocket) throws IOException {
56 | ConnectionSpec tlsConfiguration = null;
57 | for (int i = nextModeIndex, size = connectionSpecs.size(); i < size; i++) {
58 | ConnectionSpec connectionSpec = connectionSpecs.get(i);
59 | if (connectionSpec.isCompatible(sslSocket)) {
60 | tlsConfiguration = connectionSpec;
61 | nextModeIndex = i + 1;
62 | break;
63 | }
64 | }
65 |
66 | if (tlsConfiguration == null) {
67 | // This may be the first time a connection has been attempted and the socket does not support
68 | // any the required protocols, or it may be a retry (but this socket supports fewer
69 | // protocols than was suggested by a prior socket).
70 | throw new UnknownServiceException(
71 | "Unable to find acceptable protocols. isFallback=" + isFallback
72 | + ", modes=" + connectionSpecs
73 | + ", supported protocols=" + Arrays.toString(sslSocket.getEnabledProtocols()));
74 | }
75 |
76 | isFallbackPossible = isFallbackPossible(sslSocket);
77 |
78 | Internal.instance.apply(tlsConfiguration, sslSocket, isFallback);
79 |
80 | return tlsConfiguration;
81 | }
82 |
83 | /**
84 | * Reports a failure to complete a connection. Determines the next {@link ConnectionSpec} to try,
85 | * if any.
86 | *
87 | * @return {@code true} if the connection should be retried using {@link
88 | * #configureSecureSocket(SSLSocket)} or {@code false} if not
89 | */
90 | public boolean connectionFailed(IOException e) {
91 | // Any future attempt to connect using this strategy will be a fallback attempt.
92 | isFallback = true;
93 |
94 | if (!isFallbackPossible) {
95 | return false;
96 | }
97 |
98 | // If there was a protocol problem, don't recover.
99 | if (e instanceof ProtocolException) {
100 | return false;
101 | }
102 |
103 | // If there was an interruption or timeout (SocketTimeoutException), don't recover.
104 | // For the socket connect timeout case we do not try the same host with a different
105 | // ConnectionSpec: we assume it is unreachable.
106 | if (e instanceof InterruptedIOException) {
107 | return false;
108 | }
109 |
110 | // Look for known client-side or negotiation errors that are unlikely to be fixed by trying
111 | // again with a different connection spec.
112 | if (e instanceof SSLHandshakeException) {
113 | // If the problem was a CertificateException from the X509TrustManager,
114 | // do not retry.
115 | if (e.getCause() instanceof CertificateException) {
116 | return false;
117 | }
118 | }
119 | if (e instanceof SSLPeerUnverifiedException) {
120 | // e.g. a certificate pinning error.
121 | return false;
122 | }
123 |
124 | // On Android, SSLProtocolExceptions can be caused by TLS_FALLBACK_SCSV failures, which means we
125 | // retry those when we probably should not.
126 | return (e instanceof SSLHandshakeException || e instanceof SSLProtocolException);
127 | }
128 |
129 | /**
130 | * Returns {@code true} if any later {@link ConnectionSpec} in the fallback strategy looks
131 | * possible based on the supplied {@link SSLSocket}. It assumes that a future socket will have the
132 | * same capabilities as the supplied socket.
133 | */
134 | private boolean isFallbackPossible(SSLSocket socket) {
135 | for (int i = nextModeIndex; i < connectionSpecs.size(); i++) {
136 | if (connectionSpecs.get(i).isCompatible(socket)) {
137 | return true;
138 | }
139 | }
140 | return false;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/FaultHidingSink.java:
--------------------------------------------------------------------------------
1 | package okhttp3.internal;
2 |
3 | import java.io.IOException;
4 | import okio.Buffer;
5 | import okio.ForwardingSink;
6 | import okio.Sink;
7 |
8 | /** A sink that never throws IOExceptions, even if the underlying sink does. */
9 | class FaultHidingSink extends ForwardingSink {
10 | private boolean hasErrors;
11 |
12 | public FaultHidingSink(Sink delegate) {
13 | super(delegate);
14 | }
15 |
16 | @Override public void write(Buffer source, long byteCount) throws IOException {
17 | if (hasErrors) {
18 | source.skip(byteCount);
19 | return;
20 | }
21 | try {
22 | super.write(source, byteCount);
23 | } catch (IOException e) {
24 | hasErrors = true;
25 | onException(e);
26 | }
27 | }
28 |
29 | @Override public void flush() throws IOException {
30 | if (hasErrors) return;
31 | try {
32 | super.flush();
33 | } catch (IOException e) {
34 | hasErrors = true;
35 | onException(e);
36 | }
37 | }
38 |
39 | @Override public void close() throws IOException {
40 | if (hasErrors) return;
41 | try {
42 | super.close();
43 | } catch (IOException e) {
44 | hasErrors = true;
45 | onException(e);
46 | }
47 | }
48 |
49 | protected void onException(IOException e) {
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/Internal.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal;
17 |
18 | import java.net.MalformedURLException;
19 | import java.net.UnknownHostException;
20 | import java.util.logging.Logger;
21 | import javax.net.ssl.SSLSocket;
22 | import okhttp3.Address;
23 | import okhttp3.Call;
24 | import okhttp3.Callback;
25 | import okhttp3.ConnectionPool;
26 | import okhttp3.ConnectionSpec;
27 | import okhttp3.Headers;
28 | import okhttp3.HttpUrl;
29 | import okhttp3.OkHttpClient;
30 | import okhttp3.internal.http.StreamAllocation;
31 | import okhttp3.internal.io.RealConnection;
32 |
33 | /**
34 | * Escalate internal APIs in {@code okhttp3} so they can be used from OkHttp's implementation
35 | * packages. The only implementation of this interface is in {@link OkHttpClient}.
36 | */
37 | public abstract class Internal {
38 | public static final Logger logger = Logger.getLogger(OkHttpClient.class.getName());
39 |
40 | public static void initializeInstanceForTests() {
41 | // Needed in tests to ensure that the instance is actually pointing to something.
42 | new OkHttpClient();
43 | }
44 |
45 | public static Internal instance;
46 |
47 | public abstract void addLenient(Headers.Builder builder, String line);
48 |
49 | public abstract void addLenient(Headers.Builder builder, String name, String value);
50 |
51 | public abstract void setCache(OkHttpClient.Builder builder, InternalCache internalCache);
52 |
53 | public abstract InternalCache internalCache(OkHttpClient client);
54 |
55 | public abstract RealConnection get(
56 | ConnectionPool pool, Address address, StreamAllocation streamAllocation);
57 |
58 | public abstract void put(ConnectionPool pool, RealConnection connection);
59 |
60 | public abstract boolean connectionBecameIdle(ConnectionPool pool, RealConnection connection);
61 |
62 | public abstract RouteDatabase routeDatabase(ConnectionPool connectionPool);
63 |
64 | public abstract void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket,
65 | boolean isFallback);
66 |
67 | public abstract HttpUrl getHttpUrlChecked(String url)
68 | throws MalformedURLException, UnknownHostException;
69 |
70 | // TODO delete the following when web sockets move into the main package.
71 | public abstract void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket);
72 |
73 | public abstract StreamAllocation callEngineGetStreamAllocation(Call call);
74 | }
75 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/InternalCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal;
17 |
18 | import java.io.IOException;
19 | import okhttp3.Request;
20 | import okhttp3.Response;
21 | import okhttp3.internal.http.CacheRequest;
22 | import okhttp3.internal.http.CacheStrategy;
23 |
24 | /**
25 | * OkHttp's internal cache interface. Applications shouldn't implement this: instead use {@link
26 | * okhttp3.Cache}.
27 | */
28 | public interface InternalCache {
29 | Response get(Request request) throws IOException;
30 |
31 | CacheRequest put(Response response) throws IOException;
32 |
33 | /**
34 | * Remove any cache entries for the supplied {@code request}. This is invoked when the client
35 | * invalidates the cache, such as when making POST requests.
36 | */
37 | void remove(Request request) throws IOException;
38 |
39 | /**
40 | * Handles a conditional request hit by updating the stored cache response with the headers from
41 | * {@code network}. The cached response body is not updated. If the stored response has changed
42 | * since {@code cached} was returned, this does nothing.
43 | */
44 | void update(Response cached, Response network) throws IOException;
45 |
46 | /** Track an conditional GET that was satisfied by this cache. */
47 | void trackConditionalCacheHit();
48 |
49 | /** Track an HTTP response being satisfied with {@code cacheStrategy}. */
50 | void trackResponse(CacheStrategy cacheStrategy);
51 | }
52 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/NamedRunnable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 okhttp3.internal;
18 |
19 | /**
20 | * Runnable implementation which always sets its thread name.
21 | */
22 | public abstract class NamedRunnable implements Runnable {
23 | protected final String name;
24 |
25 | public NamedRunnable(String format, Object... args) {
26 | this.name = String.format(format, args);
27 | }
28 |
29 | @Override public final void run() {
30 | String oldName = Thread.currentThread().getName();
31 | Thread.currentThread().setName(name);
32 | try {
33 | execute();
34 | } finally {
35 | Thread.currentThread().setName(oldName);
36 | }
37 | }
38 |
39 | protected abstract void execute();
40 | }
41 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/OptionalMethod.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package okhttp3.internal;
19 |
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 | import java.lang.reflect.Modifier;
23 |
24 | /**
25 | * Duck-typing for methods: Represents a method that may or may not be present on an object.
26 | *
27 | * @param the type of the object the method might be on, typically an interface or base class
28 | */
29 | class OptionalMethod {
30 |
31 | /** The return type of the method. null means "don't care". */
32 | private final Class> returnType;
33 |
34 | private final String methodName;
35 |
36 | private final Class[] methodParams;
37 |
38 | /**
39 | * Creates an optional method.
40 | *
41 | * @param returnType the return type to required, null if it does not matter
42 | * @param methodName the name of the method
43 | * @param methodParams the method parameter types
44 | */
45 | public OptionalMethod(Class> returnType, String methodName, Class... methodParams) {
46 | this.returnType = returnType;
47 | this.methodName = methodName;
48 | this.methodParams = methodParams;
49 | }
50 |
51 | /**
52 | * Returns true if the method exists on the supplied {@code target}.
53 | */
54 | public boolean isSupported(T target) {
55 | return getMethod(target.getClass()) != null;
56 | }
57 |
58 | /**
59 | * Invokes the method on {@code target} with {@code args}. If the method does not exist or is not
60 | * public then {@code null} is returned. See also {@link #invokeOptionalWithoutCheckedException}.
61 | *
62 | * @throws IllegalArgumentException if the arguments are invalid
63 | * @throws InvocationTargetException if the invocation throws an exception
64 | */
65 | public Object invokeOptional(T target, Object... args) throws InvocationTargetException {
66 | Method m = getMethod(target.getClass());
67 | if (m == null) {
68 | return null;
69 | }
70 | try {
71 | return m.invoke(target, args);
72 | } catch (IllegalAccessException e) {
73 | return null;
74 | }
75 | }
76 |
77 | /**
78 | * Invokes the method on {@code target}. If the method does not exist or is not public then
79 | * {@code null} is returned. Any RuntimeException thrown by the method is thrown, checked
80 | * exceptions are wrapped in an {@link AssertionError}.
81 | *
82 | * @throws IllegalArgumentException if the arguments are invalid
83 | */
84 | public Object invokeOptionalWithoutCheckedException(T target, Object... args) {
85 | try {
86 | return invokeOptional(target, args);
87 | } catch (InvocationTargetException e) {
88 | Throwable targetException = e.getTargetException();
89 | if (targetException instanceof RuntimeException) {
90 | throw (RuntimeException) targetException;
91 | }
92 | AssertionError error = new AssertionError("Unexpected exception");
93 | error.initCause(targetException);
94 | throw error;
95 | }
96 | }
97 |
98 | /**
99 | * Invokes the method on {@code target} with {@code args}. Throws an error if the method is not
100 | * supported. See also {@link #invokeWithoutCheckedException(Object, Object...)}.
101 | *
102 | * @throws IllegalArgumentException if the arguments are invalid
103 | * @throws InvocationTargetException if the invocation throws an exception
104 | */
105 | public Object invoke(T target, Object... args) throws InvocationTargetException {
106 | Method m = getMethod(target.getClass());
107 | if (m == null) {
108 | throw new AssertionError("Method " + methodName + " not supported for object " + target);
109 | }
110 | try {
111 | return m.invoke(target, args);
112 | } catch (IllegalAccessException e) {
113 | // Method should be public: we checked.
114 | AssertionError error = new AssertionError("Unexpectedly could not call: " + m);
115 | error.initCause(e);
116 | throw error;
117 | }
118 | }
119 |
120 | /**
121 | * Invokes the method on {@code target}. Throws an error if the method is not supported. Any
122 | * RuntimeException thrown by the method is thrown, checked exceptions are wrapped in an {@link
123 | * AssertionError}.
124 | *
125 | * @throws IllegalArgumentException if the arguments are invalid
126 | */
127 | public Object invokeWithoutCheckedException(T target, Object... args) {
128 | try {
129 | return invoke(target, args);
130 | } catch (InvocationTargetException e) {
131 | Throwable targetException = e.getTargetException();
132 | if (targetException instanceof RuntimeException) {
133 | throw (RuntimeException) targetException;
134 | }
135 | AssertionError error = new AssertionError("Unexpected exception");
136 | error.initCause(targetException);
137 | throw error;
138 | }
139 | }
140 |
141 | /**
142 | * Perform a lookup for the method. No caching. In order to return a method the method name and
143 | * arguments must match those specified when the {@link OptionalMethod} was created. If the return
144 | * type is specified (i.e. non-null) it must also be compatible. The method must also be public.
145 | */
146 | private Method getMethod(Class> clazz) {
147 | Method method = null;
148 | if (methodName != null) {
149 | method = getPublicMethod(clazz, methodName, methodParams);
150 | if (method != null
151 | && returnType != null
152 | && !returnType.isAssignableFrom(method.getReturnType())) {
153 |
154 | // If the return type is non-null it must be compatible.
155 | method = null;
156 | }
157 | }
158 | return method;
159 | }
160 |
161 | private static Method getPublicMethod(Class> clazz, String methodName, Class[] parameterTypes) {
162 | Method method = null;
163 | try {
164 | method = clazz.getMethod(methodName, parameterTypes);
165 | if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
166 | method = null;
167 | }
168 | } catch (NoSuchMethodException e) {
169 | // None.
170 | }
171 | return method;
172 | }
173 | }
174 |
175 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/RouteDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal;
17 |
18 | import java.util.LinkedHashSet;
19 | import java.util.Set;
20 | import okhttp3.Route;
21 |
22 | /**
23 | * A blacklist of failed routes to avoid when creating a new connection to a target address. This is
24 | * used so that OkHttp can learn from its mistakes: if there was a failure attempting to connect to
25 | * a specific IP address or proxy server, that failure is remembered and alternate routes are
26 | * preferred.
27 | */
28 | public final class RouteDatabase {
29 | private final Set failedRoutes = new LinkedHashSet<>();
30 |
31 | /** Records a failure connecting to {@code failedRoute}. */
32 | public synchronized void failed(Route failedRoute) {
33 | failedRoutes.add(failedRoute);
34 | }
35 |
36 | /** Records success connecting to {@code failedRoute}. */
37 | public synchronized void connected(Route route) {
38 | failedRoutes.remove(route);
39 | }
40 |
41 | /** Returns true if {@code route} has failed recently and should be avoided. */
42 | public synchronized boolean shouldPostpone(Route route) {
43 | return failedRoutes.contains(route);
44 | }
45 |
46 | public synchronized int failedRoutesCount() {
47 | return failedRoutes.size();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/Version.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal;
17 |
18 | public final class Version {
19 | public static String userAgent() {
20 | return "okhttp/${project.version}";
21 | }
22 |
23 | private Version() {
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/ErrorCode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | // http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-7
19 | public enum ErrorCode {
20 | /** Not an error! For SPDY stream resets, prefer null over NO_ERROR. */
21 | NO_ERROR(0, -1, 0),
22 |
23 | PROTOCOL_ERROR(1, 1, 1),
24 |
25 | /** A subtype of PROTOCOL_ERROR used by SPDY. */
26 | INVALID_STREAM(1, 2, -1),
27 |
28 | /** A subtype of PROTOCOL_ERROR used by SPDY. */
29 | UNSUPPORTED_VERSION(1, 4, -1),
30 |
31 | /** A subtype of PROTOCOL_ERROR used by SPDY. */
32 | STREAM_IN_USE(1, 8, -1),
33 |
34 | /** A subtype of PROTOCOL_ERROR used by SPDY. */
35 | STREAM_ALREADY_CLOSED(1, 9, -1),
36 |
37 | INTERNAL_ERROR(2, 6, 2),
38 |
39 | FLOW_CONTROL_ERROR(3, 7, -1),
40 |
41 | STREAM_CLOSED(5, -1, -1),
42 |
43 | FRAME_TOO_LARGE(6, 11, -1),
44 |
45 | REFUSED_STREAM(7, 3, -1),
46 |
47 | CANCEL(8, 5, -1),
48 |
49 | COMPRESSION_ERROR(9, -1, -1),
50 |
51 | CONNECT_ERROR(10, -1, -1),
52 |
53 | ENHANCE_YOUR_CALM(11, -1, -1),
54 |
55 | INADEQUATE_SECURITY(12, -1, -1),
56 |
57 | HTTP_1_1_REQUIRED(13, -1, -1),
58 |
59 | INVALID_CREDENTIALS(-1, 10, -1);
60 |
61 | public final int httpCode;
62 | public final int spdyRstCode;
63 | public final int spdyGoAwayCode;
64 |
65 | private ErrorCode(int httpCode, int spdyRstCode, int spdyGoAwayCode) {
66 | this.httpCode = httpCode;
67 | this.spdyRstCode = spdyRstCode;
68 | this.spdyGoAwayCode = spdyGoAwayCode;
69 | }
70 |
71 | public static ErrorCode fromSpdy3Rst(int code) {
72 | for (ErrorCode errorCode : ErrorCode.values()) {
73 | if (errorCode.spdyRstCode == code) return errorCode;
74 | }
75 | return null;
76 | }
77 |
78 | public static ErrorCode fromHttp2(int code) {
79 | for (ErrorCode errorCode : ErrorCode.values()) {
80 | if (errorCode.httpCode == code) return errorCode;
81 | }
82 | return null;
83 | }
84 |
85 | public static ErrorCode fromSpdyGoAway(int code) {
86 | for (ErrorCode errorCode : ErrorCode.values()) {
87 | if (errorCode.spdyGoAwayCode == code) return errorCode;
88 | }
89 | return null;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/FrameReader.java:
--------------------------------------------------------------------------------
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 okhttp3.internal.framed;
18 |
19 | import java.io.Closeable;
20 | import java.io.IOException;
21 | import java.util.List;
22 | import okio.BufferedSource;
23 | import okio.ByteString;
24 |
25 | /** Reads transport frames for SPDY/3 or HTTP/2. */
26 | public interface FrameReader extends Closeable {
27 | void readConnectionPreface() throws IOException;
28 |
29 | boolean nextFrame(Handler handler) throws IOException;
30 |
31 | interface Handler {
32 | void data(boolean inFinished, int streamId, BufferedSource source, int length)
33 | throws IOException;
34 |
35 | /**
36 | * Create or update incoming headers, creating the corresponding streams if necessary. Frames
37 | * that trigger this are SPDY SYN_STREAM, HEADERS, and SYN_REPLY, and HTTP/2 HEADERS and
38 | * PUSH_PROMISE.
39 | *
40 | * @param outFinished true if the receiver should not send further frames.
41 | * @param inFinished true if the sender will not send further frames.
42 | * @param streamId the stream owning these headers.
43 | * @param associatedStreamId the stream that triggered the sender to create this stream.
44 | */
45 | void headers(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
46 | List headerBlock, HeadersMode headersMode);
47 |
48 | void rstStream(int streamId, ErrorCode errorCode);
49 |
50 | void settings(boolean clearPrevious, Settings settings);
51 |
52 | /** HTTP/2 only. */
53 | void ackSettings();
54 |
55 | /**
56 | * Read a connection-level ping from the peer. {@code ack} indicates this is a reply. Payload
57 | * parameters are different between SPDY/3 and HTTP/2.
58 | *
59 | * In SPDY/3, only the first {@code payload1} parameter is set. If the reader is a client,
60 | * it is an unsigned even number. Likewise, a server will receive an odd number.
61 | *
62 | *
In HTTP/2, both {@code payload1} and {@code payload2} parameters are set. The data is
63 | * opaque binary, and there are no rules on the content.
64 | */
65 | void ping(boolean ack, int payload1, int payload2);
66 |
67 | /**
68 | * The peer tells us to stop creating streams. It is safe to replay streams with {@code ID >
69 | * lastGoodStreamId} on a new connection. In- flight streams with {@code ID <=
70 | * lastGoodStreamId} can only be replayed on a new connection if they are idempotent.
71 | *
72 | * @param lastGoodStreamId the last stream ID the peer processed before sending this message. If
73 | * {@code lastGoodStreamId} is zero, the peer processed no frames.
74 | * @param errorCode reason for closing the connection.
75 | * @param debugData only valid for HTTP/2; opaque debug data to send.
76 | */
77 | void goAway(int lastGoodStreamId, ErrorCode errorCode, ByteString debugData);
78 |
79 | /**
80 | * Notifies that an additional {@code windowSizeIncrement} bytes can be sent on {@code
81 | * streamId}, or the connection if {@code streamId} is zero.
82 | */
83 | void windowUpdate(int streamId, long windowSizeIncrement);
84 |
85 | /**
86 | * Called when reading a headers or priority frame. This may be used to change the stream's
87 | * weight from the default (16) to a new value.
88 | *
89 | * @param streamId stream which has a priority change.
90 | * @param streamDependency the stream ID this stream is dependent on.
91 | * @param weight relative proportion of priority in [1..256].
92 | * @param exclusive inserts this stream ID as the sole child of {@code streamDependency}.
93 | */
94 | void priority(int streamId, int streamDependency, int weight, boolean exclusive);
95 |
96 | /**
97 | * HTTP/2 only. Receive a push promise header block.
A push promise contains all the headers
98 | * that pertain to a server-initiated request, and a {@code promisedStreamId} to which response
99 | * frames will be delivered. Push promise frames are sent as a part of the response to {@code
100 | * streamId}.
101 | *
102 | * @param streamId client-initiated stream ID. Must be an odd number.
103 | * @param promisedStreamId server-initiated stream ID. Must be an even number.
104 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code
105 | * :authority}, and (@code :path}.
106 | */
107 | void pushPromise(int streamId, int promisedStreamId, List requestHeaders)
108 | throws IOException;
109 |
110 | /**
111 | * HTTP/2 only. Expresses that resources for the connection or a client- initiated stream are
112 | * available from a different network location or protocol configuration.
113 | *
114 | * See alt-svc
115 | *
116 | * @param streamId when a client-initiated stream ID (odd number), the origin of this alternate
117 | * service is the origin of the stream. When zero, the origin is specified in the {@code origin}
118 | * parameter.
119 | * @param origin when present, the origin is
120 | * typically represented as a combination of scheme, host and port. When empty, the origin is
121 | * that of the {@code streamId}.
122 | * @param protocol an ALPN protocol, such as {@code h2}.
123 | * @param host an IP address or hostname.
124 | * @param port the IP port associated with the service.
125 | * @param maxAge time in seconds that this alternative is considered fresh.
126 | */
127 | void alternateService(int streamId, String origin, ByteString protocol, String host, int port,
128 | long maxAge);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/FrameWriter.java:
--------------------------------------------------------------------------------
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 okhttp3.internal.framed;
18 |
19 | import java.io.Closeable;
20 | import java.io.IOException;
21 | import java.util.List;
22 | import okio.Buffer;
23 |
24 | /** Writes transport frames for SPDY/3 or HTTP/2. */
25 | public interface FrameWriter extends Closeable {
26 | /** HTTP/2 only. */
27 | void connectionPreface() throws IOException;
28 |
29 | /** Informs the peer that we've applied its latest settings. */
30 | void ackSettings(Settings peerSettings) throws IOException;
31 |
32 | /**
33 | * HTTP/2 only. Send a push promise header block.
34 | *
35 | *
A push promise contains all the headers that pertain to a server-initiated request, and a
36 | * {@code promisedStreamId} to which response frames will be delivered. Push promise frames are
37 | * sent as a part of the response to {@code streamId}. The {@code promisedStreamId} has a priority
38 | * of one greater than {@code streamId}.
39 | *
40 | * @param streamId client-initiated stream ID. Must be an odd number.
41 | * @param promisedStreamId server-initiated stream ID. Must be an even number.
42 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code :authority},
43 | * and (@code :path}.
44 | */
45 | void pushPromise(int streamId, int promisedStreamId, List requestHeaders)
46 | throws IOException;
47 |
48 | /** SPDY/3 only. */
49 | void flush() throws IOException;
50 |
51 | void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
52 | List headerBlock) throws IOException;
53 |
54 | void synReply(boolean outFinished, int streamId, List headerBlock)
55 | throws IOException;
56 |
57 | void headers(int streamId, List headerBlock) throws IOException;
58 |
59 | void rstStream(int streamId, ErrorCode errorCode) throws IOException;
60 |
61 | /** The maximum size of bytes that may be sent in a single call to {@link #data}. */
62 | int maxDataLength();
63 |
64 | /**
65 | * {@code source.length} may be longer than the max length of the variant's data frame.
66 | * Implementations must send multiple frames as necessary.
67 | *
68 | * @param source the buffer to draw bytes from. May be null if byteCount is 0.
69 | * @param byteCount must be between 0 and the minimum of {code source.length} and {@link
70 | * #maxDataLength}.
71 | */
72 | void data(boolean outFinished, int streamId, Buffer source, int byteCount) throws IOException;
73 |
74 | /** Write okhttp's settings to the peer. */
75 | void settings(Settings okHttpSettings) throws IOException;
76 |
77 | /**
78 | * Send a connection-level ping to the peer. {@code ack} indicates this is a reply. Payload
79 | * parameters are different between SPDY/3 and HTTP/2.
80 | *
81 | * In SPDY/3, only the first {@code payload1} parameter is sent. If the sender is a client, it
82 | * is an unsigned odd number. Likewise, a server will send an even number.
83 | *
84 | *
In HTTP/2, both {@code payload1} and {@code payload2} parameters are sent. The data is
85 | * opaque binary, and there are no rules on the content.
86 | */
87 | void ping(boolean ack, int payload1, int payload2) throws IOException;
88 |
89 | /**
90 | * Tell the peer to stop creating streams and that we last processed {@code lastGoodStreamId}, or
91 | * zero if no streams were processed.
92 | *
93 | * @param lastGoodStreamId the last stream ID processed, or zero if no streams were processed.
94 | * @param errorCode reason for closing the connection.
95 | * @param debugData only valid for HTTP/2; opaque debug data to send.
96 | */
97 | void goAway(int lastGoodStreamId, ErrorCode errorCode, byte[] debugData) throws IOException;
98 |
99 | /**
100 | * Inform peer that an additional {@code windowSizeIncrement} bytes can be sent on {@code
101 | * streamId}, or the connection if {@code streamId} is zero.
102 | */
103 | void windowUpdate(int streamId, long windowSizeIncrement) throws IOException;
104 | }
105 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/Header.java:
--------------------------------------------------------------------------------
1 | package okhttp3.internal.framed;
2 |
3 | import okio.ByteString;
4 |
5 | /** HTTP header: the name is an ASCII string, but the value can be UTF-8. */
6 | public final class Header {
7 | // Special header names defined in the SPDY and HTTP/2 specs.
8 | public static final ByteString RESPONSE_STATUS = ByteString.encodeUtf8(":status");
9 | public static final ByteString TARGET_METHOD = ByteString.encodeUtf8(":method");
10 | public static final ByteString TARGET_PATH = ByteString.encodeUtf8(":path");
11 | public static final ByteString TARGET_SCHEME = ByteString.encodeUtf8(":scheme");
12 | public static final ByteString TARGET_AUTHORITY = ByteString.encodeUtf8(":authority"); // HTTP/2
13 | public static final ByteString TARGET_HOST = ByteString.encodeUtf8(":host"); // spdy/3
14 | public static final ByteString VERSION = ByteString.encodeUtf8(":version"); // spdy/3
15 |
16 | /** Name in case-insensitive ASCII encoding. */
17 | public final ByteString name;
18 | /** Value in UTF-8 encoding. */
19 | public final ByteString value;
20 | final int hpackSize;
21 |
22 | // TODO: search for toLowerCase and consider moving logic here.
23 | public Header(String name, String value) {
24 | this(ByteString.encodeUtf8(name), ByteString.encodeUtf8(value));
25 | }
26 |
27 | public Header(ByteString name, String value) {
28 | this(name, ByteString.encodeUtf8(value));
29 | }
30 |
31 | public Header(ByteString name, ByteString value) {
32 | this.name = name;
33 | this.value = value;
34 | this.hpackSize = 32 + name.size() + value.size();
35 | }
36 |
37 | @Override public boolean equals(Object other) {
38 | if (other instanceof Header) {
39 | Header that = (Header) other;
40 | return this.name.equals(that.name)
41 | && this.value.equals(that.value);
42 | }
43 | return false;
44 | }
45 |
46 | @Override public int hashCode() {
47 | int result = 17;
48 | result = 31 * result + name.hashCode();
49 | result = 31 * result + value.hashCode();
50 | return result;
51 | }
52 |
53 | @Override public String toString() {
54 | return String.format("%s: %s", name.utf8(), value.utf8());
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/HeadersMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | public enum HeadersMode {
19 | SPDY_SYN_STREAM,
20 | SPDY_REPLY,
21 | SPDY_HEADERS,
22 | HTTP_20_HEADERS;
23 |
24 | /** Returns true if it is an error these headers to create a new stream. */
25 | public boolean failIfStreamAbsent() {
26 | return this == SPDY_REPLY || this == SPDY_HEADERS;
27 | }
28 |
29 | /** Returns true if it is an error these headers to update an existing stream. */
30 | public boolean failIfStreamPresent() {
31 | return this == SPDY_SYN_STREAM;
32 | }
33 |
34 | /**
35 | * Returns true if it is an error these headers to be the initial headers of a response.
36 | */
37 | public boolean failIfHeadersAbsent() {
38 | return this == SPDY_HEADERS;
39 | }
40 |
41 | /**
42 | * Returns true if it is an error these headers to be update existing headers of a response.
43 | */
44 | public boolean failIfHeadersPresent() {
45 | return this == SPDY_REPLY;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/NameValueBlockReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.zip.DataFormatException;
22 | import java.util.zip.Inflater;
23 | import okio.Buffer;
24 | import okio.BufferedSource;
25 | import okio.ByteString;
26 | import okio.ForwardingSource;
27 | import okio.InflaterSource;
28 | import okio.Okio;
29 | import okio.Source;
30 |
31 | /**
32 | * Reads a SPDY/3 Name/Value header block. This class is made complicated by the requirement that
33 | * we're strict with which bytes we put in the compressed bytes buffer. We need to put all
34 | * compressed bytes into that buffer -- but no other bytes.
35 | */
36 | class NameValueBlockReader {
37 | /** This source transforms compressed bytes into uncompressed bytes. */
38 | private final InflaterSource inflaterSource;
39 |
40 | /**
41 | * How many compressed bytes must be read into inflaterSource before {@link #readNameValueBlock}
42 | * returns.
43 | */
44 | private int compressedLimit;
45 |
46 | /** This source holds inflated bytes. */
47 | private final BufferedSource source;
48 |
49 | public NameValueBlockReader(BufferedSource source) {
50 | // Limit the inflater input stream to only those bytes in the Name/Value
51 | // block. We cut the inflater off at its source because we can't predict the
52 | // ratio of compressed bytes to uncompressed bytes.
53 | Source throttleSource = new ForwardingSource(source) {
54 | @Override public long read(Buffer sink, long byteCount) throws IOException {
55 | if (compressedLimit == 0) return -1; // Out of data for the current block.
56 | long read = super.read(sink, Math.min(byteCount, compressedLimit));
57 | if (read == -1) return -1;
58 | compressedLimit -= read;
59 | return read;
60 | }
61 | };
62 |
63 | // Subclass inflater to install a dictionary when it's needed.
64 | Inflater inflater = new Inflater() {
65 | @Override public int inflate(byte[] buffer, int offset, int count)
66 | throws DataFormatException {
67 | int result = super.inflate(buffer, offset, count);
68 | if (result == 0 && needsDictionary()) {
69 | setDictionary(Spdy3.DICTIONARY);
70 | result = super.inflate(buffer, offset, count);
71 | }
72 | return result;
73 | }
74 | };
75 |
76 | this.inflaterSource = new InflaterSource(throttleSource, inflater);
77 | this.source = Okio.buffer(inflaterSource);
78 | }
79 |
80 | public List readNameValueBlock(int length) throws IOException {
81 | this.compressedLimit += length;
82 |
83 | int numberOfPairs = source.readInt();
84 | if (numberOfPairs < 0) throw new IOException("numberOfPairs < 0: " + numberOfPairs);
85 | if (numberOfPairs > 1024) throw new IOException("numberOfPairs > 1024: " + numberOfPairs);
86 |
87 | List entries = new ArrayList<>(numberOfPairs);
88 | for (int i = 0; i < numberOfPairs; i++) {
89 | ByteString name = readByteString().toAsciiLowercase();
90 | ByteString values = readByteString();
91 | if (name.size() == 0) throw new IOException("name.size == 0");
92 | entries.add(new Header(name, values));
93 | }
94 |
95 | doneReading();
96 | return entries;
97 | }
98 |
99 | private ByteString readByteString() throws IOException {
100 | int length = source.readInt();
101 | return source.readByteString(length);
102 | }
103 |
104 | private void doneReading() throws IOException {
105 | // Move any outstanding unread bytes into the inflater. One side-effect of
106 | // deflate compression is that sometimes there are bytes remaining in the
107 | // stream after we've consumed all of the content.
108 | if (compressedLimit > 0) {
109 | inflaterSource.refill();
110 | if (compressedLimit != 0) throw new IOException("compressedLimit > 0: " + compressedLimit);
111 | }
112 | }
113 |
114 | public void close() throws IOException {
115 | source.close();
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/Ping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | import java.util.concurrent.CountDownLatch;
19 | import java.util.concurrent.TimeUnit;
20 |
21 | /**
22 | * A locally-originated ping.
23 | */
24 | public final class Ping {
25 | private final CountDownLatch latch = new CountDownLatch(1);
26 | private long sent = -1;
27 | private long received = -1;
28 |
29 | Ping() {
30 | }
31 |
32 | void send() {
33 | if (sent != -1) throw new IllegalStateException();
34 | sent = System.nanoTime();
35 | }
36 |
37 | void receive() {
38 | if (received != -1 || sent == -1) throw new IllegalStateException();
39 | received = System.nanoTime();
40 | latch.countDown();
41 | }
42 |
43 | void cancel() {
44 | if (received != -1 || sent == -1) throw new IllegalStateException();
45 | received = sent - 1;
46 | latch.countDown();
47 | }
48 |
49 | /**
50 | * Returns the round trip time for this ping in nanoseconds, waiting for the response to arrive if
51 | * necessary. Returns -1 if the response was canceled.
52 | */
53 | public long roundTripTime() throws InterruptedException {
54 | latch.await();
55 | return received - sent;
56 | }
57 |
58 | /**
59 | * Returns the round trip time for this ping in nanoseconds, or -1 if the response was canceled,
60 | * or -2 if the timeout elapsed before the round trip completed.
61 | */
62 | public long roundTripTime(long timeout, TimeUnit unit) throws InterruptedException {
63 | if (latch.await(timeout, unit)) {
64 | return received - sent;
65 | } else {
66 | return -2;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/PushObserver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | import java.io.IOException;
19 | import java.util.List;
20 | import okhttp3.Protocol;
21 | import okio.BufferedSource;
22 |
23 | /**
24 | * {@link Protocol#HTTP_2 HTTP/2} only. Processes server-initiated HTTP requests on the client.
25 | * Implementations must quickly dispatch callbacks to avoid creating a bottleneck.
26 | *
27 | * While {@link #onReset} may occur at any time, the following callbacks are expected in order,
28 | * correlated by stream ID.
29 | *
30 | *
31 | * - {@link #onRequest}
- {@link #onHeaders} (unless canceled)
32 | *
- {@link #onData} (optional sequence of data frames)
33 | *
34 | *
35 | * As a stream ID is scoped to a single HTTP/2 connection, implementations which target multiple
36 | * connections should expect repetition of stream IDs.
37 | *
38 | *
Return true to request cancellation of a pushed stream. Note that this does not guarantee
39 | * future frames won't arrive on the stream ID.
40 | */
41 | public interface PushObserver {
42 | /**
43 | * Describes the request that the server intends to push a response for.
44 | *
45 | * @param streamId server-initiated stream ID: an even number.
46 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code :authority},
47 | * and (@code :path}.
48 | */
49 | boolean onRequest(int streamId, List requestHeaders);
50 |
51 | /**
52 | * The response headers corresponding to a pushed request. When {@code last} is true, there are
53 | * no data frames to follow.
54 | *
55 | * @param streamId server-initiated stream ID: an even number.
56 | * @param responseHeaders minimally includes {@code :status}.
57 | * @param last when true, there is no response data.
58 | */
59 | boolean onHeaders(int streamId, List responseHeaders, boolean last);
60 |
61 | /**
62 | * A chunk of response data corresponding to a pushed request. This data must either be read or
63 | * skipped.
64 | *
65 | * @param streamId server-initiated stream ID: an even number.
66 | * @param source location of data corresponding with this stream ID.
67 | * @param byteCount number of bytes to read or skip from the source.
68 | * @param last when true, there are no data frames to follow.
69 | */
70 | boolean onData(int streamId, BufferedSource source, int byteCount, boolean last)
71 | throws IOException;
72 |
73 | /** Indicates the reason why this stream was canceled. */
74 | void onReset(int streamId, ErrorCode errorCode);
75 |
76 | PushObserver CANCEL = new PushObserver() {
77 |
78 | @Override public boolean onRequest(int streamId, List requestHeaders) {
79 | return true;
80 | }
81 |
82 | @Override public boolean onHeaders(int streamId, List responseHeaders, boolean last) {
83 | return true;
84 | }
85 |
86 | @Override public boolean onData(int streamId, BufferedSource source, int byteCount,
87 | boolean last) throws IOException {
88 | source.skip(byteCount);
89 | return true;
90 | }
91 |
92 | @Override public void onReset(int streamId, ErrorCode errorCode) {
93 | }
94 | };
95 | }
96 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/framed/Variant.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
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 | package okhttp3.internal.framed;
17 |
18 | import okhttp3.Protocol;
19 | import okio.BufferedSink;
20 | import okio.BufferedSource;
21 |
22 | /** A version and dialect of the framed socket protocol. */
23 | public interface Variant {
24 |
25 | /** The protocol as selected using ALPN. */
26 | Protocol getProtocol();
27 |
28 | /**
29 | * @param client true if this is the HTTP client's reader, reading frames from a server.
30 | */
31 | FrameReader newReader(BufferedSource source, boolean client);
32 |
33 | /**
34 | * @param client true if this is the HTTP client's writer, writing frames to a server.
35 | */
36 | FrameWriter newWriter(BufferedSink sink, boolean client);
37 | }
38 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/CacheRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal.http;
17 |
18 | import java.io.IOException;
19 | import okio.Sink;
20 |
21 | public interface CacheRequest {
22 | Sink body() throws IOException;
23 |
24 | void abort();
25 | }
26 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/HeaderParser.java:
--------------------------------------------------------------------------------
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 okhttp3.internal.http;
18 |
19 | public final class HeaderParser {
20 | /**
21 | * Returns the next index in {@code input} at or after {@code pos} that contains a character from
22 | * {@code characters}. Returns the input length if none of the requested characters can be found.
23 | */
24 | public static int skipUntil(String input, int pos, String characters) {
25 | for (; pos < input.length(); pos++) {
26 | if (characters.indexOf(input.charAt(pos)) != -1) {
27 | break;
28 | }
29 | }
30 | return pos;
31 | }
32 |
33 | /**
34 | * Returns the next non-whitespace character in {@code input} that is white space. Result is
35 | * undefined if input contains newline characters.
36 | */
37 | public static int skipWhitespace(String input, int pos) {
38 | for (; pos < input.length(); pos++) {
39 | char c = input.charAt(pos);
40 | if (c != ' ' && c != '\t') {
41 | break;
42 | }
43 | }
44 | return pos;
45 | }
46 |
47 | /**
48 | * Returns {@code value} as a positive integer, or 0 if it is negative, or {@code defaultValue} if
49 | * it cannot be parsed.
50 | */
51 | public static int parseSeconds(String value, int defaultValue) {
52 | try {
53 | long seconds = Long.parseLong(value);
54 | if (seconds > Integer.MAX_VALUE) {
55 | return Integer.MAX_VALUE;
56 | } else if (seconds < 0) {
57 | return 0;
58 | } else {
59 | return (int) seconds;
60 | }
61 | } catch (NumberFormatException e) {
62 | return defaultValue;
63 | }
64 | }
65 |
66 | private HeaderParser() {
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/HttpDate.java:
--------------------------------------------------------------------------------
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 okhttp3.internal.http;
18 |
19 | import java.text.DateFormat;
20 | import java.text.ParsePosition;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Date;
23 | import java.util.Locale;
24 |
25 | import static okhttp3.internal.Util.UTC;
26 |
27 | /**
28 | * Best-effort parser for HTTP dates.
29 | */
30 | public final class HttpDate {
31 | /** The last four-digit year: "Fri, 31 Dec 9999 23:59:59 GMT". */
32 | public static final long MAX_DATE = 253402300799999L;
33 |
34 | /**
35 | * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such
36 | * cookies are on the fast path.
37 | */
38 | private static final ThreadLocal STANDARD_DATE_FORMAT =
39 | new ThreadLocal() {
40 | @Override protected DateFormat initialValue() {
41 | // RFC 2616 specified: RFC 822, updated by RFC 1123 format with fixed GMT.
42 | DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
43 | rfc1123.setLenient(false);
44 | rfc1123.setTimeZone(UTC);
45 | return rfc1123;
46 | }
47 | };
48 |
49 | /** If we fail to parse a date in a non-standard format, try each of these formats in sequence. */
50 | private static final String[] BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = new String[] {
51 | // HTTP formats required by RFC2616 but with any timezone.
52 | "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 822, updated by RFC 1123 with any TZ
53 | "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 850, obsoleted by RFC 1036 with any TZ.
54 | "EEE MMM d HH:mm:ss yyyy", // ANSI C's asctime() format
55 | // Alternative formats.
56 | "EEE, dd-MMM-yyyy HH:mm:ss z",
57 | "EEE, dd-MMM-yyyy HH-mm-ss z",
58 | "EEE, dd MMM yy HH:mm:ss z",
59 | "EEE dd-MMM-yyyy HH:mm:ss z",
60 | "EEE dd MMM yyyy HH:mm:ss z",
61 | "EEE dd-MMM-yyyy HH-mm-ss z",
62 | "EEE dd-MMM-yy HH:mm:ss z",
63 | "EEE dd MMM yy HH:mm:ss z",
64 | "EEE,dd-MMM-yy HH:mm:ss z",
65 | "EEE,dd-MMM-yyyy HH:mm:ss z",
66 | "EEE, dd-MM-yyyy HH:mm:ss z",
67 |
68 | /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */
69 | "EEE MMM d yyyy HH:mm:ss z",
70 | };
71 |
72 | private static final DateFormat[] BROWSER_COMPATIBLE_DATE_FORMATS =
73 | new DateFormat[BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length];
74 |
75 | /** Returns the date for {@code value}. Returns null if the value couldn't be parsed. */
76 | public static Date parse(String value) {
77 | if (value.length() == 0) {
78 | return null;
79 | }
80 |
81 | ParsePosition position = new ParsePosition(0);
82 | Date result = STANDARD_DATE_FORMAT.get().parse(value, position);
83 | if (position.getIndex() == value.length()) {
84 | // STANDARD_DATE_FORMAT must match exactly; all text must be consumed, e.g. no ignored
85 | // non-standard trailing "+01:00". Those cases are covered below.
86 | return result;
87 | }
88 | synchronized (BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS) {
89 | for (int i = 0, count = BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length; i < count; i++) {
90 | DateFormat format = BROWSER_COMPATIBLE_DATE_FORMATS[i];
91 | if (format == null) {
92 | format = new SimpleDateFormat(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS[i], Locale.US);
93 | // Set the timezone to use when interpreting formats that don't have a timezone. GMT is
94 | // specified by RFC 2616.
95 | format.setTimeZone(UTC);
96 | BROWSER_COMPATIBLE_DATE_FORMATS[i] = format;
97 | }
98 | position.setIndex(0);
99 | result = format.parse(value, position);
100 | if (position.getIndex() != 0) {
101 | // Something was parsed. It's possible the entire string was not consumed but we ignore
102 | // that. If any of the BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS ended in "'GMT'" we'd have
103 | // to also check that position.getIndex() == value.length() otherwise parsing might have
104 | // terminated early, ignoring things like "+01:00". Leaving this as != 0 means that any
105 | // trailing junk is ignored.
106 | return result;
107 | }
108 | }
109 | }
110 | return null;
111 | }
112 |
113 | /** Returns the string for {@code value}. */
114 | public static String format(Date value) {
115 | return STANDARD_DATE_FORMAT.get().format(value);
116 | }
117 |
118 | private HttpDate() {
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/HttpMethod.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal.http;
17 |
18 | public final class HttpMethod {
19 | public static boolean invalidatesCache(String method) {
20 | return method.equals("POST")
21 | || method.equals("PATCH")
22 | || method.equals("PUT")
23 | || method.equals("DELETE")
24 | || method.equals("MOVE"); // WebDAV
25 | }
26 |
27 | public static boolean requiresRequestBody(String method) {
28 | return method.equals("POST")
29 | || method.equals("PUT")
30 | || method.equals("PATCH")
31 | || method.equals("PROPPATCH") // WebDAV
32 | || method.equals("REPORT"); // CalDAV/CardDAV (defined in WebDAV Versioning)
33 | }
34 |
35 | public static boolean permitsRequestBody(String method) {
36 | return requiresRequestBody(method)
37 | || method.equals("OPTIONS")
38 | || method.equals("DELETE") // Permitted as spec is ambiguous.
39 | || method.equals("PROPFIND") // (WebDAV) without body: request
40 | || method.equals("MKCOL") // (WebDAV) may contain a body, but behaviour is unspecified
41 | || method.equals("LOCK"); // (WebDAV) body: create lock, without body: refresh lock
42 | }
43 |
44 | public static boolean redirectsToGet(String method) {
45 | // All requests but PROPFIND should redirect to a GET request.
46 | return !method.equals("PROPFIND");
47 | }
48 |
49 | private HttpMethod() {
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/HttpStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 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 okhttp3.internal.http;
18 |
19 | import java.io.IOException;
20 | import okhttp3.Request;
21 | import okhttp3.Response;
22 | import okhttp3.ResponseBody;
23 | import okio.Sink;
24 |
25 | public interface HttpStream {
26 | /**
27 | * The timeout to use while discarding a stream of input data. Since this is used for connection
28 | * reuse, this timeout should be significantly less than the time it takes to establish a new
29 | * connection.
30 | */
31 | int DISCARD_STREAM_TIMEOUT_MILLIS = 100;
32 |
33 | /** Returns an output stream where the request body can be streamed. */
34 | Sink createRequestBody(Request request, long contentLength) throws IOException;
35 |
36 | /** This should update the HTTP engine's sentRequestMillis field. */
37 | void writeRequestHeaders(Request request) throws IOException;
38 |
39 | /**
40 | * Sends the request body returned by {@link #createRequestBody} to the remote peer.
41 | */
42 | void writeRequestBody(RetryableSink requestBody) throws IOException;
43 |
44 | /** Flush the request to the underlying socket. */
45 | void finishRequest() throws IOException;
46 |
47 | /** Read and return response headers. */
48 | Response.Builder readResponseHeaders() throws IOException;
49 |
50 | /** Returns a stream that reads the response body. */
51 | ResponseBody openResponseBody(Response response) throws IOException;
52 |
53 | void setHttpEngine(HttpEngine httpEngine);
54 |
55 | /**
56 | * Cancel this stream. Resources held by this stream will be cleaned up, though not synchronously.
57 | * That may happen later by the connection pool thread.
58 | */
59 | void cancel();
60 | }
61 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/OkHeaders.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 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 | package okhttp3.internal.http;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collections;
20 | import java.util.List;
21 | import java.util.Set;
22 | import java.util.TreeSet;
23 | import okhttp3.Challenge;
24 | import okhttp3.Headers;
25 | import okhttp3.Protocol;
26 | import okhttp3.Request;
27 | import okhttp3.Response;
28 | import okhttp3.internal.Platform;
29 |
30 | import static okhttp3.internal.Util.equal;
31 |
32 | /** Headers and utilities for internal use by OkHttp. */
33 | public final class OkHeaders {
34 |
35 | static final String PREFIX = Platform.get().getPrefix();
36 |
37 | /**
38 | * Synthetic response header: the local time when the request was sent.
39 | */
40 | public static final String SENT_MILLIS = PREFIX + "-Sent-Millis";
41 |
42 | /**
43 | * Synthetic response header: the local time when the response was received.
44 | */
45 | public static final String RECEIVED_MILLIS = PREFIX + "-Received-Millis";
46 |
47 | /**
48 | * Synthetic response header: the selected {@link Protocol protocol} ("spdy/3.1", "http/1.1",
49 | * etc).
50 | */
51 | public static final String SELECTED_PROTOCOL = PREFIX + "-Selected-Protocol";
52 |
53 | /** Synthetic response header: the location from which the response was loaded. */
54 | public static final String RESPONSE_SOURCE = PREFIX + "-Response-Source";
55 |
56 | private OkHeaders() {
57 | }
58 |
59 | public static long contentLength(Request request) {
60 | return contentLength(request.headers());
61 | }
62 |
63 | public static long contentLength(Response response) {
64 | return contentLength(response.headers());
65 | }
66 |
67 | public static long contentLength(Headers headers) {
68 | return stringToLong(headers.get("Content-Length"));
69 | }
70 |
71 | private static long stringToLong(String s) {
72 | if (s == null) return -1;
73 | try {
74 | return Long.parseLong(s);
75 | } catch (NumberFormatException e) {
76 | return -1;
77 | }
78 | }
79 |
80 | /**
81 | * Returns true if none of the Vary headers have changed between {@code cachedRequest} and {@code
82 | * newRequest}.
83 | */
84 | public static boolean varyMatches(
85 | Response cachedResponse, Headers cachedRequest, Request newRequest) {
86 | for (String field : varyFields(cachedResponse)) {
87 | if (!equal(cachedRequest.values(field), newRequest.headers(field))) return false;
88 | }
89 | return true;
90 | }
91 |
92 | /**
93 | * Returns true if a Vary header contains an asterisk. Such responses cannot be cached.
94 | */
95 | public static boolean hasVaryAll(Response response) {
96 | return hasVaryAll(response.headers());
97 | }
98 |
99 | /**
100 | * Returns true if a Vary header contains an asterisk. Such responses cannot be cached.
101 | */
102 | public static boolean hasVaryAll(Headers responseHeaders) {
103 | return varyFields(responseHeaders).contains("*");
104 | }
105 |
106 | private static Set varyFields(Response response) {
107 | return varyFields(response.headers());
108 | }
109 |
110 | /**
111 | * Returns the names of the request headers that need to be checked for equality when caching.
112 | */
113 | public static Set varyFields(Headers responseHeaders) {
114 | Set result = Collections.emptySet();
115 | for (int i = 0, size = responseHeaders.size(); i < size; i++) {
116 | if (!"Vary".equalsIgnoreCase(responseHeaders.name(i))) continue;
117 |
118 | String value = responseHeaders.value(i);
119 | if (result.isEmpty()) {
120 | result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
121 | }
122 | for (String varyField : value.split(",")) {
123 | result.add(varyField.trim());
124 | }
125 | }
126 | return result;
127 | }
128 |
129 | /**
130 | * Returns the subset of the headers in {@code response}'s request that impact the content of
131 | * response's body.
132 | */
133 | public static Headers varyHeaders(Response response) {
134 | // Use the request headers sent over the network, since that's what the
135 | // response varies on. Otherwise OkHttp-supplied headers like
136 | // "Accept-Encoding: gzip" may be lost.
137 | Headers requestHeaders = response.networkResponse().request().headers();
138 | Headers responseHeaders = response.headers();
139 | return varyHeaders(requestHeaders, responseHeaders);
140 | }
141 |
142 | /**
143 | * Returns the subset of the headers in {@code requestHeaders} that impact the content of
144 | * response's body.
145 | */
146 | public static Headers varyHeaders(Headers requestHeaders, Headers responseHeaders) {
147 | Set varyFields = varyFields(responseHeaders);
148 | if (varyFields.isEmpty()) return new Headers.Builder().build();
149 |
150 | Headers.Builder result = new Headers.Builder();
151 | for (int i = 0, size = requestHeaders.size(); i < size; i++) {
152 | String fieldName = requestHeaders.name(i);
153 | if (varyFields.contains(fieldName)) {
154 | result.add(fieldName, requestHeaders.value(i));
155 | }
156 | }
157 | return result.build();
158 | }
159 |
160 | /**
161 | * Returns true if {@code fieldName} is an end-to-end HTTP header, as defined by RFC 2616,
162 | * 13.5.1.
163 | */
164 | static boolean isEndToEnd(String fieldName) {
165 | return !"Connection".equalsIgnoreCase(fieldName)
166 | && !"Keep-Alive".equalsIgnoreCase(fieldName)
167 | && !"Proxy-Authenticate".equalsIgnoreCase(fieldName)
168 | && !"Proxy-Authorization".equalsIgnoreCase(fieldName)
169 | && !"TE".equalsIgnoreCase(fieldName)
170 | && !"Trailers".equalsIgnoreCase(fieldName)
171 | && !"Transfer-Encoding".equalsIgnoreCase(fieldName)
172 | && !"Upgrade".equalsIgnoreCase(fieldName);
173 | }
174 |
175 | /**
176 | * Parse RFC 2617 challenges. This API is only interested in the scheme name and realm.
177 | */
178 | public static List parseChallenges(Headers responseHeaders, String challengeHeader) {
179 | // auth-scheme = token
180 | // auth-param = token "=" ( token | quoted-string )
181 | // challenge = auth-scheme 1*SP 1#auth-param
182 | // realm = "realm" "=" realm-value
183 | // realm-value = quoted-string
184 | List result = new ArrayList<>();
185 | for (int i = 0, size = responseHeaders.size(); i < size; i++) {
186 | if (!challengeHeader.equalsIgnoreCase(responseHeaders.name(i))) {
187 | continue;
188 | }
189 | String value = responseHeaders.value(i);
190 | int pos = 0;
191 | while (pos < value.length()) {
192 | int tokenStart = pos;
193 | pos = HeaderParser.skipUntil(value, pos, " ");
194 |
195 | String scheme = value.substring(tokenStart, pos).trim();
196 | pos = HeaderParser.skipWhitespace(value, pos);
197 |
198 | // TODO: This currently only handles schemes with a 'realm' parameter;
199 | // It needs to be fixed to handle any scheme and any parameters
200 | // http://code.google.com/p/android/issues/detail?id=11140
201 |
202 | if (!value.regionMatches(true, pos, "realm=\"", 0, "realm=\"".length())) {
203 | break; // Unexpected challenge parameter; give up!
204 | }
205 |
206 | pos += "realm=\"".length();
207 | int realmStart = pos;
208 | pos = HeaderParser.skipUntil(value, pos, "\"");
209 | String realm = value.substring(realmStart, pos);
210 | pos++; // Consume '"' close quote.
211 | pos = HeaderParser.skipUntil(value, pos, ",");
212 | pos++; // Consume ',' comma.
213 | pos = HeaderParser.skipWhitespace(value, pos);
214 | result.add(new Challenge(scheme, realm));
215 | }
216 | }
217 | return result;
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/RealResponseBody.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Square, Inc.
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 | package okhttp3.internal.http;
17 |
18 | import okhttp3.Headers;
19 | import okhttp3.MediaType;
20 | import okhttp3.ResponseBody;
21 | import okio.BufferedSource;
22 |
23 | public final class RealResponseBody extends ResponseBody {
24 | private final Headers headers;
25 | private final BufferedSource source;
26 |
27 | public RealResponseBody(Headers headers, BufferedSource source) {
28 | this.headers = headers;
29 | this.source = source;
30 | }
31 |
32 | @Override public MediaType contentType() {
33 | String contentType = headers.get("Content-Type");
34 | return contentType != null ? MediaType.parse(contentType) : null;
35 | }
36 |
37 | @Override public long contentLength() {
38 | return OkHeaders.contentLength(headers);
39 | }
40 |
41 | @Override public BufferedSource source() {
42 | return source;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/RequestException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 | package okhttp3.internal.http;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * Indicates a problem with interpreting a request. It may indicate there was a problem with the
22 | * request itself, or the environment being used to interpret the request (network failure, etc.).
23 | */
24 | public final class RequestException extends Exception {
25 |
26 | public RequestException(IOException cause) {
27 | super(cause);
28 | }
29 |
30 | @Override
31 | public IOException getCause() {
32 | return (IOException) super.getCause();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/RequestLine.java:
--------------------------------------------------------------------------------
1 | package okhttp3.internal.http;
2 |
3 | import java.net.HttpURLConnection;
4 | import java.net.Proxy;
5 | import okhttp3.HttpUrl;
6 | import okhttp3.Request;
7 |
8 | public final class RequestLine {
9 | private RequestLine() {
10 | }
11 |
12 | /**
13 | * Returns the request status line, like "GET / HTTP/1.1". This is exposed to the application by
14 | * {@link HttpURLConnection#getHeaderFields}, so it needs to be set even if the transport is
15 | * SPDY.
16 | */
17 | static String get(Request request, Proxy.Type proxyType) {
18 | StringBuilder result = new StringBuilder();
19 | result.append(request.method());
20 | result.append(' ');
21 |
22 | if (includeAuthorityInRequestLine(request, proxyType)) {
23 | result.append(request.url());
24 | } else {
25 | result.append(requestPath(request.url()));
26 | }
27 |
28 | result.append(" HTTP/1.1");
29 | return result.toString();
30 | }
31 |
32 | /**
33 | * Returns true if the request line should contain the full URL with host and port (like "GET
34 | * http://android.com/foo HTTP/1.1") or only the path (like "GET /foo HTTP/1.1").
35 | */
36 | private static boolean includeAuthorityInRequestLine(Request request, Proxy.Type proxyType) {
37 | return !request.isHttps() && proxyType == Proxy.Type.HTTP;
38 | }
39 |
40 | /**
41 | * Returns the path to request, like the '/' in 'GET / HTTP/1.1'. Never empty, even if the request
42 | * URL is. Includes the query component if it exists.
43 | */
44 | public static String requestPath(HttpUrl url) {
45 | String path = url.encodedPath();
46 | String query = url.encodedQuery();
47 | return query != null ? (path + '?' + query) : path;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/RetryableSink.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 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 okhttp3.internal.http;
18 |
19 | import java.io.IOException;
20 | import java.net.ProtocolException;
21 | import okio.Buffer;
22 | import okio.Sink;
23 | import okio.Timeout;
24 |
25 | import static okhttp3.internal.Util.checkOffsetAndCount;
26 |
27 | /**
28 | * An HTTP request body that's completely buffered in memory. This allows the post body to be
29 | * transparently re-sent if the HTTP request must be sent multiple times.
30 | */
31 | public final class RetryableSink implements Sink {
32 | private boolean closed;
33 | private final int limit;
34 | private final Buffer content = new Buffer();
35 |
36 | public RetryableSink(int limit) {
37 | this.limit = limit;
38 | }
39 |
40 | public RetryableSink() {
41 | this(-1);
42 | }
43 |
44 | @Override public void close() throws IOException {
45 | if (closed) return;
46 | closed = true;
47 | if (content.size() < limit) {
48 | throw new ProtocolException(
49 | "content-length promised " + limit + " bytes, but received " + content.size());
50 | }
51 | }
52 |
53 | @Override public void write(Buffer source, long byteCount) throws IOException {
54 | if (closed) throw new IllegalStateException("closed");
55 | checkOffsetAndCount(source.size(), 0, byteCount);
56 | if (limit != -1 && content.size() > limit - byteCount) {
57 | throw new ProtocolException("exceeded content-length limit of " + limit + " bytes");
58 | }
59 | content.write(source, byteCount);
60 | }
61 |
62 | @Override public void flush() throws IOException {
63 | }
64 |
65 | @Override public Timeout timeout() {
66 | return Timeout.NONE;
67 | }
68 |
69 | public long contentLength() throws IOException {
70 | return content.size();
71 | }
72 |
73 | public void writeToSocket(Sink socketOut) throws IOException {
74 | // Copy the content; otherwise we won't have data to retry.
75 | Buffer buffer = new Buffer();
76 | content.copyTo(buffer, 0, content.size());
77 | socketOut.write(buffer, buffer.size());
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/RouteException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 | package okhttp3.internal.http;
17 |
18 | import java.io.IOException;
19 | import java.lang.reflect.InvocationTargetException;
20 | import java.lang.reflect.Method;
21 |
22 | /**
23 | * An exception thrown to indicate a problem connecting via a single Route. Multiple attempts may
24 | * have been made with alternative protocols, none of which were successful.
25 | */
26 | public final class RouteException extends Exception {
27 | private static final Method addSuppressedExceptionMethod;
28 |
29 | static {
30 | Method m;
31 | try {
32 | m = Throwable.class.getDeclaredMethod("addSuppressed", Throwable.class);
33 | } catch (Exception e) {
34 | m = null;
35 | }
36 | addSuppressedExceptionMethod = m;
37 | }
38 |
39 | private IOException lastException;
40 |
41 | public RouteException(IOException cause) {
42 | super(cause);
43 | lastException = cause;
44 | }
45 |
46 | public IOException getLastConnectException() {
47 | return lastException;
48 | }
49 |
50 | public void addConnectException(IOException e) {
51 | addSuppressedIfPossible(e, lastException);
52 | lastException = e;
53 | }
54 |
55 | private void addSuppressedIfPossible(IOException e, IOException suppressed) {
56 | if (addSuppressedExceptionMethod != null) {
57 | try {
58 | addSuppressedExceptionMethod.invoke(e, suppressed);
59 | } catch (InvocationTargetException | IllegalAccessException ignored) {
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/http/StatusLine.java:
--------------------------------------------------------------------------------
1 | package okhttp3.internal.http;
2 |
3 | import java.io.IOException;
4 | import java.net.ProtocolException;
5 | import okhttp3.Protocol;
6 | import okhttp3.Response;
7 |
8 | /** An HTTP response status line like "HTTP/1.1 200 OK". */
9 | public final class StatusLine {
10 | /** Numeric status code, 307: Temporary Redirect. */
11 | public static final int HTTP_TEMP_REDIRECT = 307;
12 | public static final int HTTP_PERM_REDIRECT = 308;
13 | public static final int HTTP_CONTINUE = 100;
14 |
15 | public final Protocol protocol;
16 | public final int code;
17 | public final String message;
18 |
19 | public StatusLine(Protocol protocol, int code, String message) {
20 | this.protocol = protocol;
21 | this.code = code;
22 | this.message = message;
23 | }
24 |
25 | public static StatusLine get(Response response) {
26 | return new StatusLine(response.protocol(), response.code(), response.message());
27 | }
28 |
29 | public static StatusLine parse(String statusLine) throws IOException {
30 | // H T T P / 1 . 1 2 0 0 T e m p o r a r y R e d i r e c t
31 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
32 |
33 | // Parse protocol like "HTTP/1.1" followed by a space.
34 | int codeStart;
35 | Protocol protocol;
36 | if (statusLine.startsWith("HTTP/1.")) {
37 | if (statusLine.length() < 9 || statusLine.charAt(8) != ' ') {
38 | throw new ProtocolException("Unexpected status line: " + statusLine);
39 | }
40 | int httpMinorVersion = statusLine.charAt(7) - '0';
41 | codeStart = 9;
42 | if (httpMinorVersion == 0) {
43 | protocol = Protocol.HTTP_1_0;
44 | } else if (httpMinorVersion == 1) {
45 | protocol = Protocol.HTTP_1_1;
46 | } else {
47 | throw new ProtocolException("Unexpected status line: " + statusLine);
48 | }
49 | } else if (statusLine.startsWith("ICY ")) {
50 | // Shoutcast uses ICY instead of "HTTP/1.0".
51 | protocol = Protocol.HTTP_1_0;
52 | codeStart = 4;
53 | } else {
54 | throw new ProtocolException("Unexpected status line: " + statusLine);
55 | }
56 |
57 | // Parse response code like "200". Always 3 digits.
58 | if (statusLine.length() < codeStart + 3) {
59 | throw new ProtocolException("Unexpected status line: " + statusLine);
60 | }
61 | int code;
62 | try {
63 | code = Integer.parseInt(statusLine.substring(codeStart, codeStart + 3));
64 | } catch (NumberFormatException e) {
65 | throw new ProtocolException("Unexpected status line: " + statusLine);
66 | }
67 |
68 | // Parse an optional response message like "OK" or "Not Modified". If it
69 | // exists, it is separated from the response code by a space.
70 | String message = "";
71 | if (statusLine.length() > codeStart + 3) {
72 | if (statusLine.charAt(codeStart + 3) != ' ') {
73 | throw new ProtocolException("Unexpected status line: " + statusLine);
74 | }
75 | message = statusLine.substring(codeStart + 4);
76 | }
77 |
78 | return new StatusLine(protocol, code, message);
79 | }
80 |
81 | @Override public String toString() {
82 | StringBuilder result = new StringBuilder();
83 | result.append(protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1");
84 | result.append(' ').append(code);
85 | if (message != null) {
86 | result.append(' ').append(message);
87 | }
88 | return result.toString();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/okhttp/src/main/java/okhttp3/internal/io/FileSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Square, Inc.
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 | package okhttp3.internal.io;
17 |
18 | import java.io.File;
19 | import java.io.FileNotFoundException;
20 | import java.io.IOException;
21 | import okio.Okio;
22 | import okio.Sink;
23 | import okio.Source;
24 |
25 | /**
26 | * Access to read and write files on a hierarchical data store. Most callers should use the {@link
27 | * #SYSTEM} implementation, which uses the host machine's local file system. Alternate
28 | * implementations may be used to inject faults (for testing) or to transform stored data (to add
29 | * encryption, for example).
30 | *
31 | * All operations on a file system are racy. For example, guarding a call to {@link #source} with
32 | * {@link #exists} does not guarantee that {@link FileNotFoundException} will not be thrown. The
33 | * file may be moved between the two calls!
34 | *
35 | *
This interface is less ambitious than {@link java.nio.file.FileSystem} introduced in Java 7.
36 | * It lacks important features like file watching, metadata, permissions, and disk space
37 | * information. In exchange for these limitations, this interface is easier to implement and works
38 | * on all versions of Java and Android.
39 | */
40 | public interface FileSystem {
41 | /** The host machine's local file system. */
42 | FileSystem SYSTEM = new FileSystem() {
43 | @Override public Source source(File file) throws FileNotFoundException {
44 | return Okio.source(file);
45 | }
46 |
47 | @Override public Sink sink(File file) throws FileNotFoundException {
48 | try {
49 | return Okio.sink(file);
50 | } catch (FileNotFoundException e) {
51 | // Maybe the parent directory doesn't exist? Try creating it first.
52 | file.getParentFile().mkdirs();
53 | return Okio.sink(file);
54 | }
55 | }
56 |
57 | @Override public Sink appendingSink(File file) throws FileNotFoundException {
58 | try {
59 | return Okio.appendingSink(file);
60 | } catch (FileNotFoundException e) {
61 | // Maybe the parent directory doesn't exist? Try creating it first.
62 | file.getParentFile().mkdirs();
63 | return Okio.appendingSink(file);
64 | }
65 | }
66 |
67 | @Override public void delete(File file) throws IOException {
68 | // If delete() fails, make sure it's because the file didn't exist!
69 | if (!file.delete() && file.exists()) {
70 | throw new IOException("failed to delete " + file);
71 | }
72 | }
73 |
74 | @Override public boolean exists(File file) throws IOException {
75 | return file.exists();
76 | }
77 |
78 | @Override public long size(File file) {
79 | return file.length();
80 | }
81 |
82 | @Override public void rename(File from, File to) throws IOException {
83 | delete(to);
84 | if (!from.renameTo(to)) {
85 | throw new IOException("failed to rename " + from + " to " + to);
86 | }
87 | }
88 |
89 | @Override public void deleteContents(File directory) throws IOException {
90 | File[] files = directory.listFiles();
91 | if (files == null) {
92 | throw new IOException("not a readable directory: " + directory);
93 | }
94 | for (File file : files) {
95 | if (file.isDirectory()) {
96 | deleteContents(file);
97 | }
98 | if (!file.delete()) {
99 | throw new IOException("failed to delete " + file);
100 | }
101 | }
102 | }
103 | };
104 |
105 | /** Reads from {@code file}. */
106 | Source source(File file) throws FileNotFoundException;
107 |
108 | /**
109 | * Writes to {@code file}, discarding any data already present. Creates parent directories if
110 | * necessary.
111 | */
112 | Sink sink(File file) throws FileNotFoundException;
113 |
114 | /**
115 | * Writes to {@code file}, appending if data is already present. Creates parent directories if
116 | * necessary.
117 | */
118 | Sink appendingSink(File file) throws FileNotFoundException;
119 |
120 | /** Deletes {@code file} if it exists. Throws if the file exists and cannot be deleted. */
121 | void delete(File file) throws IOException;
122 |
123 | /** Returns true if {@code file} exists on the file system. */
124 | boolean exists(File file) throws IOException;
125 |
126 | /** Returns the number of bytes stored in {@code file}, or 0 if it does not exist. */
127 | long size(File file);
128 |
129 | /** Renames {@code from} to {@code to}. Throws if the file cannot be renamed. */
130 | void rename(File from, File to) throws IOException;
131 |
132 | /**
133 | * Recursively delete the contents of {@code directory}. Throws an IOException if any file could
134 | * not be deleted, or if {@code dir} is not a readable directory.
135 | */
136 | void deleteContents(File directory) throws IOException;
137 | }
138 |
--------------------------------------------------------------------------------
/okhttp/src/test/java/git/dzc/okhttp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/okhttputilslib/.gitignore:
--------------------------------------------------------------------------------
1 | /local.properties
2 | /project.properties
3 | /build
4 |
--------------------------------------------------------------------------------
/okhttputilslib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 |
4 | android {
5 | compileSdkVersion 22
6 | buildToolsVersion "22.0.1"
7 |
8 | defaultConfig {
9 | minSdkVersion 8
10 | targetSdkVersion 22
11 | versionCode 5
12 | versionName "1.0.4"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile 'com.google.code.gson:gson:2.5'
25 | compile project(':okhttp')
26 | }
27 | //apply from: "https://raw.githubusercontent.com/xiaopansky/android-library-publish-to-jcenter/master/bintrayUpload.gradle"
--------------------------------------------------------------------------------
/okhttputilslib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/dzc/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/okhttputilslib/project.properties:
--------------------------------------------------------------------------------
1 | project.name=okhttputilslib
2 | project.groupId=git.dzc.okhttputilslib
3 | project.artifactId=okhttputilslib
4 | project.packaging=jar
5 | project.siteUrl=https://github.com/duzechao/OKHttpUtils
6 | project.gitUrl=https://github.com/duzechao/OKHttpUtils
--------------------------------------------------------------------------------
/okhttputilslib/src/androidTest/java/git/dzc/okhttputilslib/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/okhttputilslib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/okhttputilslib/src/main/java/git/dzc/okhttputilslib/CacheType.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | /**
6 | * Created by dzc on 15/12/5.
7 | */
8 | @IntDef({CacheType.ONLY_NETWORK,CacheType.ONLY_CACHED,CacheType.CACHED_ELSE_NETWORK,CacheType.NETWORK_ELSE_CACHED})
9 | public @interface CacheType {
10 | int ONLY_NETWORK = 0;
11 | int ONLY_CACHED = 1;
12 | int CACHED_ELSE_NETWORK =2;
13 | int NETWORK_ELSE_CACHED = 3;
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/okhttputilslib/src/main/java/git/dzc/okhttputilslib/Callback.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 |
4 |
5 | import java.io.IOException;
6 |
7 | import okhttp3.Call;
8 | import okhttp3.Request;
9 | import okhttp3.Response;
10 |
11 | /**
12 | * Created by dzc on 15/12/11.
13 | */
14 | public abstract class Callback implements okhttp3.Callback {
15 | public void onStart(){
16 |
17 | }
18 | public void onFinish(){
19 |
20 | }
21 |
22 | public abstract void onFailure(Call call, IOException e);
23 |
24 | public abstract void onResponse(Call call, Response response) throws IOException;
25 | }
26 |
--------------------------------------------------------------------------------
/okhttputilslib/src/main/java/git/dzc/okhttputilslib/JsonCallback.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 | import com.google.gson.reflect.TypeToken;
4 |
5 | import okhttp3.Call;
6 | import okhttp3.Request;
7 | import okhttp3.Response;
8 |
9 | import java.io.IOException;
10 | import java.lang.reflect.ParameterizedType;
11 | import java.lang.reflect.Type;
12 |
13 | /**
14 | * Created by dzc on 15/12/10.
15 | */
16 | public abstract class JsonCallback {
17 | public abstract void onFailure(Call call, Exception e);
18 | public abstract void onResponse(Call call,T object) throws IOException;
19 |
20 | public void onStart(){
21 |
22 | }
23 | public void onFinish(){
24 |
25 | }
26 |
27 | Type getType(){
28 | Type type = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
29 | if(type instanceof Class){
30 | return type;
31 | }else{
32 | return new TypeToken(){}.getType();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/okhttputilslib/src/main/java/git/dzc/okhttputilslib/UploadListener.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 | import okhttp3.*;
4 |
5 | /**
6 | * Created by dzc on 15/12/13.
7 | */
8 | public interface UploadListener extends okhttp3.Callback{
9 | void onProgress(long totalBytes, long remainingBytes);
10 | }
11 |
--------------------------------------------------------------------------------
/okhttputilslib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | OKHttpUtilsLib
3 |
4 |
--------------------------------------------------------------------------------
/okhttputilslib/src/test/java/git/dzc/okhttputilslib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package git.dzc.okhttputilslib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':okhttputilslib', ':okhttp'
2 |
--------------------------------------------------------------------------------