Browse Source

ios http ref

dmuratshin 8 years ago
parent
commit
b1461e863e

+ 1 - 1
examples/Demo/src/test.cpp

@@ -247,4 +247,4 @@ void Test::notifyDone(Event* ev)
 {
     size_t N = size_t(ev->target->getUserData());
     _notifies[N] -= 1;
-}
+}

+ 24 - 2
oxygine/src/HttpRequestTask.cpp

@@ -21,10 +21,27 @@ namespace oxygine
     void HttpRequestTask::init() {}
     void HttpRequestTask::release() {}
 #endif
-    HttpRequestTask::HttpRequestTask() : _loaded(0), _cacheEnabled(true), _successOnAnyResponceCode(false), _continueDownload(false), _fhandle(0)
+    
+    static HttpRequestTask::responseCodeChecker _defaultCheckerAny = [](int code)
+    {
+        return true;
+    };
+    
+    
+    static HttpRequestTask::responseCodeChecker _defaultChecker200 = [](int code)
+    {
+        return code == 200 || code == 206;
+    };
+    
+    HttpRequestTask::HttpRequestTask() : _loaded(0),
+        _cacheEnabled(true),
+        _continueDownload(false),
+        _fhandle(0),
+        _responseCodeChecker(_defaultChecker200)
     {
 
     }
+    
     HttpRequestTask::~HttpRequestTask()
     {
         log::messageln("~HttpRequestTask");
@@ -63,6 +80,11 @@ namespace oxygine
         _setCacheEnabled(enabled);
     }
 
+    void HttpRequestTask::setSuccessOnAnyResponseCode(bool any)
+    {
+        _responseCodeChecker = any ? _defaultCheckerAny : _defaultChecker200;
+    }
+    
     void HttpRequestTask::addHeader(const std::string& key, const std::string& value)
     {
         OX_ASSERT(!key.empty());
@@ -147,7 +169,7 @@ namespace oxygine
 
     void HttpRequestTask::_dispatchComplete()
     {
-        if (_responseCode == 200 || _responseCode == 206 || _successOnAnyResponceCode)
+        if (_responseCodeChecker(_responseCode))
         {
             Event ev(COMPLETE);
             dispatchEvent(&ev);

+ 8 - 3
oxygine/src/HttpRequestTask.h

@@ -13,6 +13,7 @@ namespace oxygine
     public:
         static spHttpRequestTask create();
         typedef HttpRequestTask* (*createHttpRequestCallback)();
+        typedef std::function< bool(int) > responseCodeChecker;
         static void setCustomRequests(createHttpRequestCallback);
         static void init();
         static void release();
@@ -48,13 +49,16 @@ namespace oxygine
         /**swap version of getResponse if you want to modify result buffer inplace*/
         void getResponseSwap(std::vector<unsigned char>&);
         int  getResponseCode() const { return _responseCode; }
+        const responseCodeChecker& getResponseCodeChecker() const {return _responseCodeChecker;}
         void addHeader(const std::string& key, const std::string& value);
 
         void setPostData(const std::vector<unsigned char>& data);
         void setUrl(const std::string& url);
         void setFileName(const std::string& name, bool continueDownload = false);
         void setCacheEnabled(bool enabled);
-        void setSuccessOnAnyResponseCode(bool en) { _successOnAnyResponceCode = en; }
+        
+        void setResponseCodeChecker(const responseCodeChecker &f){_responseCodeChecker = f;}
+        void setSuccessOnAnyResponseCode(bool en);
 
     protected:
         void _prerun() override;
@@ -84,13 +88,14 @@ namespace oxygine
         bool _cacheEnabled;
         std::vector<unsigned char> _response;
         std::vector<unsigned char> _postData;
+        
+        responseCodeChecker _responseCodeChecker;
 
         int _responseCode;
-        bool _successOnAnyResponceCode;
 
 		bool _continueDownload;
 
         typedef std::vector< std::pair<std::string, std::string> >  headers;
         headers _headers;
     };
-}
+}

+ 3 - 1
oxygine/src/core/ios/HttpRequestCocoaTask.h

@@ -16,8 +16,10 @@ namespace oxygine
         HttpRequestCocoaTask();
         ~HttpRequestCocoaTask();
 
