Skip to content

Commit db63d1a

Browse files
committed
Share cookies between built-in HttpURLConnection and OkHttpClient
1 parent e2c9363 commit db63d1a

File tree

2 files changed

+135
-2
lines changed

2 files changed

+135
-2
lines changed

src/AndroidClient/android/src/main/java/net/servicestack/android/AndroidServerEventsClient.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.InputStream;
2020
import java.io.InterruptedIOException;
2121
import java.lang.reflect.Field;
22+
import java.net.CookieHandler;
2223
import java.net.HttpURLConnection;
2324
import java.net.SocketException;
2425
import java.net.URL;
@@ -39,9 +40,15 @@
3940
*/
4041

4142
public class AndroidServerEventsClient extends ServerEventsClient {
43+
protected OkHttpClient client;
44+
4245
public AndroidServerEventsClient(String baseUri, String... channels) {
4346
super(baseUri, channels);
4447
this.serviceClient = new AndroidServiceClient(this.baseUri);
48+
49+
client = new OkHttpClient.Builder()
50+
.cookieJar(new JavaNetCookieJar(CookieHandler.getDefault()))
51+
.build();
4552
}
4653

4754
public AndroidServerEventsClient(String baseUrl, String channel) {
@@ -52,6 +59,15 @@ public AndroidServerEventsClient(String baseUrl) {
5259
this(baseUrl, new String[]{});
5360
}
5461

62+
public AndroidServerEventsClient setOkHttpClient(OkHttpClient client){
63+
this.client = client;
64+
return this;
65+
}
66+
67+
public OkHttpClient getOkHttpClient(){
68+
return client;
69+
}
70+
5571
public AndroidServiceClient getAndroidClient(){
5672
return (AndroidServiceClient) this.serviceClient;
5773
}
@@ -61,8 +77,6 @@ protected EventStream createEventStream() {
6177
return new AndroidEventStream(this);
6278
}
6379

64-
public static final OkHttpClient client = new OkHttpClient();
65-
6680
class AndroidEventStream extends EventStream
6781
{
6882
public AndroidEventStream(ServerEventsClient client) {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package net.servicestack.android;
2+
/*
3+
* Copyright (C) 2015 Square, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* 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+
import java.io.IOException;
19+
import java.net.CookieHandler;
20+
import java.net.HttpCookie;
21+
import java.util.ArrayList;
22+
import java.util.Collections;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
import okhttp3.Cookie;
27+
import okhttp3.CookieJar;
28+
import okhttp3.HttpUrl;
29+
import okhttp3.internal.platform.Platform;
30+
31+
import static okhttp3.internal.Util.delimiterOffset;
32+
import static okhttp3.internal.Util.trimSubstring;
33+
import static okhttp3.internal.platform.Platform.WARN;
34+
35+
/** A cookie jar that delegates to a {@link java.net.CookieHandler}. */
36+
public final class JavaNetCookieJar implements CookieJar {
37+
38+
private final CookieHandler cookieHandler;
39+
40+
public JavaNetCookieJar(CookieHandler cookieHandler) {
41+
this.cookieHandler = cookieHandler;
42+
}
43+
44+
@Override
45+
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
46+
if (cookieHandler != null) {
47+
List<String> cookieStrings = new ArrayList<>();
48+
for (Cookie cookie : cookies) {
49+
cookieStrings.add(cookie.toString());
50+
}
51+
Map<String, List<String>> multimap = Collections.singletonMap("Set-Cookie", cookieStrings);
52+
try {
53+
cookieHandler.put(url.uri(), multimap);
54+
} catch (IOException e) {
55+
Platform.get().log(WARN, "Saving cookies failed for " + url.resolve("/..."), e);
56+
}
57+
}
58+
}
59+
60+
@Override
61+
public List<Cookie> loadForRequest(HttpUrl url) {
62+
// The RI passes all headers. We don't have 'em, so we don't pass 'em!
63+
Map<String, List<String>> headers = Collections.emptyMap();
64+
Map<String, List<String>> cookieHeaders;
65+
try {
66+
cookieHeaders = cookieHandler.get(url.uri(), headers);
67+
} catch (IOException e) {
68+
Platform.get().log(WARN, "Loading cookies failed for " + url.resolve("/..."), e);
69+
return Collections.emptyList();
70+
}
71+
72+
List<Cookie> cookies = null;
73+
for (Map.Entry<String, List<String>> entry : cookieHeaders.entrySet()) {
74+
String key = entry.getKey();
75+
if (("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key))
76+
&& !entry.getValue().isEmpty()) {
77+
for (String header : entry.getValue()) {
78+
if (cookies == null) cookies = new ArrayList<>();
79+
cookies.addAll(decodeHeaderAsJavaNetCookies(url, header));
80+
}
81+
}
82+
}
83+
84+
return cookies != null
85+
? Collections.unmodifiableList(cookies)
86+
: Collections.<Cookie>emptyList();
87+
}
88+
89+
/**
90+
* Convert a request header to OkHttp's cookies via {@link HttpCookie}. That extra step handles
91+
* multiple cookies in a single request header, which {@link Cookie#parse} doesn't support.
92+
*/
93+
private List<Cookie> decodeHeaderAsJavaNetCookies(HttpUrl url, String header) {
94+
List<Cookie> result = new ArrayList<>();
95+
for (int pos = 0, limit = header.length(), pairEnd; pos < limit; pos = pairEnd + 1) {
96+
pairEnd = delimiterOffset(header, pos, limit, ";,");
97+
int equalsSign = delimiterOffset(header, pos, pairEnd, '=');
98+
String name = trimSubstring(header, pos, equalsSign);
99+
if (name.startsWith("$")) continue;
100+
101+
// We have either name=value or just a name.
102+
String value = equalsSign < pairEnd
103+
? trimSubstring(header, equalsSign + 1, pairEnd)
104+
: "";
105+
106+
// If the value is "quoted", drop the quotes.
107+
if (value.startsWith("\"") && value.endsWith("\"")) {
108+
value = value.substring(1, value.length() - 1);
109+
}
110+
111+
result.add(new Cookie.Builder()
112+
.name(name)
113+
.value(value)
114+
.domain(url.host())
115+
.build());
116+
}
117+
return result;
118+
}
119+
}

0 commit comments

Comments
 (0)