Skip to content

Commit 2355eb0

Browse files
committed
feat: cachePolicy support
1 parent aeb6fea commit 2355eb0

File tree

3 files changed

+147
-62
lines changed

3 files changed

+147
-62
lines changed

src/https.android.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ let peer: Ipeer = {
1717
validatesDomainName: true
1818
};
1919

20+
let cache:okhttp3.Cache;
21+
22+
export function setCache(options?: Https.CacheOptions) {
23+
if (options) {
24+
cache = new okhttp3.Cache(new java.io.File(options.diskLocation), options.diskSize);
25+
} else {
26+
cache = null
27+
}
28+
if (Client) {
29+
getClient(true);
30+
}
31+
}
32+
export function clearCache() {
33+
if (cache) {
34+
cache.evictAll();
35+
}
36+
}
37+
2038
let _timeout = 10;
2139

2240
export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
@@ -152,6 +170,10 @@ function getClient(reload: boolean = false, timeout: number = 10): okhttp3.OkHtt
152170
}
153171
}
154172

173+
if (cache) {
174+
client.cache(cache);
175+
}
176+
155177
// set connection timeout to override okhttp3 default
156178
if (timeout) {
157179
client
@@ -176,6 +198,22 @@ export function request(opts: Https.HttpsRequestOptions): Promise<Https.HttpsRes
176198
Object.keys(opts.headers).forEach(key => request.addHeader(key, opts.headers[key] as any));
177199
}
178200

201+
if (opts.cachePolicy) {
202+
let cacheControlBuilder = new okhttp3.CacheControl.Builder();
203+
switch (opts.cachePolicy) {
204+
case "noCache":
205+
cacheControlBuilder = cacheControlBuilder.noStore();
206+
break;
207+
case "onlyCache":
208+
cacheControlBuilder = cacheControlBuilder.onlyIfCached();
209+
break;
210+
case "ignoreCache":
211+
cacheControlBuilder = cacheControlBuilder.noCache();
212+
break;
213+
}
214+
request.cacheControl(cacheControlBuilder.build());
215+
}
216+
179217
const methods = {
180218
'GET': 'get',
181219
'HEAD': 'head',

src/https.common.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ export interface HttpsSSLPinningOptions {
88
commonName?: string;
99
useLegacy?: boolean;
1010
}
11+
export interface CacheOptions {
12+
diskLocation: string;
13+
diskSize: number;
14+
memorySize?: number;
15+
}
1116

1217
export interface HttpsRequestObject {
1318
[key: string]: string | number;
1419
}
1520

21+
22+
export type CachePolicy = 'noCache' | 'onlyCache' | 'ignoreCache';
1623
export interface HttpsRequestOptions {
1724
url: string;
1825
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
@@ -29,6 +36,8 @@ export interface HttpsRequestOptions {
2936
* Default 10 (seconds).
3037
*/
3138
timeout?: number;
39+
40+
cachePolicy?:CachePolicy
3241
}
3342

3443
export interface HttpsResponse {

src/https.ios.ts

Lines changed: 100 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,65 @@
11
import { isDefined, isNullOrUndefined, isObject } from 'tns-core-modules/utils/types';
22
import * as Https from './https.common';
33

4-
interface Ipolicies {
5-
def: AFSecurityPolicy;
6-
secured: boolean;
7-
secure?: AFSecurityPolicy;
4+
let useLegacy: boolean = false;
5+
6+
let cache: NSURLCache;
7+
8+
export function setCache(options?: Https.CacheOptions) {
9+
if (options) {
10+
cache = NSURLCache.alloc().initWithMemoryCapacityDiskCapacityDirectoryURL(
11+
options.memorySize,
12+
options.diskSize,
13+
NSURL.URLWithString(options.diskLocation)
14+
);
15+
} else {
16+
cache = null;
17+
}
18+
NSURLCache.sharedURLCache = cache;
19+
}
20+
export function clearCache() {
21+
if (cache) {
22+
cache.removeAllCachedResponses();
23+
}
824
}
925

10-
let useLegacy: boolean = false;
26+
interface Ipolicies {
27+
def: AFSecurityPolicy;
28+
secured: boolean;
29+
secure?: AFSecurityPolicy;
30+
}
1131

1232
let policies: Ipolicies = {
13-
def: AFSecurityPolicy.defaultPolicy(),
14-
secured: false,
33+
def: AFSecurityPolicy.defaultPolicy(),
34+
secured: false,
1535
};
1636

1737
policies.def.allowInvalidCertificates = true;
1838
policies.def.validatesDomainName = false;
1939

2040
export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
21-
if (!policies.secure) {
41+
if (!policies.secure) {
2242
policies.secure = AFSecurityPolicy.policyWithPinningMode(AFSSLPinningMode.PublicKey);
2343
policies.secure.allowInvalidCertificates = (isDefined(options.allowInvalidCertificates)) ? options.allowInvalidCertificates : false;
2444
policies.secure.validatesDomainName = (isDefined(options.validatesDomainName)) ? options.validatesDomainName : true;
25-
let data = NSData.dataWithContentsOfFile(options.certificate);
26-
policies.secure.pinnedCertificates = NSSet.setWithObject(data);
27-
}
45+
let data = NSData.dataWithContentsOfFile(options.certificate);
46+
policies.secure.pinnedCertificates = NSSet.setWithObject(data);
47+
}
2848
useLegacy = (isDefined(options.useLegacy)) ? options.useLegacy : false;
29-
policies.secured = true;
49+
policies.secured = true;
3050
console.log('nativescript-https > Enabled SSL pinning');
3151
}
3252

3353
export function disableSSLPinning() {
34-
policies.secured = false;
54+
policies.secured = false;
3555
console.log('nativescript-https > Disabled SSL pinning');
3656
}
3757

3858
console.info('nativescript-https > Disabled SSL pinning by default');
3959

4060
function AFSuccess(resolve, task: NSURLSessionDataTask, data?: NSDictionary<string, any> & NSData & NSArray<any>) {
4161
let content = getData(data);
42-
resolve({task, content});
62+
resolve({ task, content });
4363
}
4464

4565
function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError) {
@@ -60,8 +80,8 @@ function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError)
6080
} else {
6181
let content: any = {
6282
body: parsedData,
63-
description: error.description,
64-
reason: error.localizedDescription,
83+
description: error.description,
84+
reason: error.localizedDescription,
6585
url: error.userInfo.objectForKey('NSErrorFailingURLKey').description
6686
};
6787

@@ -70,53 +90,71 @@ function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError)
7090
}
7191

