Browse Source

wip commit

Ben Hsieh 8 years ago
parent
commit
ded20c2dd1
4 changed files with 87 additions and 45 deletions
  1. 10
    4
      src/index.js
  2. 8
    2
      src/ios/RNFetchBlobReqBuilder.m
  3. 43
    14
      src/polyfill/XMLHttpRequest.js
  4. 26
    25
      test/test-firebase.js

+ 10
- 4
src/index.js View File

@@ -109,26 +109,27 @@ function fetch(...args:any):Promise {
109 109
   // create task ID for receiving progress event
110 110
   let taskId = getUUID()
111 111
   let options = this || {}
112
+  let subscription, subscriptionUpload, stateEvent
112 113
 
113 114
   let promise = new Promise((resolve, reject) => {
114 115
     let [method, url, headers, body] = [...args]
115 116
     let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
116 117
 
117 118
     // on progress event listener
118
-    let subscription = emitter.addListener('RNFetchBlobProgress', (e) => {
119
+    subscription = emitter.addListener('RNFetchBlobProgress', (e) => {
119 120
       if(e.taskId === taskId && promise.onProgress) {
120 121
         promise.onProgress(e.written, e.total)
121 122
       }
122 123
     })
123 124
 
124
-    let subscriptionUpload = emitter.addListener('RNFetchBlobProgress-upload', (e) => {
125
+    subscriptionUpload = emitter.addListener('RNFetchBlobProgress-upload', (e) => {
125 126
       if(e.taskId === taskId && promise.onUploadProgress) {
126 127
         promise.onUploadProgress(e.written, e.total)
127 128
       }
128 129
     })
129 130
 
130
-    let stateEvent = emitter.addListener('RNFetchBlobState', (e) => {
131
-      if(e.taskId === taskId && promise.onUploadProgress) {
131
+    stateEvent = emitter.addListener('RNFetchBlobState', (e) => {
132
+      if(e.taskId === taskId && promise.onStateChange) {
132 133
         promise.onStateChange(e)
133 134
       }
134 135
     })
@@ -166,10 +167,15 @@ function fetch(...args:any):Promise {
166 167
     promise.onUploadProgress = fn
167 168
     return promise
168 169
   }
170
+  promise.stateChange = (fn) => {
171
+    promise.onStateChange = fn
172
+    return promise
173
+  }
169 174
   promise.cancel = (fn) => {
170 175
     fn = fn || function(){}
171 176
     subscription.remove()
172 177
     subscriptionUpload.remove()
178
+    stateEvent.remove()
173 179
     RNFetchBlob.cancelRequest(taskId, fn)
174 180
   }
175 181
 

+ 8
- 2
src/ios/RNFetchBlobReqBuilder.m View File

@@ -95,7 +95,10 @@
95 95
                     {
96 96
                         [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
97 97
                             [request setHTTPBody:content];
98
-                            [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
98
+                            if([mheaders valueForKey:@"content-type"] == nil)
99
+                            {
100
+                                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
101
+                            }
99 102
                             [request setHTTPMethod: method];
100 103
                             [request setAllHTTPHeaderFields:mheaders];
101 104
                             onComplete(request, [content length]);
@@ -111,7 +114,10 @@
111 114
                     [request setHTTPBody:blobData];
112 115
                 }
113 116
                 
114
-                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
117
+                if([mheaders valueForKey:@"content-type"] == nil)
118
+                {
119
+                    [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
120
+                }
115 121
                 
116 122
             }
117 123
         }

+ 43
- 14
src/polyfill/XMLHttpRequest.js View File

@@ -19,6 +19,7 @@ export default class XMLHttpRequest extends EventTarget{
19 19
   readyState : number;
20 20
   response : any;
21 21
   responseText : any;
22
+  responseHeaders : any;
22 23
   responseType : '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text';
23 24
   // TODO : not suppoted for now
24 25
   responseURL : null;
@@ -38,21 +39,20 @@ export default class XMLHttpRequest extends EventTarget{
38 39
   // `cancel` methods.
39 40
   _task: any;
40 41
 
41
-  constructor() {
42
+  constructor(...args) {
42 43
     super()
43
-    console.log('---------------------------------')
44
-    console.log('XMLHttpRequest constructor called')
44
+    console.log('XMLHttpRequest constructor called', args)
45 45
     this._config = {}
46 46
     this._args = {}
47 47
     this._headers = {}
48 48
     this.readyState = 0
49 49
     this.response = null
50 50
     this.responseText = null
51
+    this.responseHeaders = null
51 52
   }
52 53
 
53 54
   // XMLHttpRequest.open, always async, user and password not supported.
54 55
   open(method:string, url:string, async:true, user:any, password:any) {
55
-    console.log('---------------------------------')
56 56
     console.log('XMLHttpRequest open called', method, url, async, user, password)
57 57
     this._method = method
58 58
     this._url = url
@@ -61,10 +61,10 @@ export default class XMLHttpRequest extends EventTarget{
61 61
       this.onload()
62 62
     if(this.onloadstart)
63 63
       this.onloadstart()
64
+    this._invokeOnStateChange()
64 65
   }
65 66
 
66 67
   addEventListener(event, listener) {
67
-    console.log('---------------------------------')
68 68
     console.log('XMLHttpRequest add listener', event, listener.toString())
69 69
     this.addEventListener(event, listener)
70 70
   }
@@ -74,13 +74,20 @@ export default class XMLHttpRequest extends EventTarget{
74 74
    * @param  {any} body Body in RNfetchblob flavor
75 75
    */
76 76
   send(body) {
77
-    console.log('---------------------------------')
78 77
     console.log('XMLHttpRequest send called', body)
79
-    let [_method, _url, _headers] = this
78
+    let {_method, _url, _headers } = this
80 79
     console.log('sending request with args', _method, _url, _headers, body)
81 80
 
82 81
     this._task = RNFetchBlob.fetch(_method, _url, _headers, body)
83 82
     this._task
83
+        .stateChange((e) => {
84
+          console.log('state change')
85
+          if(e.state === "2") {
86
+            this.readyState = 2
87
+            this.responseHeaders = e.headers
88
+          }
89
+          this._invokeOnStateChange()
90
+        })
84 91
         .uploadProgress(this._progressEvent)
85 92
         .onProgress(this._progressEvent)
86 93
         .then(this._onDone)
@@ -97,8 +104,9 @@ export default class XMLHttpRequest extends EventTarget{
97 104
   }
98 105
 
99 106
   abort() {
100
-    console.log('---------------------------------')
101 107
     console.log('XMLHttpRequest abort called', this._task)
108
+    if(!this._task)
109
+      return
102 110
     this._task.cancel((err) => {
103 111
       let e = {
104 112
         timeStamp : Date.now(),
@@ -117,16 +125,24 @@ export default class XMLHttpRequest extends EventTarget{
117 125
     })
118 126
   }
119 127
 
120
-  getResponseHeader(field:string):string | null{
128
+  getResponseHeader(field:string):string | null {
129
+
130
+    if(!this.responseHeaders)
131
+      return null
132
+    return this.responseHeaders[field] || null
121 133
 
122 134
   }
123 135
 
124 136
   getAllResponseHeaders():string | null {
125 137
 
126
-  }
127
-
128
-  set onreadystatechange(handler:() => void) {
129
-    this.onreadystatechange = handler
138
+    if(!this.responseHeaders)
139
+      return null
140
+    let result = ''
141
+    let respHeaders = this.responseHeaders
142
+    for(let i in respHeaders) {
143
+      result += `${i}:${respHeaders[i]}\r\n`
144
+    }
145
+    return result
130 146
   }
131 147
 
132 148
   _progressEvent(send:number, total:number) {
@@ -143,8 +159,11 @@ export default class XMLHttpRequest extends EventTarget{
143 159
   }
144 160
 
145 161
   _onError(err) {
162
+    console.log('XMLHttpRequest error', err)
146 163
     this.statusText = err
147
-
164
+    this.status = String(err).match(/\d+/)
165
+    this.status = this.status ? Math.floor(this.status) : 404
166
+    this.readyState = 4
148 167
     if(String(err).match('timeout') !== null) {
149 168
       if(this.ontimeout)
150 169
         this.ontimeout()
@@ -155,10 +174,13 @@ export default class XMLHttpRequest extends EventTarget{
155 174
         detail : err
156 175
       })
157 176
     }
177
+    this._invokeOnStateChange()
158 178
   }
159 179
 
160 180
   _onDone(resp) {
181
+    console.log('XMLHttpRequest done', resp.text())
161 182
     this.statusText = '200 OK'
183
+    this.status = 200
162 184
     switch(resp.type) {
163 185
       case 'base64' :
164 186
       this.responseType = 'text'
@@ -170,6 +192,13 @@ export default class XMLHttpRequest extends EventTarget{
170 192
       this.response = resp.blob()
171 193
       break;
172 194
     }
195
+    this.readyState = 4
196
+    this._invokeOnStateChange()
197
+  }
198
+
199
+  _invokeOnStateChange() {
200
+    if(this.onreadystatechange)
201
+      this.onreadystatechange()
173 202
   }
174 203
 
175 204
 }

+ 26
- 25
test/test-firebase.js View File

@@ -50,8 +50,8 @@ describe('firebase login', (report, done) => {
50 50
     })
51 51
   firebase.auth().onAuthStateChanged((user) => {
52 52
     report(<Assert key="login status" uid="100"
53
-      expect={user !== undefined}
54
-      actual={user}/>,
53
+      expect={true}
54
+      actual={user !== null}/>,
55 55
     <Info key="user content" uid="user data">
56 56
       <Text>{JSON.stringify(user)}</Text>
57 57
     </Info>)
@@ -60,26 +60,27 @@ describe('firebase login', (report, done) => {
60 60
 })
61 61
 
62 62
 
63
-describe('upload file to firebase', (report, done) => {
64
-
65
-  try {
66
-
67
-    let storage = firebase.storage().ref()
68
-    let task = storage.child(`testdata/firebase-test-${Platform.OS}.png`).put(new Blob('hello !'), { contentType : 'text/plain' })
69
-
70
-    task.on('state_change', null, (err) => {
71
-
72
-    }, () => {
73
-      report(<Assert key="upload success"
74
-        expect={true}
75
-        actual={true}/>,
76
-      <Info key="uploaded file stat" >
77
-        <Text>{task.snapshot.totalBytes}</Text>
78
-        <Text>{JSON.stringify(task.snapshot.metadata)}</Text>
79
-      </Info>)
80
-    })
81
-  } catch(ex) {
82
-    console.log('firebase polyfill error', ex)
83
-  }
84
-
85
-})
63
+// describe('upload file to firebase', (report, done) => {
64
+//
65
+//   try {
66
+//     let storage = firebase.storage().ref()
67
+//     let task = storage
68
+//       .child(`testdata/firebase-test-${Platform.OS}.png`)
69
+//       .put(new Blob(file, 'image/png'), { contentType : 'image/png' })
70
+//
71
+//     task.on('state_change', null, (err) => {
72
+//
73
+//     }, () => {
74
+//       report(<Assert key="upload success"
75
+//         expect={true}
76
+//         actual={true}/>,
77
+//       <Info key="uploaded file stat" >
78
+//         <Text>{task.snapshot.totalBytes}</Text>
79
+//         <Text>{JSON.stringify(task.snapshot.metadata)}</Text>
80
+//       </Info>)
81
+//     })
82
+//   } catch(ex) {
83
+//     console.log('firebase polyfill error', ex)
84
+//   }
85
+//
86
+// })