Compare commits

..
30 Commits
Author SHA1 Message Date
Sefa Ilkimen c7820c8185 release v1.9.1 2018-01-04 16:34:21 +01:00
Sefa Ilkimen f6a15190f3 add another cookie spec to validate #59 2018-01-04 13:17:52 +01:00
Sefa Ilkimen 419283c5dd add another spec for cookie handling 2018-01-04 04:10:30 +01:00
Sefa Ilkimen 7a8f9a0dba add a spec for cookie handling 2018-01-04 03:53:39 +01:00
Sefa Ilkimen 64731a3794 fix #58: white-list of allowed content-types should be removed for iOS 2018-01-04 02:05:55 +01:00
Sefa Ilkimen 73097b9db9 fix: bug fix #54 causes a bug on Android (success and failure handler are called both) 2018-01-04 01:23:49 +01:00
Sefa Ilkimen a9c3be124e fixed #54: Requests are not responding on iOS with non-string values in header object 2018-01-04 00:40:40 +01:00
Sefa Ilkimen d67e80dfe0 fix #45: does not encode arrays correctly as HTTP GET parameter on Android 2017-11-26 03:42:22 +01:00
Sefa Ilkimen 55ba423d2f update readme to include tough-cookie 2017-11-24 19:48:39 +01:00
Sefa Ilkimen 7f34201e8d release v1.9.0 2017-11-24 19:26:03 +01:00
Sefa Ilkimen 01c43c4e29 throw an error when "setHeader" is used to add a custom cookie header 2017-11-24 19:14:14 +01:00
Sefa Ilkimen d34196ff4e feature #46: support adding custom cookies 2017-11-24 18:47:00 +01:00
Sefa Ilkimen 1957cf4ef7 update change log 2017-11-24 17:46:44 +01:00
Sefa IlkimenandGitHub 681c384b3e feature #43: add support for Content-Type "application/javascript"
Add support for Content-Type application/javascript
2017-11-23 01:03:33 +01:00
Sefa Ilkimen 9d6406277c - feature #44: expose "getCookieString" method
- update version number
2017-11-16 23:22:29 +01:00
Sefa Ilkimen b9bc1b0054 - update cordova (dev dependency)
- pin version of cordova file plugin dependency (v4.3.3)
2017-11-13 17:47:35 +01:00
Sefa Ilkimen d17f44b641 improve CI build error handling (do not continue when one of the commands fail) 2017-11-08 12:17:27 +01:00
Sefa Ilkimen 11515a8400 add tests for sending url encoded data 2017-11-08 11:57:33 +01:00
Sefa Ilkimen 937296b371 release v1.8.1 2017-11-08 11:17:53 +01:00
Thomas Opiolka b60086df0d Add support for Content-Type application/javascript 2017-11-08 11:16:42 +01:00
Sefa Ilkimen a48a91dd14 add OS identifier for saucelabs tests 2017-11-08 11:15:32 +01:00
Sefa Ilkimen e8a72a53cc split CI build into two jobs 2017-11-08 10:29:59 +01:00
Sefa Ilkimen efbdc21221 fix: ANDROID_HOME path for CI build 2017-11-07 18:30:42 +01:00
Sefa Ilkimen 06d7d859e7 update change log 2017-11-07 14:53:37 +01:00
Sefa Ilkimen 239b82c08e enable saucelabs testing for android platform 2017-11-07 14:52:11 +01:00
Sefa Ilkimen e987652d97 fix #40: generic error codes are different on Android and iOS 2017-11-07 13:31:38 +01:00
Sefa Ilkimen 068b25b6f9 - fix #27: "uploadFile" method doesn't return data object on iOS
- update version number
2017-11-03 15:51:19 +01:00
Sefa Ilkimen 8c55572eb8 implement test for "downloadFile" method 2017-11-02 17:01:35 +01:00
Sefa Ilkimen 48afeefbc3 - update version number
- update change log
2017-11-02 15:45:37 +01:00
Sefa Ilkimen 292d726b20 - feature #33: response object contains response url
- annotate tests with issue numbers
- refactor android source code
2017-11-02 14:59:53 +01:00
27 changed files with 584 additions and 317 deletions
+2 -5
View File
@@ -1,16 +1,13 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 4
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
@@ -19,4 +16,4 @@ trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
trim_trailing_whitespace = false
+2
View File
@@ -3,3 +3,5 @@ tags
.zedstate
npm-debug.log
/temp
/android-sdk-macosx.zip
/android-sdk-macosx/**
+14 -15
View File
@@ -4,6 +4,10 @@ language: objective-c
os: osx
osx_image: xcode9.1
env:
- TARGET_PLATFORM=android
- TARGET_PLATFORM=ios
cache:
directories:
- node_modules
@@ -15,27 +19,22 @@ addons:
before_install:
- export LANG=en_US.UTF-8
- brew update
install:
- npm install
- brew install gradle
- wget http://dl.google.com/android/android-sdk_r24.4-macosx.zip
- tar -xvf android-sdk_r24.4-macosx.zip
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter platform-tools
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter build-tools-25.0.0
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter android-25
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-android-support
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-android-m2repository
- echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-google-m2repository
- export ANDROID_HOME=./android-sdk-macosx
- export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/23.0.2
- if [ $TARGET_PLATFORM = "android" ]; then
brew update &&
brew install gradle &&
scripts/setup-android-sdk.sh &&
export ANDROID_HOME=$(pwd)/android-sdk-macosx &&
export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/23.0.2;
fi
script:
- travis_wait scripts/build-test-app.sh
- scripts/upload-artifact.sh
- npm run testjs
- scripts/test-app.sh --ios --emulator
- travis_wait scripts/build-test-app.sh --$TARGET_PLATFORM --emulator &&
scripts/upload-artifact.sh --$TARGET_PLATFORM &&
scripts/test-app.sh --$TARGET_PLATFORM --emulator;
after_success:
+21
View File
@@ -1,5 +1,26 @@
# Changelog
## 1.9.1
- Fixed #45: does not encode arrays correctly as HTTP GET parameter on Android
- Fixed #54: requests are not responding on iOS with non-string values in header object
- Fixed #58: white-list of allowed content-types should be removed for iOS
## v1.9.0
- Feature #44: "getCookieString" method is exposed
- Feature #43: added support for content type "application/javascript" on iOS (thanks wh33ler)
- Feature #46: "setCookie" allows adding custom cookies
## v1.8.1
- Fixed #27: "uploadFile" method doesn't return data object on iOS (thanks Faisalali23 and laiyinjie)
- Fixed #40: generic error codes are different on Android and iOS
## v1.8.0
- Feature #33: response object contains response url
## v1.7.1
- Fixed #36: setting basic authentication not working correctly (thanks jkfb)
+21 -6
View File
@@ -64,7 +64,7 @@ cordova.plugin.http.useBasicAuth('user', 'password');
```
### setHeader
Set a header for all future requests to a specified host. Takes a hostname, a header and a value.
Set a header for all future requests to a specified host. Takes a hostname, a header and a value (must be a string value).
```js
cordova.plugin.http.setHeader('Hostname', 'Header', 'Value');
@@ -114,6 +114,20 @@ Set how long to wait for a request to respond, in seconds.
cordova.plugin.http.setRequestTimeout(5.0);
```
### getCookieString
Returns saved cookies (as string) matching given URL.
```js
cordova.plugin.http.getCookieString(url);
```
### setCookie
Add a custom cookie. Takes a URL, a cookie string and an options object. See [ToughCookie documentation](https://github.com/salesforce/tough-cookie#setcookiecookieorstring-currenturl-options-cberrcookie) for allowed options.
```js
cordova.plugin.http.setCookie(url, cookie, options);
```
### clearCookies
Clear the cookie store.
@@ -157,7 +171,7 @@ This function was removed in v1.6.2. Domain name validation is disabled automati
Remove all cookies associated with a given URL.
```js
cordova.plugin.http.removeCookies(url);
cordova.plugin.http.removeCookies(url, callback);
```
### post<a name="post"></a>
@@ -279,12 +293,13 @@ cordova.plugin.http.downloadFile("https://google.com/", {
## Libraries
This plugin utilizes some awesome open source networking libraries. These are both MIT licensed:
This plugin utilizes some awesome open source libraries:
- iOS - [AFNetworking](https://github.com/AFNetworking/AFNetworking)
- Android - [http-request](https://github.com/kevinsawicki/http-request)
- iOS - [AFNetworking](https://github.com/AFNetworking/AFNetworking) (MIT licensed)
- Android - [http-request](https://github.com/kevinsawicki/http-request) (MIT licensed)
- Cookie handling - [tough-cookie](https://github.com/salesforce/tough-cookie) (BSD-3-Clause licensed)
We made a few modifications to both of them.
We made a few modifications to the networking libraries.
## Contribute & Develop
+5 -3
View File
@@ -1,9 +1,11 @@
{
"name": "cordova-plugin-advanced-http",
"version": "1.7.1",
"version": "1.9.1",
"description": "Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning",
"scripts": {
"testapp": "./scripts/build-test-app.sh && ./scripts/test-app.sh --ios --emulator",
"testandroid": "./scripts/build-test-app.sh --android --emulator && ./scripts/test-app.sh --android --emulator",
"testios": "./scripts/build-test-app.sh --ios --emulator && ./scripts/test-app.sh --ios --emulator",
"testapp": "npm run testandroid && npm run testios",
"testjs": "mocha ./test/js-mocha-specs.js",
"test": "npm run testjs && npm run testapp",
"release": "npm run test && ./scripts/release.sh"
@@ -55,7 +57,7 @@
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"colors": "1.1.2",
"cordova": "7.0.1",
"cordova": "7.1.0",
"mocha": "4.0.0",
"mock-require": "2.0.2",
"mz": "2.7.0",
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-advanced-http" version="1.7.1">
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-advanced-http" version="1.9.1">
<name>Advanced HTTP plugin</name>
<description>
Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
curl http://dl.google.com/android/android-sdk_r24.4-macosx.zip -o android-sdk-macosx.zip
tar -xvf android-sdk-macosx.zip
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter platform-tools
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter build-tools-25.0.0
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter android-25
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-android-support
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-android-m2repository
echo y | ./android-sdk-macosx/tools/android update sdk --no-ui --all --filter extra-google-m2repository
+18 -9
View File
@@ -1,16 +1,25 @@
#!/usr/bin/env bash
set -e
PLATFORM=$([[ "${@#--android}" = "$@" ]] && echo "ios" || echo "android")
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
TEMP=$ROOT/temp
rm -rf $TEMP/HttpDemo.app.zip
pushd $TEMP/platforms/ios/build/emulator
zip -r $TEMP/HttpDemo.app.zip ./HttpDemo.app
popd
if [ $PLATFORM = "android" ]; then
curl -u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
-X POST \
-H "Content-Type: application/octet-stream" \
https://saucelabs.com/rest/v1/storage/$SAUCE_USERNAME/HttpDemo.apk?overwrite=true \
--data-binary @$TEMP/platforms/android/build/outputs/apk/android-debug.apk
else
rm -rf $TEMP/HttpDemo.app.zip
pushd $TEMP/platforms/ios/build/emulator
zip -r $TEMP/HttpDemo.app.zip ./HttpDemo.app
popd
curl -u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
-X POST \
-H "Content-Type: application/octet-stream" \
https://saucelabs.com/rest/v1/storage/$SAUCE_USERNAME/HttpDemo.app.zip?overwrite=true \
--data-binary @$TEMP/HttpDemo.app.zip
curl -u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
-X POST \
-H "Content-Type: application/octet-stream" \
https://saucelabs.com/rest/v1/storage/$SAUCE_USERNAME/HttpDemo.app.zip?overwrite=true \
--data-binary @$TEMP/HttpDemo.app.zip
fi
@@ -6,8 +6,15 @@ package com.synconset.cordovahttp;
import org.apache.cordova.CallbackContext;
import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import javax.net.ssl.SSLHandshakeException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -17,6 +24,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 +128,7 @@ abstract class CordovaHttp {
if (sslPinning.get()) {
request.pinToCerts();
}
return request;
}
@@ -127,9 +136,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();
@@ -142,7 +163,7 @@ abstract class CordovaHttp {
}
protected void respondWithError(String msg) {
this.respondWithError(500, msg);
this.respondWithError(-1, msg);
}
protected void addResponseHeaders(HttpRequest request, JSONObject response) throws JSONException {
@@ -172,14 +193,72 @@ abstract class CordovaHttp {
return map;
}
protected ArrayList<Object> getListFromJSONArray(JSONArray array) throws JSONException {
ArrayList<Object> list = new ArrayList<Object>();
for (int i = 0; i < array.length(); i++) {
list.add(array.get(i));
}
return list;
}
protected HashMap<String, Object> getMapFromJSONObject(JSONObject object) throws JSONException {
HashMap<String, Object> map = new HashMap<String, Object>();
Iterator<?> i = object.keys();
while(i.hasNext()) {
String key = (String)i.next();
map.put(key, object.get(key));
Object value = object.get(key);
if (value instanceof JSONArray) {
map.put(key, getListFromJSONArray((JSONArray)value));
} else {
map.put(key, object.get(key));
}
}
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: " + e.getMessage());
}
}
}
@@ -57,7 +57,7 @@ class CordovaHttpDelete extends CordovaHttp implements Runnable {
} else if (e.getCause() instanceof SSLHandshakeException) {
this.respondWithError("SSL handshake failed");
} else {
this.respondWithError("There was an error with the request");
this.respondWithError("There was an error with the request: " + e.getMessage());
}
} catch (Exception e) {
this.respondWithError(-1, e.getMessage());
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
+3 -1
View File
@@ -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"];
@@ -364,7 +366,7 @@
}
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+2 -1
View File
@@ -19,11 +19,12 @@ static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger co
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"text/html", @"text/json", @"application/hal+json", @"application/json", @"text/xml", @"application/xml", @"text/css", nil];
self.acceptableContentTypes = nil;
return self;
}
+9 -6
View File
@@ -8,18 +8,21 @@ const testDefinitions = require('../app-test-definitions');
const pkgjson = require('../../package.json');
describe('Advanced HTTP', function() {
const isDevice = process.argv.includes('--device');
const isAndroid = process.argv.includes('--android');
const targetInfo = { isDevice, isAndroid };
let driver = null;
let allPassed = true;
this.timeout(900000);
const getCaps = appName => {
const isDevice = process.argv.includes('--device');
const isAndroid = process.argv.includes('--android');
const desiredCaps = caps[(isAndroid ? 'android' : 'ios') + (isDevice ? 'Device' : 'Emulator')];
const desiredApp = apps[(isAndroid ? 'android' : 'ios') + appName];
const desiredOs = isAndroid ? 'android' : 'ios';
const desiredCaps = caps[desiredOs + (isDevice ? 'Device' : 'Emulator')];
const desiredApp = apps[desiredOs + appName];
desiredCaps.name = pkgjson.name;
desiredCaps.name = pkgjson.name + ` (${desiredOs})`;
desiredCaps.app = desiredApp;
return desiredCaps;
@@ -57,7 +60,7 @@ describe('Advanced HTTP', function() {
const validateResult = testDefinition => driver
.safeExecute('app.lastResult')
.then(result => testDefinition.validationFunc(driver, result));
.then(result => testDefinition.validationFunc(driver, result, targetInfo));
const clickNext = () => driver
.elementById('nextBtn')
+1
View File
@@ -24,4 +24,5 @@
</platform>
<engine name="android" spec="6.2.3" />
<engine name="ios" spec="4.4.0" />
<plugin name="cordova-plugin-file" spec="4.3.3" />
</widget>
+16 -1
View File
@@ -33,6 +33,16 @@ const app = {
};
},
throw: function(error) {
document.getElementById('statusInput').value = 'finished';
app.printResult('result - throwed', error.message);
app.lastResult = {
type: 'throwed',
message: error.message
};
},
getResult: function(cb) {
cb(app.lastResult);
},
@@ -46,7 +56,12 @@ const app = {
document.getElementById('expectedTextarea').value = expectedText;
document.getElementById('resultTextarea').value = '';
document.getElementById('descriptionLbl').innerText = titleText;
testDefinition.func(app.resolve, app.reject);
try {
testDefinition.func(app.resolve, app.reject);
} catch (error) {
app.throw(error);
}
},
onBeforeTest: function(testIndex, cb) {
+244 -20
View File
@@ -1,12 +1,37 @@
const hooks = {
onBeforeEachTest: function(done) {
cordova.plugin.http.clearCookies();
cordova.plugin.http.acceptAllCerts(false, done, done);
}
};
const helpers = {
acceptAllCerts: function(done) { cordova.plugin.http.acceptAllCerts(true, done, done); },
setJsonSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('json')); }
setJsonSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('json')); },
setUrlEncodedSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('urlencoded')); },
getWithXhr: function(done, url) {
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function() {
done(this.responseText);
});
xhr.open('GET', url);
xhr.send();
},
writeToFile: function (done, fileName, content) {
window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function (directoryEntry) {
directoryEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
var blob = new Blob([ content ], { type: 'text/plain' });
fileWriter.onwriteend = done;
fileWriter.onerror = done;
fileWriter.write(blob);
}, done);
}, done);
}, done);
}
};
const tests = [
@@ -14,41 +39,41 @@ const tests = [
description: 'should reject self signed cert (GET)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
func: function(resolve, reject) { cordova.plugin.http.get('https://self-signed.badssl.com/', {}, {}, resolve, reject); },
validationFunc: function(driver, result) {
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error:'cancelled' });
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
}
},{
description: 'should reject self signed cert (PUT)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
func: function(resolve, reject) { cordova.plugin.http.put('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error:'cancelled' });
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
}
},{
description: 'should reject self signed cert (POST)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
func: function(resolve, reject) { cordova.plugin.http.post('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error:'cancelled' });
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
}
},{
description: 'should reject self signed cert (PATCH)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
func: function(resolve, reject) { cordova.plugin.http.patch('https://self-signed.badssl.com/', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error:'cancelled' });
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
}
},{
description: 'should reject self signed cert (DELETE)',
expected: 'rejected: {"status":-1,"error":"cancelled"}',
func: function(resolve, reject) { cordova.plugin.http.delete('https://self-signed.badssl.com/', {}, {}, resolve, reject); },
validationFunc: function(driver, result) {
validationFunc: function(driver, result, targetInfo) {
result.type.should.be.equal('rejected');
result.data.should.be.eql({ status: -1, error:'cancelled' });
result.data.should.be.eql({ status: -1, error: targetInfo.isAndroid ? 'SSL handshake failed' : 'cancelled' });
}
},{
description: 'should accept bad cert (GET)',
@@ -106,7 +131,7 @@ const tests = [
}
},{
description: 'should send JSON object correctly (POST)',
expected: 'resolved: {"status": 200, data: "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
expected: 'resolved: {"status": 200, "data": "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setJsonSerializer,
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
@@ -115,7 +140,7 @@ const tests = [
}
},{
description: 'should send JSON object correctly (PUT)',
expected: 'resolved: {"status": 200, data: "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
expected: 'resolved: {"status": 200, "data": "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setJsonSerializer,
func: function(resolve, reject) { cordova.plugin.http.put('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
@@ -124,7 +149,7 @@ const tests = [
}
},{
description: 'should send JSON object correctly (PATCH)',
expected: 'resolved: {"status": 200, data: "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
expected: 'resolved: {"status": 200, "data": "{\\"json\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setJsonSerializer,
func: function(resolve, reject) { cordova.plugin.http.patch('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
@@ -132,8 +157,8 @@ const tests = [
JSON.parse(result.data.data).json.should.eql({ test: 'testString' });
}
},{
description: 'should send JSON array correctly (POST)',
expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...',
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); },
validationFunc: function(driver, result) {
@@ -141,8 +166,8 @@ const tests = [
JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]);
}
},{
description: 'should send JSON array correctly (PUT)',
expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...',
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); },
validationFunc: function(driver, result) {
@@ -150,14 +175,213 @@ const tests = [
JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]);
}
},{
description: 'should send JSON array correctly (PATCH)',
expected: 'resolved: {"status": 200, data: "[ 1, 2, 3 ]\" ...',
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); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.data.should.be.a('string');
JSON.parse(result.data.data).json.should.eql([ 1, 2, 3 ]);
}
},{
description: 'should send url encoded data correctly (POST) #41',
expected: 'resolved: {"status": 200, "data": "{\\"form\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setUrlEncodedSerializer,
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
JSON.parse(result.data.data).form.should.eql({ test: 'testString' });
}
},{
description: 'should send url encoded data correctly (PUT)',
expected: 'resolved: {"status": 200, "data": "{\\"form\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setUrlEncodedSerializer,
func: function(resolve, reject) { cordova.plugin.http.put('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
JSON.parse(result.data.data).form.should.eql({ test: 'testString' });
}
},{
description: 'should send url encoded data correctly (PATCH)',
expected: 'resolved: {"status": 200, "data": "{\\"form\\":\\"test\\": \\"testString\\"}\" ...',
before: helpers.setUrlEncodedSerializer,
func: function(resolve, reject) { cordova.plugin.http.patch('http://httpbin.org/anything', { test: 'testString' }, {}, resolve, reject); },
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
JSON.parse(result.data.data).form.should.eql({ test: 'testString' });
}
},{
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');
}
},{
description: 'should download a file from given URL to given path in local filesystem',
expected: 'resolved: {"content": "<?xml version=\'1.0\' encoding=\'us-ascii\'?>\\n\\n<!-- A SAMPLE set of slides -->" ...',
func: function(resolve, reject) {
var sourceUrl = 'http://httpbin.org/xml';
var targetPath = cordova.file.cacheDirectory + 'test.xml';
cordova.plugin.http.downloadFile(sourceUrl, {}, {}, targetPath, function(entry) {
helpers.getWithXhr(function(content) {
resolve({
sourceUrl: sourceUrl,
targetPath: targetPath,
fullPath: entry.fullPath,
name: entry.name,
content: content
});
}, targetPath);
}, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.name.should.be.equal('test.xml');
result.data.content.should.be.equal("<?xml version='1.0' encoding='us-ascii'?>\n\n<!-- A SAMPLE set of slides -->\n\n<slideshow \n title=\"Sample Slide Show\"\n date=\"Date of publication\"\n author=\"Yours Truly\"\n >\n\n <!-- TITLE SLIDE -->\n <slide type=\"all\">\n <title>Wake up to WonderWidgets!</title>\n </slide>\n\n <!-- OVERVIEW -->\n <slide type=\"all\">\n <title>Overview</title>\n <item>Why <em>WonderWidgets</em> are great</item>\n <item/>\n <item>Who <em>buys</em> WonderWidgets</item>\n </slide>\n\n</slideshow>");
}
},{
description: 'should upload a file from given path in local filesystem to given URL #27',
expected: 'resolved: {"status": 200, "data": "files": {"test-file.txt": "I am a dummy file. I am used ...',
func: function(resolve, reject) {
var fileName = 'test-file.txt';
var fileContent = 'I am a dummy file. I am used for testing purposes!';
var sourcePath = cordova.file.cacheDirectory + fileName;
var targetUrl = 'http://httpbin.org/post';
helpers.writeToFile(function() {
cordova.plugin.http.uploadFile(targetUrl, {}, {}, sourcePath, fileName, resolve, reject);
}, fileName, fileContent);
},
validationFunc: function(driver, result) {
var fileName = 'test-file.txt';
var fileContent = 'I am a dummy file. I am used for testing purposes!';
result.type.should.be.equal('resolved');
result.data.data.should.be.a('string');
JSON
.parse(result.data.data)
.files[fileName]
.should.be.equal(fileContent);
}
},{
description: 'should encode HTTP array params correctly (GET) #45',
expected: 'resolved: {"status": 200, "data": "{\\"url\\":\\"http://httpbin.org/get?myArray[]=val1&myArray[]=val2&myArray[]=val3\\"}\" ...',
func: function(resolve, reject) {
cordova.plugin.http.get('http://httpbin.org/get', { myArray: [ 'val1', 'val2', 'val3' ], myString: 'testString' }, {}, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.data.should.be.a('string');
JSON
.parse(result.data.data)
.url
.should.be.equal('http://httpbin.org/get?myArray[]=val1&myArray[]=val2&myArray[]=val3&myString=testString');
}
},{
description: 'should reject non-string values in local header object #54',
expected: 'rejected: {"status": 0, "error": "advanced-http: header values must be strings" ...',
func: function(resolve, reject) {
cordova.plugin.http.get('http://httpbin.org/get', {}, { myTestHeader: 1 }, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('rejected');
result.data.error.should.be.equal('advanced-http: header values must be strings');
}
},{
description: 'should throw an error while setting non-string value as global header #54',
expected: 'throwed: "advanced-http: header values must be strings"',
func: function(resolve, reject) {
cordova.plugin.http.setHeader('myTestHeader', 2);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('throwed');
result.message.should.be.equal('advanced-http: header values must be strings');
}
},{
description: 'should accept content-type "application/xml" #58',
expected: 'resolved: {"status": 200, ...',
func: function(resolve, reject) {
cordova.plugin.http.get('http://httpbin.org/xml', {}, {}, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.status.should.be.equal(200);
}
},{
description: 'should send programmatically set cookies correctly (GET)',
expected: 'resolved: {"status": 200, ...',
func: function(resolve, reject) {
cordova.plugin.http.setCookie('http://httpbin.org/get', 'myCookie=myValue');
cordova.plugin.http.setCookie('http://httpbin.org/get', 'mySecondCookie=mySecondValue');
cordova.plugin.http.get('http://httpbin.org/get', {}, {}, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.data.should.be.a('string');
JSON
.parse(result.data.data)
.headers
.Cookie
.should.be.equal('myCookie=myValue; mySecondCookie=mySecondValue');
}
},{
description: 'should not send any cookies after running "clearCookies" (GET) #59',
expected: 'resolved: {"status": 200, "data": "{\"headers\": {\"Cookie\": \"\"...',
func: function(resolve, reject) {
cordova.plugin.http.setCookie('http://httpbin.org/get', 'myCookie=myValue');
cordova.plugin.http.setCookie('http://httpbin.org/get', 'mySecondCookie=mySecondValue');
cordova.plugin.http.clearCookies();
cordova.plugin.http.get('http://httpbin.org/get', {}, {}, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.data.should.be.a('string');
JSON
.parse(result.data.data)
.headers
.Cookie
.should.be.equal('');
}
},{
description: 'should send programmatically set cookies correctly (DOWNLOAD) #57',
expected: 'resolved: {"content":{"cookies":{"myCookie":"myValue ...',
func: function(resolve, reject) {
var sourceUrl = 'http://httpbin.org/cookies';
var targetPath = cordova.file.cacheDirectory + 'cookies.json';
cordova.plugin.http.setCookie('http://httpbin.org/get', 'myCookie=myValue');
cordova.plugin.http.setCookie('http://httpbin.org/get', 'mySecondCookie=mySecondValue');
cordova.plugin.http.downloadFile(sourceUrl, {}, {}, targetPath, function(entry) {
helpers.getWithXhr(function(content) {
resolve({
sourceUrl: sourceUrl,
targetPath: targetPath,
fullPath: entry.fullPath,
name: entry.name,
content: content
});
}, targetPath);
}, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('resolved');
result.data.name.should.be.equal('cookies.json');
result.data.content.should.be.a('string');
var cookies = JSON.parse(result.data.content).cookies;
cookies.myCookie.should.be.equal('myValue');
cookies.mySecondCookie.should.be.equal('mySecondValue');
}
}
];
+10 -6
View File
@@ -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,8 +114,12 @@ 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');
});
it('throws an Error when you try to add a cookie by using "setHeader" #46', () => {
(function() { http.setHeader('*', 'cookie', 'value') }).should.throw();
});
});
+79 -5
View File
@@ -39,6 +39,11 @@ var exec = require('cordova/exec');
var angularIntegration = require(pluginId +'.angular-integration');
var cookieHandler = require(pluginId + '.cookie-handler');
var MANDATORY_SUCCESS = 'advanced-http: missing mandatory "onSuccess" callback function';
var MANDATORY_FAIL = 'advanced-http: missing mandatory "onFail" callback function';
var ADDING_COOKIES_NOT_SUPPORTED = 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead';
var HEADER_VALUE_MUST_BE_STRING = 'advanced-http: header values must be strings';
// Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
@@ -61,6 +66,29 @@ function mergeHeaders(globalHeaders, localHeaders) {
return localHeaders;
}
function checkHeaders(headers) {
var keys = Object.keys(headers);
var key;
for (var i = 0; i < keys.length; i++) {
key = keys[i];
if (typeof headers[key] !== 'string') {
return false;
}
}
return true;
}
function onInvalidHeader(handler) {
handler({
status: 0,
error: HEADER_VALUE_MUST_BE_STRING,
headers: {}
});
}
function checkSerializer(serializer) {
serializer = serializer || '';
serializer = serializer.trim().toLowerCase();
@@ -134,11 +162,11 @@ function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
function handleMissingCallbacks(successFn, failFn) {
if (Object.prototype.toString.call(successFn) !== '[object Function]') {
throw new Error('advanced-http: missing mandatory "onSuccess" callback function');
throw new Error(MANDATORY_SUCCESS);
}
if (Object.prototype.toString.call(failFn) !== '[object Function]') {
throw new Error('advanced-http: missing mandatory "onFail" callback function');
throw new Error(MANDATORY_FAIL);
}
}
@@ -165,19 +193,33 @@ var http = {
value = arguments[2];
}
if (header.toLowerCase() === 'cookie') {
throw new Error(ADDING_COOKIES_NOT_SUPPORTED);
}
if (typeof value !== 'string') {
throw new Error(HEADER_VALUE_MUST_BE_STRING);
}
this.headers[host] = this.headers[host] || {};
this.headers[host][header] = value;
},
setDataSerializer: function (serializer) {
this.dataSerializer = checkSerializer(serializer);
},
setCookie: function (url, cookie, options) {
cookieHandler.setCookie(url, cookie, options);
},
clearCookies: function () {
return cookieHandler.clearCookies();
cookieHandler.clearCookies();
},
removeCookies: function (url, callback) {
cookieHandler.removeCookies(url, callback);
},
setRequestTimeout: function(timeout) {
getCookieString: function (url) {
return cookieHandler.getCookieString(url);
},
setRequestTimeout: function (timeout) {
this.timeoutInSeconds = timeout;
},
enableSSLPinning: function (enable, success, failure) {
@@ -186,7 +228,7 @@ var http = {
acceptAllCerts: function (allow, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'acceptAllCerts', [allow]);
},
disableRedirect: function(disable, success, failure) {
disableRedirect: function (disable, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'disableRedirect', [disable]);
},
validateDomainName: function (validate, success, failure) {
@@ -198,6 +240,10 @@ var http = {
data = data || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -209,6 +255,10 @@ var http = {
params = params || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -220,6 +270,10 @@ var http = {
data = data || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -232,6 +286,10 @@ var http = {
data = data || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -244,6 +302,10 @@ var http = {
params = params || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -255,6 +317,10 @@ var http = {
params = params || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -266,6 +332,10 @@ var http = {
params = params || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, success);
var onFail = injectCookieHandler(url, failure);
@@ -277,6 +347,10 @@ var http = {
params = params || {};
headers = getMergedHeaders(url, headers, this.headers);
if (!checkHeaders(headers)) {
return onInvalidHeader(failure);
}
var onSuccess = injectCookieHandler(url, injectFileEntryHandler(success));
var onFail = injectCookieHandler(url, failure);
+7
View File
@@ -10,6 +10,7 @@ var cookieJar = new ToughCookie.CookieJar(store);
module.exports = {
setCookieFromString: setCookieFromString,
setCookie: setCookie,
getCookieString: getCookieString,
clearCookies: clearCookies,
removeCookies: removeCookies
@@ -45,6 +46,12 @@ function setCookieFromString(url, cookieStr) {
}
}
function setCookie(url, cookie, options) {
options = options || {};
options.ignoreError = false;
cookieJar.setCookieSync(cookie, url, options);
}
function getCookieString(url) {
return cookieJar.getCookieStringSync(url);
}