7292
let reason = error.localizedDescription;
73-
resolve({task, content, reason});
74-
}
93+
resolve({ task, content, reason });
94+
}
7595
}
7696

7797
export function request(opts: Https.HttpsRequestOptions): Promise<Https.HttpsResponse> {
78-
return new Promise((resolve, reject) => {
79-
try {
98+
return new Promise((resolve, reject) => {
99+
try {
80100
const manager = AFHTTPSessionManager.alloc().initWithBaseURL(NSURL.URLWithString(opts.url));
81101
if (opts.headers && (<any>opts.headers['Content-Type']).substring(0, 16) === 'application/json') {
82-
manager.requestSerializer = AFJSONRequestSerializer.serializer();
102+
manager.requestSerializer = AFJSONRequestSerializer.serializer();
83103
manager.responseSerializer = AFJSONResponseSerializer.serializerWithReadingOptions(NSJSONReadingOptions.AllowFragments);
84-
} else {
85-
manager.requestSerializer = AFHTTPRequestSerializer.serializer();
86-
manager.responseSerializer = AFHTTPResponseSerializer.serializer();
87-
}
88-
manager.requestSerializer.allowsCellularAccess = true;
104+
} else {
105+
manager.requestSerializer = AFHTTPRequestSerializer.serializer();
106+
manager.responseSerializer = AFHTTPResponseSerializer.serializer();
107+
}
108+
manager.requestSerializer.allowsCellularAccess = true;
89109
manager.securityPolicy = (policies.secured === true) ? policies.secure : policies.def;
90110

91-
let heads = opts.headers;
92-
if (heads) {
111+
if (opts.cachePolicy) {
112+
let cacheControlBuilder = new okhttp3.CacheControl.Builder();
113+
switch (opts.cachePolicy) {
114+
case "noCache":
115+
manager.setDataTaskWillCacheResponseBlock((session, task, cacheResponse) => {
116+
return null;
117+
});
118+
break;
119+
case "onlyCache":
120+
manager.requestSerializer.cachePolicy =
121+
NSURLRequestCachePolicy.ReturnCacheDataDontLoad;
122+
break;
123+
case "ignoreCache":
124+
manager.requestSerializer.cachePolicy =
125+
NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData;
126+
break;
127+
}
128+
}
129+
let heads = opts.headers;
130+
if (heads) {
93131
Object.keys(heads).forEach(key => manager.requestSerializer.setValueForHTTPHeaderField(heads[key] as any, key));
94-
}
95-
96-
let dict = null;
97-
if (opts.body) {
98-
let cont = opts.body;
99-
if (Array.isArray(cont)) {
100-
dict = NSMutableArray.new();
101-
cont.forEach(function (item, idx) {
102-
dict.addObject(item);
103-
});
104-
} else if (isObject(cont)) {
105-
dict = NSMutableDictionary.new<string, any>();
132+
}
133+
134+
let dict = null;
135+
if (opts.body) {
136+
let cont = opts.body;
137+
if (Array.isArray(cont)) {
138+
dict = NSMutableArray.new();
139+
cont.forEach(function(item, idx) {
140+
dict.addObject(item);
141+
});
142+
} else if (isObject(cont)) {
143+
dict = NSMutableDictionary.new<string, any>();
106144
Object.keys(cont).forEach(key => dict.setValueForKey(cont[key] as any, key));
107-
}
108-
}
145+
}
146+
}
109147

110148
manager.requestSerializer.timeoutInterval = opts.timeout ? opts.timeout : 10;
111149

112150
const headers = null;
113151

114152
const success = (task: NSURLSessionDataTask, data?: any) => {
115-
AFSuccess(resolve, task, data);
153+
AFSuccess(resolve, task, data);
116154
};
117155

118156
const failure = (task, error) => {
119-
AFFailure(resolve, reject, task, error);
157+
AFFailure(resolve, reject, task, error);
120158
};
121159

122160
const progress = (progress: NSProgress) => {
@@ -138,32 +176,32 @@ export function request(opts: Https.HttpsRequestOptions): Promise<Https.HttpsRes
138176
}
139177

140178

141-
} catch (error) {
142-
reject(error);
143-
}
179+
} catch (error) {
180+
reject(error);
181+
}
144182

145183
}).then((AFResponse: {
146184
task: NSURLSessionDataTask
147185
content: any
148186
reason?: string
149-
}) => {
150-
let sendi: Https.HttpsResponse = {
151-
content: AFResponse.content,
152-
headers: {},
153-
};
154-
155-
let response = AFResponse.task.response as NSHTTPURLResponse;
156-
if (!isNullOrUndefined(response)) {
157-
sendi.statusCode = response.statusCode;
158-
let dict = response.allHeaderFields;
187+
}) => {
188+
let sendi: Https.HttpsResponse = {
189+
content: AFResponse.content,
190+
headers: {},
191+
};
192+
193+
let response = AFResponse.task.response as NSHTTPURLResponse;
194+
if (!isNullOrUndefined(response)) {
195+
sendi.statusCode = response.statusCode;
196+
let dict = response.allHeaderFields;
159197
dict.enumerateKeysAndObjectsUsingBlock((k, v) => sendi.headers[k] = v);
160-
}
198+
}
161199

162-
if (AFResponse.reason) {
163-
sendi.reason = AFResponse.reason;
164-
}
200+
if (AFResponse.reason) {
201+
sendi.reason = AFResponse.reason;
202+
}
165203

166-
return Promise.resolve(sendi);
204+
return Promise.resolve(sendi);
167205
});
168206
}
169207

0 commit comments

Comments
 (0)