-        void complete_(NSData* data, bool error, int respCode);
+        void write(NSData* data);
+        void complete_(bool error);
         void progress_(int loaded, int total);
+        void gotResponse(int resp);
 
     protected:
         void _run();

+ 62 - 122
oxygine/src/core/ios/HttpRequestCocoaTask.mm

@@ -13,7 +13,7 @@ static HttpRequestTask *createTask()
     return new HttpRequestCocoaTask;
 }
 
-@interface HttpRequests:NSObject<NSURLSessionDownloadDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
+@interface HttpRequests:NSObject<NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
 {
 }
 @end
@@ -34,98 +34,63 @@ static HttpRequestTask *createTask()
     oxygine::HttpRequestCocoaTask* task = (oxygine::HttpRequestCocoaTask*)taskValue.pointerValue;
     if (remove)
         objc_removeAssociatedObjects(object);
-    if (!task)
-        int q=0;
     return task;
 }
 
-#pragma mark - NSURLSessionDownloadDelegate
+#pragma mark - NSURLSessionTaskDelegate
 
--(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
 {
-    oxygine::HttpRequestCocoaTask* task = [self getTask:downloadTask remove:false];
-    task->progress_((int) totalBytesWritten, (int) totalBytesExpectedToWrite);
-}
-
--(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
-    
-    oxygine::HttpRequestCocoaTask* task = [self getTask:downloadTask remove:true];
-    
-    NSHTTPURLResponse *resp = (NSHTTPURLResponse*)[downloadTask response];
-    
-    long code = [resp statusCode];
-    
-    
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    
-    std::string dest = oxygine::file::wfs().getFullPath(task->getFileName().c_str());
-    NSURL *destUrl = [NSURL fileURLWithPath:[NSString stringWithUTF8String:dest.c_str()]];
+    NSLog(@"Session %@ download task %@ finished downloading with error %@\n",session, task, error);
     
-    NSError *fileManagerError;
     
-    [fileManager removeItemAtURL:destUrl error:&fileManagerError];
+    oxygine::HttpRequestCocoaTask* httpRequestTask = [self getTask:task remove:true];
     
-    /*
-    if (code == 200)
+    if (error)
     {
-        [fileManager copyItemAtURL:location toURL:destUrl error:&fileManagerError];
-    
-        task->complete_(nil,  false);
+        httpRequestTask->complete_(true);
     }
     else
     {
-        task->complete_(nil, true);
-        
+        httpRequestTask->complete_(false);
     }
-    */
-
-    task->complete_(nil, false, (int)code);
 }
 
-#pragma mark - NSURLSessionTaskDelegate
 
-- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
+#pragma mark - NSURLSessionDataDelegate
+
+// Not used yet (using completion handler for data tasks)
+- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask  didReceiveData:(NSData *)data
 {
-    NSLog(@"Session %@ download task %@ finished downloading with error %@\n",session, task, error);
-    
-    
-    oxygine::HttpRequestCocoaTask* httpRequestTask = [self getTask:task remove:true];
-    
-    if (error) {
-        NSData* resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];
-        if (resumeData) {
-            NSURLSessionTask *rt = [session downloadTaskWithResumeData:resumeData];
-            [rt resume];
-            
-            NSValue *taskValue = [NSValue valueWithPointer:httpRequestTask];
-            objc_setAssociatedObject(rt, &taskKey, taskValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-        }
-        else
+    oxygine::HttpRequestCocoaTask* task = [self getTask:dataTask remove:false];
+    if (!task)
+        return;
+    task->write(data);
+}
+
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+didReceiveResponse:(NSURLResponse *)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
+{
+    if ([response isKindOfClass:[NSHTTPURLResponse class]])
+    {
+        NSHTTPURLResponse *httpResponse = ((NSHTTPURLResponse *)response);
+        int resp = (int)httpResponse.statusCode;
+        
+        oxygine::HttpRequestCocoaTask* task = [self getTask:dataTask remove:false];
+        if (task)
         {
-            httpRequestTask->complete_(/* data */ nil, /* error */ true, 0);
+            task->gotResponse(resp);
+            bool ok = task->getResponseCodeChecker()(resp);
+            completionHandler(ok ? NSURLSessionResponseAllow : NSURLSessionResponseCancel);
         }
     }
+
     
-    if (!error) {
-        // didFinishDownloadingToURL will be called in this case,
-        // which will save the file and signal completion.
-    } else {
-        
-    }
+    completionHandler(NSURLSessionResponseAllow);
 }
 
-
-#pragma mark - NSURLSessionDataDelegate
-
-// Not used yet (using completion handler for data tasks)
-//- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask  didReceiveData:(NSData *)data{
-//    oxygine::HttpRequestCocoaTask* task = [self getTask:dataTask remove:true];
-//    log::messageln("nssessiond complete %x", dataTask);
-//    //if (!task)
-//    //    return;
-//    task->complete_(data);
-//}
-
 #pragma mark -
 
 @end
@@ -204,83 +169,58 @@ namespace oxygine
         progress(loaded, total);
     }
     
-    void HttpRequestCocoaTask::complete_(NSData *data, bool error, int respCode)
+    void HttpRequestCocoaTask::write(NSData *data)
     {
-        _responseCode = respCode;
+        const void *ptr = [data bytes];
+        unsigned int len = [data length];
+        HttpRequestTask::write(ptr, len);
         
+    }
+    void HttpRequestCocoaTask::complete_(bool error)
+    {
         if (error)
             onError();
         else
-        {
-            if (data)
-            {
-                const void *ptr = [data bytes];
-                size_t len = [data length];
-                _response.assign((const char*)ptr, (const char*)ptr + len);
-            }
-            
             onComplete();
-        }
         
         releaseRef();
     }
     
+    void HttpRequestCocoaTask::gotResponse(int resp)
+    {
+        _responseCode = resp;
+        
+    }
+    
     void HttpRequestCocoaTask::_run()
     {
         _mainThreadSync = true;
         
         addRef();
+        
         NSString *urlString = [NSString stringWithUTF8String:_url.c_str()];
-        NSURL *url =[NSURL URLWithString:urlString];
+        NSURL *url = [NSURL URLWithString:urlString];
         
         NSURLSession *session = _cacheEnabled ? _getDefaultSession() : _getEphemeralSession();
         
         NSURLSessionTask *task = 0;
-        if (_fname.empty())
+        
+        NSMutableURLRequest *request = [NSMutableURLRequest	requestWithURL:url];
+        for (const auto& h:_headers)
         {
-            NSMutableURLRequest *request = [NSMutableURLRequest	requestWithURL:url];
-            if (!_postData.empty())
-            {
-                request.HTTPBody = [NSData dataWithBytes:_postData.data() length:_postData.size()];
-                request.HTTPMethod = @"POST";
-            }
+            NSString *key = [NSString stringWithUTF8String:h.first.c_str()];
+            NSString *value = [NSString stringWithUTF8String:h.second.c_str()];
             
-            task = [session dataTaskWithRequest:request
-                              completionHandler:^(NSData *data,
-                                                  NSURLResponse *response,
-                                                  NSError *error) {
-                                  // handle response
-                                  
-                                  
-                                  if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
-                                      NSHTTPURLResponse *httpResponse = ((NSHTTPURLResponse *)response);
-                                      _responseCode = (int)httpResponse.statusCode;
-                                      //if (statusCode != 200)
-                                       //   httpError = true;
-                                  }
-                                  
-                                  if (error)
-                                  {
-                                      onError();
-                                  }
-                                  else
-                                  {
-                                      if (data)
-                                      {
-                                          const void *ptr = data.bytes;
-                                          size_t len = data.length;
-                                          _response.assign((const char*)ptr, (const char*)ptr + len);
-                                      }
-                                      
-                                      onComplete();
-                                  }
-                                  releaseRef();
-                              }];
+            [request setValue:key forHTTPHeaderField:value];
         }
-        else
+        
+        if (!_postData.empty())
         {
-            task = [session downloadTaskWithURL:url];
+            request.HTTPBody = [NSData dataWithBytes:_postData.data() length:_postData.size()];
+            request.HTTPMethod = @"POST";
         }
+            
+        task = [session dataTaskWithRequest:request];
         
         NSValue *taskValue = [NSValue valueWithPointer:this];
         objc_setAssociatedObject(task, &taskKey, taskValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);