Pārlūkot izejas kodu

Add cookie related implementation #156

Ben Hsieh 7 gadus atpakaļ
vecāks
revīzija
6a435dab60

+ 16
- 0
src/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java Parādīt failu

3
 import android.content.Intent;
3
 import android.content.Intent;
4
 import android.net.Uri;
4
 import android.net.Uri;
5
 
5
 
6
+import com.RNFetchBlob.Utils.RNFBCookieJar;
6
 import com.facebook.react.bridge.Callback;
7
 import com.facebook.react.bridge.Callback;
7
 import com.facebook.react.bridge.Promise;
8
 import com.facebook.react.bridge.Promise;
8
 import com.facebook.react.bridge.ReactApplicationContext;
9
 import com.facebook.react.bridge.ReactApplicationContext;
10
 import com.facebook.react.bridge.ReactMethod;
11
 import com.facebook.react.bridge.ReactMethod;
11
 import com.facebook.react.bridge.ReadableArray;
12
 import com.facebook.react.bridge.ReadableArray;
12
 import com.facebook.react.bridge.ReadableMap;
13
 import com.facebook.react.bridge.ReadableMap;
14
+import com.facebook.react.bridge.WritableArray;
13
 
15
 
14
 import java.util.Map;
16
 import java.util.Map;
15
 import java.util.concurrent.LinkedBlockingQueue;
17
 import java.util.concurrent.LinkedBlockingQueue;
203
 
205
 
204
     }
206
     }
205
 
207
 
208
+    @ReactMethod
209
+    /**
210
+     * Get cookies belongs specific host.
211
+     * @param host String host name.
212
+     */
213
+    public void getCookies(String host, Promise promise) {
214
+        try {
215
+            WritableArray cookies = RNFBCookieJar.getCookies(host);
216
+            promise.resolve(cookies);
217
+        } catch(Exception err) {
218
+            promise.reject("RNFetchBlob.getCookies", err.getMessage());
219
+        }
220
+    }
221
+
206
     @ReactMethod
222
     @ReactMethod
