Skip to content

Commit 91fe3c7

Browse files
committed
feat: basick cookie support
1 parent 0d9d331 commit 91fe3c7

File tree

4 files changed

+127
-3
lines changed

4 files changed

+127
-3
lines changed

src/https.android.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ export function disableSSLPinning() {
101101
console.info('nativescript-https > Disabled SSL pinning by default');
102102

103103
let Client: okhttp3.OkHttpClient;
104-
104+
let cookieJar: com.nativescript.https.QuotePreservingCookieJar;
105+
let cookieManager: java.net.CookieManager;
105106
function getClient(reload: boolean = false, timeout: number = 10): okhttp3.OkHttpClient {
106107
// if (!Client) {
107108
// Client = new okhttp3.OkHttpClient()
@@ -113,6 +114,11 @@ function getClient(reload: boolean = false, timeout: number = 10): okhttp3.OkHtt
113114
if (Client && reload === false && _timeout === timeout) {
114115
return Client;
115116
}
117+
if (!cookieJar) {
118+
cookieManager = new java.net.CookieManager();
119+
cookieManager.setCookiePolicy(java.net.CookiePolicy.ACCEPT_ALL);
120+
cookieJar = new com.nativescript.https.QuotePreservingCookieJar(cookieManager);
121+
}
116122

117123
_timeout = timeout;
118124

@@ -191,6 +197,9 @@ function getClient(reload: boolean = false, timeout: number = 10): okhttp3.OkHtt
191197
if (cache) {
192198
client.cache(cache);
193199
}
200+
if (cookieJar) {
201+
client.cookieJar(cookieJar)
202+
}
194203

195204
// set connection timeout to override okhttp3 default
196205
if (timeout) {
@@ -211,7 +220,7 @@ export function request(opts: Https.HttpsRequestOptions): Promise<Https.HttpsRes
211220
request.url(opts.url);
212221

213222
if (opts.headers) {
214-
// console.log('adding request header', opts.headers)
223+
console.log('adding request header', opts.headers)
215224
Object.keys(opts.headers).forEach(key => request.addHeader(key, opts.headers[key] as any));
216225
}
217226

src/https.ios.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ export function request(opts: Https.HttpsRequestOptions): Promise<Https.HttpsRes
127127
manager.responseSerializer = AFHTTPResponseSerializer.serializer();
128128
}
129129
manager.requestSerializer.allowsCellularAccess = true;
130-
manager.securityPolicy = (policies.secured === true) ? policies.secure : policies.def;
130+
manager.requestSerializer.HTTPShouldHandleCookies = true;
131+
manager.securityPolicy =
132+
policies.secured === true ? policies.secure : policies.def;
131133

132134
if (opts.cachePolicy) {
133135
switch (opts.cachePolicy) {
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.nativescript.https;
2+
/*
3+
* Copyright (C) 2016 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+
import okhttp3.Cookie;
26+
import okhttp3.CookieJar;
27+
import okhttp3.HttpUrl;
28+
import okhttp3.internal.platform.Platform;
29+
30+
import static okhttp3.internal.Util.delimiterOffset;
31+
import static okhttp3.internal.Util.trimSubstring;
32+
import static okhttp3.internal.platform.Platform.WARN;
33+
34+
/** A cookie jar that delegates to a {@link java.net.CookieHandler}. */
35+
public final class QuotePreservingCookieJar implements CookieJar {
36+
private final CookieHandler cookieHandler;
37+
38+
public QuotePreservingCookieJar(CookieHandler cookieHandler) {
39+
this.cookieHandler = cookieHandler;
40+
}
41+
42+
@Override public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
43+
if (cookieHandler != null) {
44+
List<String> cookieStrings = new ArrayList<>();
45+
for (Cookie cookie : cookies) {
46+
cookieStrings.add(cookie.toString().replaceAll("; domain=", "; domain=."));
47+
}
48+
Map<String, List<String>> multimap = Collections.singletonMap("Set-Cookie", cookieStrings);
49+
try {
50+
cookieHandler.put(url.uri(), multimap);
51+
} catch (IOException e) {
52+
Platform.get().log(WARN, "Saving cookies failed for " + url.resolve("/..."), e);
53+
}
54+
}
55+
}
56+
57+
@Override public List<Cookie> loadForRequest(HttpUrl url) {
58+
// The RI passes all headers. We don't have 'em, so we don't pass 'em!
59+
Map<String, List<String>> headers = Collections.emptyMap();
60+
Map<String, List<String>> cookieHeaders;
61+
try {
62+
cookieHeaders = cookieHandler.get(url.uri(), headers);
63+
} catch (IOException e) {
64+
Platform.get().log(WARN, "Loading cookies failed for " + url.resolve("/..."), e);
65+
return Collections.emptyList();
66+
}
67+
68+
List<Cookie> cookies = null;
69+
for (Map.Entry<String, List<String>> entry : cookieHeaders.entrySet()) {
70+
String key = entry.getKey();
71+
if (("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key))
72+
&& !entry.getValue().isEmpty()) {
73+
for (String header : entry.getValue()) {
74+
if (cookies == null) cookies = new ArrayList<>();
75+
cookies.addAll(decodeHeaderAsJavaNetCookies(url, header));
76+
}
77+
}
78+
}
79+
80+
return cookies != null
81+
? Collections.unmodifiableList(cookies)
82+
: Collections.<Cookie>emptyList();
83+
}
84+
85+
/**
86+
* Convert a request header to OkHttp's cookies via {@link HttpCookie}. That extra step handles
87+
* multiple cookies in a single request header, which {@link Cookie#parse} doesn't support.
88+
*/
89+
private List<Cookie> decodeHeaderAsJavaNetCookies(HttpUrl url, String header) {
90+
List<Cookie> result = new ArrayList<>();
91+
for (int pos = 0, limit = header.length(), pairEnd; pos < limit; pos = pairEnd + 1) {
92+
pairEnd = delimiterOffset(header, pos, limit, ";,");
93+
int equalsSign = delimiterOffset(header, pos, pairEnd, '=');
94+
String name = trimSubstring(header, pos, equalsSign);
95+
if (name.startsWith("$")) continue;
96+
97+
// We have either name=value or just a name.
98+
String value = equalsSign < pairEnd
99+
? trimSubstring(header, equalsSign + 1, pairEnd)
100+
: "";
101+
102+
result.add(new Cookie.Builder()
103+
.name(name)
104+
.value(value)
105+
.domain(url.host())
106+
.build());
107+
}
108+
return result;
109+
}
110+
}

src/references.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ declare namespace com {
1414
public constructor();
1515
onStringResponse( responseString:string, statusCode: number, headers: okhttp3.Headers)
1616
}
17+
class QuotePreservingCookieJar extends okhttp3.CookieJar {
18+
constructor(cookieHandler:java.net.CookieHandler)
19+
}
1720
}
1821
}
1922
}

0 commit comments

Comments
 (0)