diff --git a/src/android/com/synconset/cordovahttp/CordovaHttp.java b/src/android/com/synconset/cordovahttp/CordovaHttp.java index c1a048a..1e0bb0b 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttp.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttp.java @@ -8,6 +8,11 @@ import org.apache.cordova.CallbackContext; import org.json.JSONException; import org.json.JSONObject; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; + +import javax.net.ssl.SSLHandshakeException; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,6 +22,7 @@ import java.util.Iterator; import android.text.TextUtils; import com.github.kevinsawicki.http.HttpRequest; +import com.github.kevinsawicki.http.HttpRequest.HttpRequestException; abstract class CordovaHttp { protected static final String TAG = "CordovaHTTP"; @@ -120,6 +126,7 @@ abstract class CordovaHttp { if (sslPinning.get()) { request.pinToCerts(); } + return request; } @@ -127,9 +134,21 @@ abstract class CordovaHttp { if (disableRedirect.get()) { request.followRedirects(false); } + return request; } + protected HttpRequest setupDataSerializer(HttpRequest request) throws JSONException, Exception { + if (new String("json").equals(this.getSerializerName())) { + request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8); + request.send(this.getParamsObject().toString()); + } else { + request.form(this.getParamsMap()); + } + + return request; + } + protected void respondWithError(int status, String msg) { try { JSONObject response = new JSONObject(); @@ -182,4 +201,47 @@ abstract class CordovaHttp { } return map; } + + protected void prepareRequest(HttpRequest request) throws HttpRequestException, JSONException { + this.setupRedirect(request); + this.setupSecurity(request); + request.readTimeout(this.getRequestTimeout()); + request.acceptCharset(CHARSET); + request.headers(this.getHeadersMap()); + request.uncompress(true); + } + + protected void returnResponseObject(HttpRequest request) throws HttpRequestException { + try { + JSONObject response = new JSONObject(); + int code = request.code(); + String body = request.body(CHARSET); + + response.put("status", code); + response.put("url", request.url().toString()); + this.addResponseHeaders(request, response); + + if (code >= 200 && code < 300) { + response.put("data", body); + this.getCallbackContext().success(response); + } else { + response.put("error", body); + this.getCallbackContext().error(response); + } + } catch(JSONException e) { + this.respondWithError("There was an error generating the response"); + } + } + + protected void handleHttpRequestException(HttpRequestException e) { + if (e.getCause() instanceof UnknownHostException) { + this.respondWithError(0, "The host could not be resolved"); + } else if (e.getCause() instanceof SocketTimeoutException) { + this.respondWithError(1, "The request timed out"); + } else if (e.getCause() instanceof SSLHandshakeException) { + this.respondWithError("SSL handshake failed"); + } else { + this.respondWithError("There was an error with the request"); + } + } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpDownload.java b/src/android/com/synconset/cordovahttp/CordovaHttpDownload.java index aa655c7..07aa53f 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpDownload.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpDownload.java @@ -33,17 +33,15 @@ class CordovaHttpDownload extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.get(this.getUrlString(), this.getParamsMap(), true); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - int code = request.code(); + this.prepareRequest(request); JSONObject response = new JSONObject(); - this.addResponseHeaders(request, response); + int code = request.code(); + response.put("status", code); + response.put("url", request.url().toString()); + this.addResponseHeaders(request, response); + if (code >= 200 && code < 300) { URI uri = new URI(filePath); File file = new File(uri); @@ -60,17 +58,9 @@ class CordovaHttpDownload extends CordovaHttp implements Runnable { } catch (JSONException e) { this.respondWithError("There was an error generating the response"); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpGet.java b/src/android/com/synconset/cordovahttp/CordovaHttpGet.java index a3de313..a522866 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpGet.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpGet.java @@ -26,41 +26,12 @@ class CordovaHttpGet extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.get(this.getUrlString(), this.getParamsMap(), false); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - - int code = request.code(); - String body = request.body(CHARSET); - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - response.put("data", body); - this.getCallbackContext().success(response); - } else { - response.put("error", body); - this.getCallbackContext().error(response); - } - } catch (JSONException e) { - this.respondWithError("There was an error generating the response"); + this.prepareRequest(request); + this.returnResponseObject(request); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpHead.java b/src/android/com/synconset/cordovahttp/CordovaHttpHead.java index 9423046..bd199ed 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpHead.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpHead.java @@ -25,41 +25,12 @@ class CordovaHttpHead extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.head(this.getUrlString(), this.getParamsMap(), true); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - - int code = request.code(); - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - // no 'body' to return for HEAD request - this.getCallbackContext().success(response); - } else { - String body = request.body(CHARSET); - response.put("error", body); - this.getCallbackContext().error(response); - } - } catch (JSONException e) { - this.respondWithError("There was an error generating the response"); + this.prepareRequest(request); + this.returnResponseObject(request); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java b/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java index 54894ba..5696505 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java @@ -25,48 +25,13 @@ class CordovaHttpPatch extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.patch(this.getUrlString()); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - - if (new String("json").equals(this.getSerializerName())) { - request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8); - request.send(this.getParamsObject().toString()); - } else { - request.form(this.getParamsMap()); - } - - int code = request.code(); - String body = request.body(CHARSET); - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - response.put("data", body); - this.getCallbackContext().success(response); - } else { - response.put("error", body); - this.getCallbackContext().error(response); - } - } catch (JSONException e) { - this.respondWithError("There was an error generating the response"); + this.prepareRequest(request); + this.setupDataSerializer(request); + this.returnResponseObject(request); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPost.java b/src/android/com/synconset/cordovahttp/CordovaHttpPost.java index 2ebe50e..ac3a3da 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpPost.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpPost.java @@ -25,48 +25,13 @@ class CordovaHttpPost extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.post(this.getUrlString()); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - - if (new String("json").equals(this.getSerializerName())) { - request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8); - request.send(this.getParamsObject().toString()); - } else { - request.form(this.getParamsMap()); - } - - int code = request.code(); - String body = request.body(CHARSET); - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - response.put("data", body); - this.getCallbackContext().success(response); - } else { - response.put("error", body); - this.getCallbackContext().error(response); - } - } catch (JSONException e) { - this.respondWithError("There was an error generating the response"); + this.prepareRequest(request); + this.setupDataSerializer(request); + this.returnResponseObject(request); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPut.java b/src/android/com/synconset/cordovahttp/CordovaHttpPut.java index 4b52630..2ca0aca 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpPut.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpPut.java @@ -25,48 +25,13 @@ class CordovaHttpPut extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.put(this.getUrlString()); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); - - if (new String("json").equals(this.getSerializerName())) { - request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8); - request.send(this.getParamsObject().toString()); - } else { - request.form(this.getParamsMap()); - } - - int code = request.code(); - String body = request.body(CHARSET); - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - response.put("data", body); - this.getCallbackContext().success(response); - } else { - response.put("error", body); - this.getCallbackContext().error(response); - } - } catch (JSONException e) { - this.respondWithError("There was an error generating the response"); + this.prepareRequest(request); + this.setupDataSerializer(request); + this.returnResponseObject(request); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpUpload.java b/src/android/com/synconset/cordovahttp/CordovaHttpUpload.java index 4f5e8fc..613430e 100644 --- a/src/android/com/synconset/cordovahttp/CordovaHttpUpload.java +++ b/src/android/com/synconset/cordovahttp/CordovaHttpUpload.java @@ -41,12 +41,7 @@ class CordovaHttpUpload extends CordovaHttp implements Runnable { try { HttpRequest request = HttpRequest.post(this.getUrlString()); - request.readTimeout(this.getRequestTimeout()); - this.setupRedirect(request); - this.setupSecurity(request); - request.acceptCharset(CHARSET); - request.headers(this.getHeadersMap()); - request.uncompress(true); + this.prepareRequest(request); URI uri = new URI(filePath); @@ -78,37 +73,15 @@ class CordovaHttpUpload extends CordovaHttp implements Runnable { } } - int code = request.code(); - String body = request.body(CHARSET); - - JSONObject response = new JSONObject(); - - this.addResponseHeaders(request, response); - response.put("status", code); - - if (code >= 200 && code < 300) { - response.put("data", body); - this.getCallbackContext().success(response); - } else { - response.put("error", body); - this.getCallbackContext().error(response); - } + this.returnResponseObject(request); } catch (URISyntaxException e) { this.respondWithError("There was an error loading the file"); } catch (JSONException e) { this.respondWithError("There was an error generating the response"); } catch (HttpRequestException e) { - if (e.getCause() instanceof UnknownHostException) { - this.respondWithError(0, "The host could not be resolved"); - } else if (e.getCause() instanceof SocketTimeoutException) { - this.respondWithError(1, "The request timed out"); - } else if (e.getCause() instanceof SSLHandshakeException) { - this.respondWithError("SSL handshake failed"); - } else { - this.respondWithError("There was an error with the request"); - } + this.handleHttpRequestException(e); } catch (Exception e) { - this.respondWithError(-1, e.getMessage()); + this.respondWithError(e.getMessage()); } } } diff --git a/src/ios/CordovaHttpPlugin.m b/src/ios/CordovaHttpPlugin.m index c5140d2..91449db 100644 --- a/src/ios/CordovaHttpPlugin.m +++ b/src/ios/CordovaHttpPlugin.m @@ -51,6 +51,7 @@ - (void)handleSuccess:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response andData:(id)data { if (response != nil) { + [dictionary setValue:response.URL.absoluteString forKey:@"url"]; [dictionary setObject:[NSNumber numberWithInt:response.statusCode] forKey:@"status"]; [dictionary setObject:[self copyHeaderFields:response.allHeaderFields] forKey:@"headers"]; } @@ -62,6 +63,7 @@ - (void)handleError:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response error:(NSError*)error { if (response != nil) { + [dictionary setValue:response.URL.absoluteString forKey:@"url"]; [dictionary setObject:[NSNumber numberWithInt:response.statusCode] forKey:@"status"]; [dictionary setObject:[self copyHeaderFields:response.allHeaderFields] forKey:@"headers"]; [dictionary setObject:[[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding] forKey:@"error"]; diff --git a/test/app-test-definitions.js b/test/app-test-definitions.js index d1ccf89..82dc897 100644 --- a/test/app-test-definitions.js +++ b/test/app-test-definitions.js @@ -132,7 +132,7 @@ const tests = [ JSON.parse(result.data.data).json.should.eql({ test: 'testString' }); } },{ - description: 'should send JSON array correctly (POST)', + description: 'should send JSON array correctly (POST) #26', expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...', before: helpers.setJsonSerializer, func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', [ 1, 2, 3 ], {}, resolve, reject); }, @@ -141,7 +141,7 @@ const tests = [ JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]); } },{ - description: 'should send JSON array correctly (PUT)', + description: 'should send JSON array correctly (PUT) #26', expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...', before: helpers.setJsonSerializer, func: function(resolve, reject) { cordova.plugin.http.put('http://httpbin.org/anything', [ 1, 2, 3 ], {}, resolve, reject); }, @@ -150,7 +150,7 @@ const tests = [ JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]); } },{ - description: 'should send JSON array correctly (PATCH)', + description: 'should send JSON array correctly (PATCH) #26', expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...', before: helpers.setJsonSerializer, func: function(resolve, reject) { cordova.plugin.http.patch('http://httpbin.org/anything', [ 1, 2, 3 ], {}, resolve, reject); }, @@ -158,6 +158,14 @@ const tests = [ result.type.should.be.equal('resolved'); JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]); } + },{ + description: 'should resolve correct URL after redirect (GET) #33', + expected: 'resolved: {"status": 200, url: "http://httpbin.org/anything", ...', + func: function(resolve, reject) { cordova.plugin.http.get('http://httpbin.org/redirect-to?url=http://httpbin.org/anything', {}, {}, resolve, reject); }, + validationFunc: function(driver, result) { + result.type.should.be.equal('resolved'); + result.data.url.should.be.equal('http://httpbin.org/anything'); + } } ]; diff --git a/test/js-mocha-specs.js b/test/js-mocha-specs.js index 5e7d6d6..f232e39 100644 --- a/test/js-mocha-specs.js +++ b/test/js-mocha-specs.js @@ -29,17 +29,17 @@ describe('Advanced HTTP www interface', function() { http.headers['*'].myKey.should.equal('myValue'); }); - it('sets global headers correctly with three args (new interface)', () => { + it('sets global headers correctly with three args (new interface) #24', () => { http.setHeader('*', 'myKey', 'myValue'); http.headers['*'].myKey.should.equal('myValue'); }); - it('sets host headers correctly', () => { + it('sets host headers correctly #24', () => { http.setHeader('www.google.de', 'myKey', 'myValue'); http.headers['www.google.de'].myKey.should.equal('myValue'); }); - it('resolves global headers correctly', () => { + it('resolves global headers correctly #24', () => { mock(`${PLUGIN_ID}.cookie-handler`, { getCookieString: () => 'fakeCookieString' }); @@ -58,7 +58,7 @@ describe('Advanced HTTP www interface', function() { http.get('url', {}, {}, noop, noop); }); - it('resolves host headers correctly (set without port number)', () => { + it('resolves host headers correctly (set without port number) #37', () => { mock(`${PLUGIN_ID}.cookie-handler`, { getCookieString: () => 'fakeCookieString' }); @@ -77,7 +77,7 @@ describe('Advanced HTTP www interface', function() { http.get('https://www.google.de/?gws_rd=ssl', {}, {}, noop, noop); }); - it('resolves host headers correctly (set with port number)', () => { + it('resolves host headers correctly (set with port number) #37', () => { mock(`${PLUGIN_ID}.cookie-handler`, { getCookieString: () => 'fakeCookieString' }); @@ -114,7 +114,7 @@ describe('Advanced HTTP www interface', function() { http.get('https://www.google.de/?gws_rd=ssl', {}, { myKey: 'myValue' }, noop, noop); }); - it('sets basic authentication header correctly', () => { + it('sets basic authentication header correctly #36', () => { http.useBasicAuth('name', 'pass'); http.headers['*'].Authorization.should.equal('Basic bmFtZTpwYXNz'); });