207
     /**
223
     /**
208
      * @param path Stream file path
224
      * @param path Stream file path

+ 9
- 0
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java Parādīt failu

11
 
11
 
12
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
12
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
13
 import com.RNFetchBlob.Response.RNFetchBlobFileResp;
13
 import com.RNFetchBlob.Response.RNFetchBlobFileResp;
14
+import com.RNFetchBlob.Utils.RNFBCookieJar;
14
 import com.facebook.react.bridge.Arguments;
15
 import com.facebook.react.bridge.Arguments;
15
 import com.facebook.react.bridge.Callback;
16
 import com.facebook.react.bridge.Callback;
16
 import com.facebook.react.bridge.ReactApplicationContext;
17
 import com.facebook.react.bridge.ReactApplicationContext;
25
 import java.io.FileOutputStream;
26
 import java.io.FileOutputStream;
26
 import java.io.IOException;
27
 import java.io.IOException;
27
 import java.io.InputStream;
28
 import java.io.InputStream;
29
+import java.net.CookieHandler;
30
+import java.net.CookieManager;
31
+import java.net.CookiePolicy;
28
 import java.net.MalformedURLException;
32
 import java.net.MalformedURLException;
29
 import java.net.SocketException;
33
 import java.net.SocketException;
30
 import java.net.SocketTimeoutException;
34
 import java.net.SocketTimeoutException;
39
 
43
 
40
 import okhttp3.Call;
44
 import okhttp3.Call;
41
 import okhttp3.ConnectionPool;
45
 import okhttp3.ConnectionPool;
46
+import okhttp3.CookieJar;
42
 import okhttp3.Headers;
47
 import okhttp3.Headers;
43
 import okhttp3.Interceptor;
48
 import okhttp3.Interceptor;
44
 import okhttp3.MediaType;
49
 import okhttp3.MediaType;
290
                     break;
295
                     break;
291
             }
296
             }
292
 
297
 
298
+            // #156 fix cookie issue
299
+
300
+
293
             final Request req = builder.build();
301
             final Request req = builder.build();
302
+            clientBuilder.cookieJar(new RNFBCookieJar());
294
             clientBuilder.addNetworkInterceptor(new Interceptor() {
303
             clientBuilder.addNetworkInterceptor(new Interceptor() {
295
                 @Override
304
                 @Override
296
                 public Response intercept(Chain chain) throws IOException {
305
                 public Response intercept(Chain chain) throws IOException {

+ 53
- 0
src/android/src/main/java/com/RNFetchBlob/Utils/RNFBCookieJar.java Parādīt failu

1
+package com.RNFetchBlob.Utils;
2
+
3
+import com.facebook.react.bridge.Arguments;
4
+import com.facebook.react.bridge.ReadableMap;
5
+import com.facebook.react.bridge.WritableArray;
6
+import com.facebook.react.bridge.WritableMap;
7
+
8
+import java.util.ArrayList;
9
+import java.util.HashMap;
10
+import java.util.List;
11
+
12
+import okhttp3.Cookie;
13
+import okhttp3.CookieJar;
14
+import okhttp3.HttpUrl;
15
+
16
+/**
17
+ * Created by wkh237on 2016/10/14.
18
+ */
19
+
20
+
21
+
22
+public class RNFBCookieJar implements CookieJar {
23
+
24
+    static final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
25
+    private List<Cookie> cookies;
26
+
27
+    @Override
28
+    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
29
+        cookieStore.put(url.host(), cookies);
30
+    }
31
+
32
+    @Override
33
+    public List<Cookie> loadForRequest(HttpUrl url) {
34
+        List<Cookie> cookies = cookieStore.get(url.host());
35
+        return cookies != null ? cookies : new ArrayList<Cookie>();
36
+    }
37
+
38
+    public static WritableArray getCookies(String host) {
39
+        HttpUrl url = HttpUrl.parse(host);
40
+        List<Cookie> cookies = null;
41
+        if(url != null) {
42
+            cookies = cookieStore.get(url.host());
43
+        }
44
+        WritableArray cookieList = Arguments.createArray();
45
+        if(cookies != null) {
46
+            for(Cookie c : cookies){
47
+                cookieList.pushString(c.toString());
48
+            }
49
+            return cookieList;
50
+        }
51
+        return null;
52
+    }
53
+}

+ 3
- 2
src/index.js Parādīt failu

24
 import polyfill from './polyfill'
24
 import polyfill from './polyfill'
25
 import android from './android'
25
 import android from './android'
26
 import ios from './ios'
26
 import ios from './ios'
27
+import net from './net'
27
 import JSONStream from './json-stream'
28
 import JSONStream from './json-stream'
28
 const {
29
 const {
29
   RNFetchBlobSession,
30
   RNFetchBlobSession,
41
   cp
42
   cp
42
 } = fs
43
 } = fs
43
 
44
 
44
-
45
 const Blob = polyfill.Blob
45
 const Blob = polyfill.Blob
46
 const emitter = DeviceEventEmitter
46
 const emitter = DeviceEventEmitter
47
-const RNFetchBlob:RNFetchBlobNative = NativeModules.RNFetchBlob
47
+const RNFetchBlob= NativeModules.RNFetchBlob
48
 
48
 
49
 // register message channel event handler.
49
 // register message channel event handler.
50
 emitter.addListener("RNFetchBlobMessage", (e) => {
50
 emitter.addListener("RNFetchBlobMessage", (e) => {
549
   session,
549
   session,
550
   fs,
550
   fs,
551
   wrap,
551
   wrap,
552
+  net,
552
   polyfill,
553
   polyfill,
553
   JSONStream
554
   JSONStream
554
 }
555
 }

+ 6
- 2
src/ios/RNFetchBlob/RNFetchBlob.m Parādīt failu

91
 
91
 
92
 }
92
 }
93
 
93
 
94
+
94
 // Fetch blob data request
95
 // Fetch blob data request
95
 RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
96
 RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
96
                   taskId:(NSString *)taskId
97
                   taskId:(NSString *)taskId
473
     return window.rootViewController;
474
     return window.rootViewController;
474
 }
475
 }
475
 
476
 
476
-
477
-#pragma mark RNFetchBlob private methods
477
+# pragma mark - getCookies
478
+RCT_EXPORT_METHOD(getCookies:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject
479
+{
480
+    resolve([RNFetchBlobNetwork getCookies:url]);
481
+})
478
 
482
 
479
 
483
 
480
 @end
484
 @end

+ 1
- 0
src/ios/RNFetchBlobNetwork.h Parādīt failu

44
 - (void) sendRequest:(NSDictionary  * _Nullable )options contentLength:(long)contentLength bridge:(RCTBridge * _Nullable)bridgeRef taskId:(NSString * _Nullable)taskId withRequest:(NSURLRequest * _Nullable)req callback:(_Nullable RCTResponseSenderBlock) callback;
44
 - (void) sendRequest:(NSDictionary  * _Nullable )options contentLength:(long)contentLength bridge:(RCTBridge * _Nullable)bridgeRef taskId:(NSString * _Nullable)taskId withRequest:(NSURLRequest * _Nullable)req callback:(_Nullable RCTResponseSenderBlock) callback;
45
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config;
45
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config;
46
 + (void) enableUploadProgress:(NSString *) taskId config:(RNFetchBlobProgress *)config;
46
 + (void) enableUploadProgress:(NSString *) taskId config:(RNFetchBlobProgress *)config;
47
++ (NSArray *) getCookies:(NSString *) url;
47
 
48
 
48
 
49
 
49
 
50
 

+ 60
- 0
src/ios/RNFetchBlobNetwork.m Parādīt failu

28
 
28
 
29
 NSMapTable * taskTable;
29
 NSMapTable * taskTable;
30
 NSMapTable * expirationTable;
30
 NSMapTable * expirationTable;
31
+NSMapTable * cookiesTable;
31
 NSMutableDictionary * progressTable;
32
 NSMutableDictionary * progressTable;
32
 NSMutableDictionary * uploadProgressTable;
33
 NSMutableDictionary * uploadProgressTable;
33
 
34
 
93
     {
94
     {
94
         uploadProgressTable = [[NSMutableDictionary alloc] init];
95
         uploadProgressTable = [[NSMutableDictionary alloc] init];
95
     }
96
     }
97
+    if(cookiesTable == nil)
98
+    {
99
+        cookiesTable = [[NSMapTable alloc] init];
100
+    }
96
     return self;
101
     return self;
97
 }
102
 }
98
 
103
 
104
++ (NSArray *) getCookies:(NSString *) url
105
+{
106
+    NSString * hostname = [[NSURL URLWithString:url] host];
107
+    NSMutableArray * cookies = [NSMutableArray new];
108
+    NSArray * list = [cookiesTable objectForKey:hostname];
109
+    for(NSHTTPCookie * cookie in list)
110
+    {
111
+        NSMutableString * cookieStr = [[NSMutableString alloc] init];
112
+        [cookieStr appendString:cookie.name];
113
+        [cookieStr appendString:@"="];
114
+        [cookieStr appendString:cookie.value];
115
+        
116
+        if(cookie.expiresDate == nil) {
117
+            [cookieStr appendString:@"; max-age=0"];
118
+        }
119
+        else {
120
+            [cookieStr appendString:@"; expires="];
121
+            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
122
+            [dateFormatter setDateFormat:@"EEE, dd MM yyyy HH:mm:ss ZZZ"];
123
+            NSString *strDate = [dateFormatter stringFromDate:cookie.expiresDate];
124
+            [cookieStr appendString:strDate];
125
+        }
126
+        
127
+        
128
+        [cookieStr appendString:@"; domain="];
129
+        [cookieStr appendString:hostname];
130
+        [cookieStr appendString:@"; path="];
131
+        [cookieStr appendString:cookie.path];
132
+        
133
+        
134
+        if (cookie.isSecure) {
135
+            [cookieStr appendString:@"; secure"];
136
+        }
137
+        
138
+        if (cookie.isHTTPOnly) {
139
+            [cookieStr appendString:@"; httponly"];
140
+        }
141
+        [cookies addObject:cookieStr];
142
+    }
143
+    return cookies;
144
+}
145
+
99
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config
146
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config
100
 {
147
 {
101
     [progressTable setValue:config forKey:taskId];
148
     [progressTable setValue:config forKey:taskId];
253
 
300
 
254
 #pragma mark NSURLSession delegate methods
301
 #pragma mark NSURLSession delegate methods
255
 
302
 
303
+
304
+#pragma mark - Received Response
256
 // set expected content length on response received
305
 // set expected content length on response received
257
 - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
306
 - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
258
 {
307
 {
332
                      @"status": [NSString stringWithFormat:@"%d", statusCode ]
381
                      @"status": [NSString stringWithFormat:@"%d", statusCode ]
333
                     };
382
                     };
334
 
383
 
384
+#pragma mark - handling cookies
385
+        // # 153 get cookies
386
+        if(response.URL != nil)
387
+        {
388
+            NSArray<NSHTTPCookie *> * cookies = [NSHTTPCookie cookiesWithResponseHeaderFields: headers forURL:response.URL];
389
+            if(cookies != nil && [cookies count] > 0) {
390
+                [cookiesTable setObject:cookies forKey:response.URL.host];
391
+            }
392
+        }
393
+        
335
         [self.bridge.eventDispatcher
394
         [self.bridge.eventDispatcher
336
          sendDeviceEventWithName: EVENT_STATE_CHANGE
395
          sendDeviceEventWithName: EVENT_STATE_CHANGE
337
          body:respInfo
396
          body:respInfo
338
         ];
397
         ];
339
         headers = nil;
398
         headers = nil;
340
         respInfo = nil;
399
         respInfo = nil;
400
+
341
     }
401
     }
342
     else
402
     else
343
         NSLog(@"oops");
403
         NSLog(@"oops");

+ 26
- 0
src/net.js Parādīt failu

1
+// Copyright 2016 wkh237@github. All rights reserved.
2
+// Use of this source code is governed by a MIT-style license that can be
3
+// found in the LICENSE file.
4
+// @flow
5
+
6
+import {
7
+  NativeModules,
8
+  DeviceEventEmitter,
9
+  Platform,
10
+  NativeAppEventEmitter,
11
+} from 'react-native'
12
+
13
+const RNFetchBlob = NativeModules.RNFetchBlob
14
+
15
+/**
16
+ * Get cookie according to the given url.
17
+ * @param  {string} url HTTP URL string.
18
+ * @return {Promise<Array<String>>}     Cookies of a specific domain.
19
+ */
20
+function getCookies(url:string):Promise<Array<String>> {
21
+  return RNFetchBlob.getCookies(url)
22
+}
23
+
24
+export default {
25
+  getCookies
26
+}

+ 71
- 54
test/test-0.10.0.js Parādīt failu

26
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
26
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
27
 let begin = Date.now()
27
 let begin = Date.now()
28
 
28
 
29
-describe('json stream via HTTP', (report, done) => {
29
+// describe('json stream via HTTP', (report, done) => {
30
+//
31
+//   let count = 0
32
+//   JSONStream(`${TEST_SERVER_URL}/public/json-dummy.json`).node('name', (name) => {
33
+//     count++
34
+//     if(Date.now() - begin < 100)
35
+//     return
36
+//     begin = Date.now()
37
+//     report(<Info key="report" uid="100">
38
+//       <Text>{count} records</Text>
39
+//     </Info>)
40
+//     done()
41
+//   })
42
+//
43
+// })
44
+//
45
+// describe('json stream via fs', (report, done) => {
46
+//
47
+//   let fetch2 = new RNFetchBlob.polyfill.Fetch({
48
+//     auto : true
49
+//   })
50
+//   let res = null
51
+//   let count = 0
52
+//
53
+//   RNFetchBlob.config({
54
+//     fileCache : true
55
+//   })
56
+//   .fetch('GET',`${TEST_SERVER_URL}/public/json-dummy.json`)
57
+//   .then((resp) => {
58
+//     res = resp
59
+//     JSONStream({
60
+//       url : RNFetchBlob.wrap(res.path()),
61
+//       headers : { bufferSize : 10240 }
62
+//     }).node('name', (name) => {
63
+//       count++
64
+//       if(Date.now() - begin < 100)
65
+//       return
66
+//       begin = Date.now()
67
+//       report(<Info key="report" uid="100">
68
+//         <Text>{count} records</Text>
69
+//       </Info>)
70
+//       done()
71
+//     })
72
+//   })
73
+// })
74
+//
75
+// describe('issue #102', (report, done) => {
76
+//   let tmp = null
77
+//   RNFetchBlob.config({ fileCache: true, appendExt : 'png' })
78
+//     .fetch('GET', `${TEST_SERVER_URL}/public/github.png`)
79
+//     .then((res) => {
80
+//       tmp = res
81
+//       RNFetchBlob.ios.previewDocument(res.path())
82
+//       return RNFetchBlob.fetch('POST', `${TEST_SERVER_URL}/upload-form`, {},
83
+//       [{ name : String(1), data : RNFetchBlob.wrap(res.path()), filename: '#102-test-image.png' }])
84
+//     })
85
+//     .then((res) =>  tmp.flush())
86
+//     .then(() => {
87
+//       done()
88
+//     })
89
+//
90
+// })
30
 
91
 
31
-  let count = 0
32
-  JSONStream(`${TEST_SERVER_URL}/public/json-dummy.json`).node('name', (name) => {
33
-    count++
34
-    if(Date.now() - begin < 100)
35
-    return
36
-    begin = Date.now()
37
-    report(<Info key="report" uid="100">
38
-      <Text>{count} records</Text>
39
-    </Info>)
40
-    done()
41
-  })
42
-
43
-})
44
 
92
 
45
-describe('json stream via fs', (report, done) => {
46
-
47
-  let fetch2 = new RNFetchBlob.polyfill.Fetch({
48
-    auto : true
49
-  })
50
-  let res = null
51
-  let count = 0
93
+describe('cookie test', (report, done) => {
52
 
94
 
53
-  RNFetchBlob.config({
54
-    fileCache : true
95
+  RNFetchBlob.fetch('GET', `${TEST_SERVER_URL}/cookie`)
96
+  .then((res) => {
97
+    return RNFetchBlob.fetch('GET', `${TEST_SERVER_URL}/xhr-header`)
55
   })
98
   })
56
-  .fetch('GET',`${TEST_SERVER_URL}/public/json-dummy.json`)
57
-  .then((resp) => {
58
-    res = resp
59
-    JSONStream({
60
-      url : RNFetchBlob.wrap(res.path()),
61
-      headers : { bufferSize : 10240 }
62
-    }).node('name', (name) => {
63
-      count++
64
-      if(Date.now() - begin < 100)
65
-      return
66
-      begin = Date.now()
67
-      report(<Info key="report" uid="100">
68
-        <Text>{count} records</Text>
69
-      </Info>)
70
-      done()
99
+  .then((res) => {
100
+    console.log(res)
101
+    RNFetchBlob.net.getCookies(`${TEST_SERVER_URL}`)
102
+    .then((cookies) => {
103
+      console.log(cookies)
71
     })
104
     })
72
   })
105
   })
73
-})
74
-
75
-describe('issue #102', (report, done) => {
76
-  let tmp = null
77
-  RNFetchBlob.config({ fileCache: true, appendExt : 'png' })
78
-    .fetch('GET', `${TEST_SERVER_URL}/public/github.png`)
79
-    .then((res) => {
80
-      tmp = res
81
-      RNFetchBlob.ios.previewDocument(res.path())
82
-      return RNFetchBlob.fetch('POST', `${TEST_SERVER_URL}/upload-form`, {},
83
-      [{ name : String(1), data : RNFetchBlob.wrap(res.path()), filename: '#102-test-image.png' }])
84
-    })
85
-    .then((res) =>  tmp.flush())
86
-    .then(() => {
87
-      done()
88
-    })
89
 
106
 
90
 })
107
 })