mirror of
https://github.com/silkimen/cordova-plugin-advanced-http.git
synced 2026-07-26 00:00:14 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1719334d39 | ||
|
|
8db15c6c96 | ||
|
|
e58a398c33 | ||
|
|
a637d70ec1 | ||
|
|
6f40ed5cd8 | ||
|
|
8b09e159fa | ||
|
|
1d5642c8ae | ||
|
|
a580ce2067 | ||
|
|
35dc0205aa | ||
|
|
2dbf0d452a | ||
|
|
8a9381ffaa | ||
|
|
f1c95ef6fd | ||
|
|
6877fbdb65 | ||
|
|
a52e243e5f | ||
|
|
9c34f47624 | ||
|
|
3f1ee62088 | ||
|
|
c73b15b620 | ||
|
|
86698ffdcc | ||
|
|
4a396c28e5 | ||
|
|
53224ed875 | ||
|
|
3adec712c9 | ||
|
|
a49bcac81b | ||
|
|
2f01d48abb | ||
|
|
53df68f154 | ||
|
|
441268586b | ||
|
|
df86929148 | ||
|
|
f691d09eb0 | ||
|
|
b68cbcd157 | ||
|
|
a9bdca2d6d | ||
|
|
5186b375a4 | ||
|
|
d28eedebd0 | ||
|
|
25b4a283ea | ||
|
|
ebef9a2944 | ||
|
|
c452b29433 | ||
|
|
60e7debbdf | ||
|
|
5d5a859cfc |
+1
-3
@@ -13,9 +13,7 @@ cache:
|
||||
- node_modules
|
||||
|
||||
addons:
|
||||
sauce_connect:
|
||||
username: silkimen
|
||||
jwt: RZHC8x5ggrXdu1xzhhHmQDwege9s3putJXY1ZG8+MNMaBTLfLBWzFsHuR6Lvz+XnrAT/CTGG957kw6ikSaV6VEkGvtO91irZoJyShjPq2hBbn2CaEbo91Eq8iNYaRG+4FVMxoHa6xpF/HtvOLQdIkURc/lzLj/BOFMmtV/d3adLDcryQZuYB211iN4d6exGHMQe8uvJdkCy4ac85guhF8KmAELyaVa0rx0m6gNaszWU9BJ8Rn+4HJbJtfpQcU1bJN43Dx8forRU/Com53K+KFtDKPUdBHZnuENrZrQ+8RU59vdLrHwsCvP9elJFkcX9xk/r45oUGXhqVV3vMyaqTa9YUO772rhgKuAi4TqiaR51H58KWqynp7wOZwL5FqJs0KzL5rNDDIoKKrklnOidS4RAUKXCi1CUNXwDdOo4Kd96cYOIHqpwa7Beci8CtVlzd/49yE9/AXnZYVwp10uKZvJJdliAOHhVEAtCIp8PzHOOPYJsXvUcEU4ORWWWpusBAz6wFiLOL4d/CAHNj6wDFliRexBrv/Wunu5ifva4oVJWrtAtyGDtsX8kBkf8OcIdy/aPUIIBrbW1sapjPFymMGeL/KkSZRjEy7KjFZKZh9L7sJE56sq+IUremFbcyaX1E3rho6Cs3ongLaKhL9f9vz8EFs7//w8pNlNS9EUdOU68=
|
||||
sauce_connect: true
|
||||
|
||||
before_install:
|
||||
- export LANG=en_US.UTF-8
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 1.10.2
|
||||
|
||||
- Fixed #78: overriding header "Content-Type" not working on Android
|
||||
- Fixed #79: PATCH operation not working on Android API level 19 and older (thanks chax)
|
||||
- Fixed #83: App crashes on error during download operation on iOS (thanks troyanskiy)
|
||||
- Fixed #76: upload sequence is not respecting order of operations needed by some sites (thanks Johny101)
|
||||
|
||||
- :warning: **Deprecation**: AngularJS service is deprecated now and will be removed anytime soon
|
||||
|
||||
## 1.10.1
|
||||
|
||||
- Fixed #71: does not encode query string in URL correctly on Android
|
||||
- Fixed #72: app crashes if response encoding is not UTF-8 (thanks jkfb)
|
||||
|
||||
## 1.10.0
|
||||
|
||||
- Feature #34: add new serializer "utf8" sending utf-8 encoded plain text (thanks robertocapuano)
|
||||
|
||||
## 1.9.1
|
||||
|
||||
- Fixed #45: does not encode arrays correctly as HTTP GET parameter on Android
|
||||
|
||||
@@ -32,11 +32,17 @@ cordova plugin add cordova-plugin-advanced-http
|
||||
|
||||
## Usage
|
||||
|
||||
### Without AngularJS
|
||||
### Plain Cordova
|
||||
|
||||
This plugin registers a global object located at `cordova.plugin.http`.
|
||||
|
||||
### With AngularJS
|
||||
### With Ionic-native wrapper
|
||||
|
||||
Check the [Ionic docs](https://ionicframework.com/docs/native/http/) for how to use this plugin with Ionic-native.
|
||||
|
||||
### With AngularJS (Deprecated)
|
||||
|
||||
:warning: *This feature is deprecated and will be removed anytime soon.* :warning:
|
||||
|
||||
This plugin creates a cordovaHTTP service inside of a cordovaHTTP module. You must load the module when you create your app's module.
|
||||
|
||||
@@ -63,7 +69,7 @@ This sets up all future requests to use Basic HTTP authentication with the given
|
||||
cordova.plugin.http.useBasicAuth('user', 'password');
|
||||
```
|
||||
|
||||
### setHeader
|
||||
### setHeader<a name="setHeader"></a>
|
||||
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
|
||||
@@ -101,11 +107,14 @@ Set the data serializer which will be used for all future PATCH, POST and PUT re
|
||||
cordova.plugin.http.setDataSerializer('urlencoded');
|
||||
```
|
||||
|
||||
You can choose one of these two:
|
||||
You can choose one of these:
|
||||
* `urlencoded`: send data as url encoded content in body (content type "application/x-www-form-urlencoded")
|
||||
* `json`: send data as JSON encoded content in body (content type "application/json")
|
||||
* `utf8`: send data as plain UTF8 encoded string in body (content type "plain/text")
|
||||
|
||||
Caution: `urlencoded` does not support serializing deep structures whereas `json` does.
|
||||
You can also override the default content type headers by specifying your own headers (see [setHeader](#setHeader)).
|
||||
|
||||
__Caution__: `urlencoded` does not support serializing deep structures whereas `json` does.
|
||||
|
||||
### setRequestTimeout
|
||||
Set how long to wait for a request to respond, in seconds.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cordova-plugin-advanced-http",
|
||||
"version": "1.9.1",
|
||||
"version": "1.10.2",
|
||||
"description": "Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning",
|
||||
"scripts": {
|
||||
"testandroid": "./scripts/build-test-app.sh --android --emulator && ./scripts/test-app.sh --android --emulator",
|
||||
|
||||
+7
-1
@@ -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.9.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.10.2">
|
||||
<name>Advanced HTTP plugin</name>
|
||||
<description>
|
||||
Cordova / Phonegap plugin for communicating with HTTP servers using SSL pinning
|
||||
@@ -10,9 +10,11 @@
|
||||
<dependency id="cordova-plugin-file" version=">=2.0.0"/>
|
||||
<js-module src="www/lodash.js" name="lodash"/>
|
||||
<js-module src="www/umd-tough-cookie.js" name="tough-cookie"/>
|
||||
<js-module src="www/messages.js" name="messages"/>
|
||||
<js-module src="www/local-storage-store.js" name="local-storage-store"/>
|
||||
<js-module src="www/cookie-handler.js" name="cookie-handler"/>
|
||||
<js-module src="www/angular-integration.js" name="angular-integration"/>
|
||||
<js-module src="www/helpers.js" name="helpers"/>
|
||||
<js-module src="www/advanced-http.js" name="http">
|
||||
<clobbers target="cordova.plugin.http"/>
|
||||
</js-module>
|
||||
@@ -24,6 +26,7 @@
|
||||
</config-file>
|
||||
<header-file src="src/ios/CordovaHttpPlugin.h"/>
|
||||
<header-file src="src/ios/TextResponseSerializer.h"/>
|
||||
<header-file src="src/ios/TextRequestSerializer.h"/>
|
||||
<header-file src="src/ios/AFNetworking/AFHTTPSessionManager.h"/>
|
||||
<header-file src="src/ios/AFNetworking/AFNetworking.h"/>
|
||||
<header-file src="src/ios/AFNetworking/AFNetworkReachabilityManager.h"/>
|
||||
@@ -33,6 +36,7 @@
|
||||
<header-file src="src/ios/AFNetworking/AFURLSessionManager.h"/>
|
||||
<source-file src="src/ios/CordovaHttpPlugin.m"/>
|
||||
<source-file src="src/ios/TextResponseSerializer.m"/>
|
||||
<source-file src="src/ios/TextRequestSerializer.m"/>
|
||||
<source-file src="src/ios/AFNetworking/AFHTTPSessionManager.m"/>
|
||||
<source-file src="src/ios/AFNetworking/AFNetworkReachabilityManager.m"/>
|
||||
<source-file src="src/ios/AFNetworking/AFSecurityPolicy.m"/>
|
||||
@@ -52,6 +56,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</config-file>
|
||||
<source-file src="src/android/com/github/kevinsawicki/http/HttpRequest.java" target-dir="src/com/github/kevinsawicki/http"/>
|
||||
<source-file src="src/android/com/github/kevinsawicki/http/OkConnectionFactory.java" target-dir="src/com/github/kevinsawicki/http"/>
|
||||
<source-file src="src/android/com/github/kevinsawicki/http/TLSSocketFactory.java" target-dir="src/com/github/kevinsawicki/http"/>
|
||||
<source-file src="src/android/com/synconset/cordovahttp/CordovaHttp.java" target-dir="src/com/synconset/cordovahttp"/>
|
||||
<source-file src="src/android/com/synconset/cordovahttp/CordovaHttpDelete.java" target-dir="src/com/synconset/cordovahttp"/>
|
||||
@@ -63,5 +68,6 @@
|
||||
<source-file src="src/android/com/synconset/cordovahttp/CordovaHttpPut.java" target-dir="src/com/synconset/cordovahttp"/>
|
||||
<source-file src="src/android/com/synconset/cordovahttp/CordovaHttpPatch.java" target-dir="src/com/synconset/cordovahttp"/>
|
||||
<source-file src="src/android/com/synconset/cordovahttp/CordovaHttpUpload.java" target-dir="src/com/synconset/cordovahttp"/>
|
||||
<framework src="com.squareup.okhttp3:okhttp-urlconnection:3.9.1"/>
|
||||
</platform>
|
||||
</plugin>
|
||||
@@ -3,6 +3,11 @@ set -e
|
||||
|
||||
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
|
||||
|
||||
if [ $CI == "true" ] && ([ -z $SAUCE_USERNAME ] || [ -z $SAUCE_ACCESS_KEY ]); then
|
||||
echo "Skipping CI tests, because Saucelabs credentials are not set.";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
pushd $ROOT
|
||||
./node_modules/.bin/mocha ./test/app-mocha-specs/test.js "$@"
|
||||
popd
|
||||
|
||||
@@ -5,6 +5,11 @@ PLATFORM=$([[ "${@#--android}" = "$@" ]] && echo "ios" || echo "android")
|
||||
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
|
||||
TEMP=$ROOT/temp
|
||||
|
||||
if [ -z $SAUCE_USERNAME ] || [ -z $SAUCE_ACCESS_KEY ]; then
|
||||
echo "Skipping uploading artifact, because Saucelabs credentials are not set.";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
if [ $PLATFORM = "android" ]; then
|
||||
curl -u $SAUCE_USERNAME:$SAUCE_ACCESS_KEY \
|
||||
-X POST \
|
||||
|
||||
@@ -92,6 +92,8 @@ import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* A fluid interface for making HTTP requests using an underlying
|
||||
* {@link HttpURLConnection} (or sub-class).
|
||||
@@ -106,6 +108,11 @@ public class HttpRequest {
|
||||
*/
|
||||
public static final String CHARSET_UTF8 = "UTF-8";
|
||||
|
||||
/**
|
||||
* 'ISO-8859-1' charset name
|
||||
*/
|
||||
public static final String CHARSET_LATIN1 = "ISO-8859-1";
|
||||
|
||||
/**
|
||||
* 'application/x-www-form-urlencoded' content type header value
|
||||
*/
|
||||
@@ -363,26 +370,35 @@ public class HttpRequest {
|
||||
}
|
||||
|
||||
private static StringBuilder addParam(final Object key, Object value,
|
||||
final StringBuilder result) {
|
||||
final StringBuilder result) throws HttpRequestException {
|
||||
return addParam(key, value, result, CHARSET_UTF8);
|
||||
}
|
||||
|
||||
private static StringBuilder addParam(final Object key, Object value,
|
||||
final StringBuilder result, String charset) throws HttpRequestException {
|
||||
if (value != null && value.getClass().isArray())
|
||||
value = arrayToList(value);
|
||||
|
||||
if (value instanceof Iterable<?>) {
|
||||
Iterator<?> iterator = ((Iterable<?>) value).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
result.append(key);
|
||||
result.append("[]=");
|
||||
Object element = iterator.next();
|
||||
if (element != null)
|
||||
result.append(element);
|
||||
if (iterator.hasNext())
|
||||
result.append("&");
|
||||
try {
|
||||
if (value instanceof Iterable<?>) {
|
||||
Iterator<?> iterator = ((Iterable<?>) value).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
result.append(URLEncoder.encode(key.toString(), charset));
|
||||
result.append("[]=");
|
||||
Object element = iterator.next();
|
||||
if (element != null)
|
||||
result.append(URLEncoder.encode(element.toString(), charset));
|
||||
if (iterator.hasNext())
|
||||
result.append("&");
|
||||
}
|
||||
} else {
|
||||
result.append(URLEncoder.encode(key.toString(), charset));
|
||||
result.append("=");
|
||||
if (value != null)
|
||||
result.append(URLEncoder.encode(value.toString(), charset));
|
||||
}
|
||||
} else {
|
||||
result.append(key);
|
||||
result.append("=");
|
||||
if (value != null)
|
||||
result.append(value);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new HttpRequestException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -412,15 +428,7 @@ public class HttpRequest {
|
||||
* A {@link ConnectionFactory} which uses the built-in
|
||||
* {@link URL#openConnection()}
|
||||
*/
|
||||
ConnectionFactory DEFAULT = new ConnectionFactory() {
|
||||
public HttpURLConnection create(URL url) throws IOException {
|
||||
return (HttpURLConnection) url.openConnection();
|
||||
}
|
||||
|
||||
public HttpURLConnection create(URL url, Proxy proxy) throws IOException {
|
||||
return (HttpURLConnection) url.openConnection(proxy);
|
||||
}
|
||||
};
|
||||
ConnectionFactory DEFAULT = new OkConnectionFactory();
|
||||
}
|
||||
|
||||
private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
|
||||
@@ -1929,16 +1937,24 @@ public class HttpRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response body as a {@link String} and set it as the value of the
|
||||
* Get the response body as ByteBuffer and set it as the value of the
|
||||
* given reference.
|
||||
*
|
||||
* @param output
|
||||
* @return this request
|
||||
* @throws HttpRequestException
|
||||
*/
|
||||
public HttpRequest body(final AtomicReference<String> output) throws HttpRequestException {
|
||||
output.set(body());
|
||||
return this;
|
||||
public HttpRequest body(final AtomicReference<ByteBuffer> output) throws HttpRequestException {
|
||||
final ByteArrayOutputStream outputStream = byteStream();
|
||||
|
||||
try {
|
||||
copy(buffer(), outputStream);
|
||||
output.set(ByteBuffer.wrap(outputStream.toByteArray()));
|
||||
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new HttpRequestException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1955,7 +1971,6 @@ public class HttpRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the response body empty?
|
||||
*
|
||||
@@ -2529,6 +2544,16 @@ public class HttpRequest {
|
||||
return header(HEADER_ACCEPT_CHARSET, acceptCharset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'Accept-Charset' header to given values
|
||||
*
|
||||
* @param acceptCharsets
|
||||
* @return this request
|
||||
*/
|
||||
public HttpRequest acceptCharset(final String[] acceptCharsets) {
|
||||
return header(HEADER_ACCEPT_CHARSET, TextUtils.join(", ", acceptCharsets));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the 'Content-Encoding' header from the response
|
||||
*
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.github.kevinsawicki.http;
|
||||
|
||||
import okhttp3.OkUrlFactory;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.net.Proxy;
|
||||
|
||||
|
||||
public class OkConnectionFactory implements HttpRequest.ConnectionFactory {
|
||||
|
||||
protected OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
public HttpURLConnection create(URL url) {
|
||||
OkUrlFactory okUrlFactory = new OkUrlFactory(okHttpClient);
|
||||
return (HttpURLConnection) okUrlFactory.open(url);
|
||||
}
|
||||
|
||||
public HttpURLConnection create(URL url, Proxy proxy) {
|
||||
OkHttpClient okHttpClientWithProxy = okHttpClient.newBuilder().proxy(proxy).build();
|
||||
OkUrlFactory okUrlFactory = new OkUrlFactory(okHttpClientWithProxy);
|
||||
return (HttpURLConnection) okUrlFactory.open(url);
|
||||
}
|
||||
}
|
||||
@@ -11,45 +11,45 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
public class TLSSocketFactory extends SSLSocketFactory {
|
||||
|
||||
private SSLSocketFactory internalSSLSocketFactory;
|
||||
private SSLSocketFactory delegate;
|
||||
|
||||
public TLSSocketFactory(SSLContext context) {
|
||||
internalSSLSocketFactory = context.getSocketFactory();
|
||||
delegate = context.getSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return internalSSLSocketFactory.getDefaultCipherSuites();
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return internalSSLSocketFactory.getSupportedCipherSuites();
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
|
||||
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
return enableTLSOnSocket(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
|
||||
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
return enableTLSOnSocket(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
|
||||
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
private Socket enableTLSOnSocket(Socket socket) {
|
||||
|
||||
@@ -12,6 +12,14 @@ import org.json.JSONObject;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.MalformedInputException;
|
||||
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -19,6 +27,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.Iterator;
|
||||
|
||||
import android.text.TextUtils;
|
||||
@@ -28,7 +37,7 @@ import com.github.kevinsawicki.http.HttpRequest.HttpRequestException;
|
||||
|
||||
abstract class CordovaHttp {
|
||||
protected static final String TAG = "CordovaHTTP";
|
||||
protected static final String CHARSET = "UTF-8";
|
||||
protected static final String[] ACCEPTED_CHARSETS = new String[] { HttpRequest.CHARSET_UTF8, HttpRequest.CHARSET_LATIN1 };
|
||||
|
||||
private static AtomicBoolean sslPinning = new AtomicBoolean(false);
|
||||
private static AtomicBoolean acceptAllCerts = new AtomicBoolean(false);
|
||||
@@ -43,12 +52,7 @@ abstract class CordovaHttp {
|
||||
private CallbackContext callbackContext;
|
||||
|
||||
public CordovaHttp(String urlString, Object params, JSONObject headers, int timeout, CallbackContext callbackContext) {
|
||||
this.urlString = urlString;
|
||||
this.params = params;
|
||||
this.serializerName = "default";
|
||||
this.headers = headers;
|
||||
this.timeoutInMilliseconds = timeout;
|
||||
this.callbackContext = callbackContext;
|
||||
this(urlString, params, "default", headers, timeout, callbackContext);
|
||||
}
|
||||
|
||||
public CordovaHttp(String urlString, Object params, String serializerName, JSONObject headers, int timeout, CallbackContext callbackContext) {
|
||||
@@ -140,15 +144,12 @@ abstract class CordovaHttp {
|
||||
return request;
|
||||
}
|
||||
|
||||
protected HttpRequest setupDataSerializer(HttpRequest request) throws JSONException, Exception {
|
||||
if (new String("json").equals(this.getSerializerName())) {
|
||||
protected void setupDataSerializer(HttpRequest request) throws JSONException, Exception {
|
||||
if ("json".equals(this.getSerializerName())) {
|
||||
request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8);
|
||||
request.send(this.getParamsObject().toString());
|
||||
} else {
|
||||
request.form(this.getParamsMap());
|
||||
} else if ("utf8".equals(this.getSerializerName())) {
|
||||
request.contentType("text/plain", request.CHARSET_UTF8);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
protected void respondWithError(int status, String msg) {
|
||||
@@ -222,31 +223,85 @@ abstract class CordovaHttp {
|
||||
protected void prepareRequest(HttpRequest request) throws HttpRequestException, JSONException {
|
||||
this.setupRedirect(request);
|
||||
this.setupSecurity(request);
|
||||
|
||||
request.readTimeout(this.getRequestTimeout());
|
||||
request.acceptCharset(CHARSET);
|
||||
request.acceptCharset(ACCEPTED_CHARSETS);
|
||||
request.headers(this.getHeadersMap());
|
||||
request.uncompress(true);
|
||||
}
|
||||
|
||||
protected void prepareRequestBody(HttpRequest request) throws JSONException, Exception {
|
||||
if ("json".equals(this.getSerializerName())) {
|
||||
request.send(this.getParamsObject().toString());
|
||||
} else if ("utf8".equals(this.getSerializerName())) {
|
||||
request.send(this.getParamsMap().get("text").toString());
|
||||
} else {
|
||||
request.form(this.getParamsMap());
|
||||
}
|
||||
}
|
||||
|
||||
private CharsetDecoder createCharsetDecoder(final String charsetName) {
|
||||
return Charset.forName(charsetName).newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
}
|
||||
|
||||
private String decodeBody(AtomicReference<ByteBuffer> rawOutput, String charsetName)
|
||||
throws CharacterCodingException, MalformedInputException {
|
||||
|
||||
if (charsetName == null) {
|
||||
return tryDecodeByteBuffer(rawOutput);
|
||||
}
|
||||
|
||||
return decodeByteBuffer(rawOutput, charsetName);
|
||||
}
|
||||
|
||||
private String tryDecodeByteBuffer(AtomicReference<ByteBuffer> rawOutput)
|
||||
throws CharacterCodingException, MalformedInputException {
|
||||
|
||||
for (int i = 0; i < ACCEPTED_CHARSETS.length - 1; i++) {
|
||||
try {
|
||||
return decodeByteBuffer(rawOutput, ACCEPTED_CHARSETS[i]);
|
||||
} catch (MalformedInputException e) {
|
||||
continue;
|
||||
} catch (CharacterCodingException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return decodeBody(rawOutput, ACCEPTED_CHARSETS[ACCEPTED_CHARSETS.length - 1]);
|
||||
}
|
||||
|
||||
private String decodeByteBuffer(AtomicReference<ByteBuffer> rawOutput, String charsetName)
|
||||
throws CharacterCodingException, MalformedInputException {
|
||||
|
||||
return createCharsetDecoder(charsetName).decode(rawOutput.get()).toString();
|
||||
}
|
||||
|
||||
protected void returnResponseObject(HttpRequest request) throws HttpRequestException {
|
||||
try {
|
||||
JSONObject response = new JSONObject();
|
||||
int code = request.code();
|
||||
String body = request.body(CHARSET);
|
||||
AtomicReference<ByteBuffer> rawOutputReference = new AtomicReference<ByteBuffer>();
|
||||
|
||||
request.body(rawOutputReference);
|
||||
response.put("status", code);
|
||||
response.put("url", request.url().toString());
|
||||
this.addResponseHeaders(request, response);
|
||||
|
||||
if (code >= 200 && code < 300) {
|
||||
response.put("data", body);
|
||||
response.put("data", decodeBody(rawOutputReference, request.charset()));
|
||||
this.getCallbackContext().success(response);
|
||||
} else {
|
||||
response.put("error", body);
|
||||
response.put("error", decodeBody(rawOutputReference, request.charset()));
|
||||
this.getCallbackContext().error(response);
|
||||
}
|
||||
} catch(JSONException e) {
|
||||
this.respondWithError("There was an error generating the response");
|
||||
} catch(MalformedInputException e) {
|
||||
this.respondWithError("Could not decode response data due to malformed data");
|
||||
} catch(CharacterCodingException e) {
|
||||
this.respondWithError("Could not decode response data due to invalid or unknown charset encoding");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,41 +26,12 @@ class CordovaHttpDelete extends CordovaHttp implements Runnable {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.delete(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: " + e.getMessage());
|
||||
}
|
||||
this.handleHttpRequestException(e);
|
||||
} catch (Exception e) {
|
||||
this.respondWithError(-1, e.getMessage());
|
||||
this.respondWithError(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,9 @@ class CordovaHttpPatch extends CordovaHttp implements Runnable {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.patch(this.getUrlString());
|
||||
|
||||
this.prepareRequest(request);
|
||||
this.setupDataSerializer(request);
|
||||
this.prepareRequest(request);
|
||||
this.prepareRequestBody(request);
|
||||
this.returnResponseObject(request);
|
||||
} catch (HttpRequestException e) {
|
||||
this.handleHttpRequestException(e);
|
||||
|
||||
@@ -25,8 +25,9 @@ class CordovaHttpPost extends CordovaHttp implements Runnable {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.post(this.getUrlString());
|
||||
|
||||
this.prepareRequest(request);
|
||||
this.setupDataSerializer(request);
|
||||
this.prepareRequest(request);
|
||||
this.prepareRequestBody(request);
|
||||
this.returnResponseObject(request);
|
||||
} catch (HttpRequestException e) {
|
||||
this.handleHttpRequestException(e);
|
||||
|
||||
@@ -25,8 +25,9 @@ class CordovaHttpPut extends CordovaHttp implements Runnable {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.put(this.getUrlString());
|
||||
|
||||
this.prepareRequest(request);
|
||||
this.setupDataSerializer(request);
|
||||
this.prepareRequest(request);
|
||||
this.prepareRequestBody(request);
|
||||
this.returnResponseObject(request);
|
||||
} catch (HttpRequestException e) {
|
||||
this.handleHttpRequestException(e);
|
||||
|
||||
@@ -54,8 +54,6 @@ class CordovaHttpUpload extends CordovaHttp implements Runnable {
|
||||
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||
String mimeType = mimeTypeMap.getMimeTypeFromExtension(ext);
|
||||
|
||||
request.part(this.name, filename, mimeType, new File(uri));
|
||||
|
||||
Set<?> set = (Set<?>)this.getParamsMap().entrySet();
|
||||
Iterator<?> i = set.iterator();
|
||||
|
||||
@@ -72,6 +70,8 @@ class CordovaHttpUpload extends CordovaHttp implements Runnable {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
request.part(this.name, filename, mimeType, new File(uri));
|
||||
|
||||
this.returnResponseObject(request);
|
||||
} catch (URISyntaxException e) {
|
||||
|
||||
+215
-153
@@ -1,6 +1,7 @@
|
||||
#import "CordovaHttpPlugin.h"
|
||||
#import "CDVFile.h"
|
||||
#import "TextResponseSerializer.h"
|
||||
#import "TextRequestSerializer.h"
|
||||
#import "AFHTTPSessionManager.h"
|
||||
|
||||
@interface CordovaHttpPlugin()
|
||||
@@ -28,6 +29,8 @@
|
||||
- (void)setRequestSerializer:(NSString*)serializerName forManager:(AFHTTPSessionManager*)manager {
|
||||
if ([serializerName isEqualToString:@"json"]) {
|
||||
manager.requestSerializer = [AFJSONRequestSerializer serializer];
|
||||
} else if ([serializerName isEqualToString:@"utf8"]) {
|
||||
manager.requestSerializer = [TextRequestSerializer serializer];
|
||||
} else {
|
||||
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
|
||||
}
|
||||
@@ -52,7 +55,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:[NSNumber numberWithInt:(int)response.statusCode] forKey:@"status"];
|
||||
[dictionary setObject:[self copyHeaderFields:response.allHeaderFields] forKey:@"headers"];
|
||||
}
|
||||
|
||||
@@ -64,15 +67,28 @@
|
||||
- (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:[NSNumber numberWithInt:(int)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"];
|
||||
if (error.userInfo[AFNetworkingOperationFailingURLResponseBodyKey]) {
|
||||
[dictionary setObject:error.userInfo[AFNetworkingOperationFailingURLResponseBodyKey] forKey:@"error"];
|
||||
}
|
||||
} else {
|
||||
[dictionary setObject:[self getStatusCode:error] forKey:@"status"];
|
||||
[dictionary setObject:[error localizedDescription] forKey:@"error"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleException:(NSException*)exception withCommand:(CDVInvokedUrlCommand*)command {
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setValue:exception.userInfo forKey:@"error"];
|
||||
[dictionary setObject:[NSNumber numberWithInt:-1] forKey:@"status"];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (NSNumber*)getStatusCode:(NSError*) error {
|
||||
switch ([error code]) {
|
||||
case -1001:
|
||||
@@ -159,19 +175,25 @@
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager POST:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager POST:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)get:(CDVInvokedUrlCommand*)command {
|
||||
@@ -190,21 +212,26 @@
|
||||
[self setRedirect: manager];
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)put:(CDVInvokedUrlCommand*)command {
|
||||
@@ -224,19 +251,25 @@
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager PUT:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager PUT:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)patch:(CDVInvokedUrlCommand*)command {
|
||||
@@ -256,19 +289,25 @@
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager PATCH:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager PATCH:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)delete:(CDVInvokedUrlCommand*)command {
|
||||
@@ -286,21 +325,26 @@
|
||||
[self setRedirect: manager];
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager DELETE:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager DELETE:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)head:(CDVInvokedUrlCommand*)command {
|
||||
@@ -316,22 +360,27 @@
|
||||
[self setRedirect: manager];
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
|
||||
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
[manager HEAD:url parameters:parameters success:^(NSURLSessionTask *task) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
// no 'body' for HEAD request, omitting 'data'
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
@try {
|
||||
[manager HEAD:url parameters:parameters success:^(NSURLSessionTask *task) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
// no 'body' for HEAD request, omitting 'data'
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uploadFile:(CDVInvokedUrlCommand*)command {
|
||||
@@ -353,30 +402,36 @@
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
manager.responseSerializer = [TextResponseSerializer serializer];
|
||||
[manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
|
||||
NSError *error;
|
||||
[formData appendPartWithFileURL:fileURL name:name error:&error];
|
||||
if (error) {
|
||||
|
||||
@try {
|
||||
[manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
|
||||
NSError *error;
|
||||
[formData appendPartWithFileURL:fileURL name:name error:&error];
|
||||
if (error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
[dictionary setObject:@"Could not add file to post body." forKey:@"error"];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
[dictionary setObject:@"Could not add file to post body." forKey:@"error"];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -400,70 +455,77 @@
|
||||
|
||||
CordovaHttpPlugin* __weak weakSelf = self;
|
||||
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
[manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Modified by Andrew Stephan for Sync OnSet
|
||||
*
|
||||
*/
|
||||
// Download response is okay; begin streaming output to file
|
||||
NSString* parentPath = [filePath stringByDeletingLastPathComponent];
|
||||
|
||||
// create parent directories if needed
|
||||
NSError *error;
|
||||
if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
if (error) {
|
||||
[dictionary setObject:[NSString stringWithFormat:@"Could not create path to save downloaded file: %@", [error localizedDescription]] forKey:@"error"];
|
||||
} else {
|
||||
[dictionary setObject:@"Could not create path to save downloaded file" forKey:@"error"];
|
||||
@try {
|
||||
[manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Modified by Andrew Stephan for Sync OnSet
|
||||
*
|
||||
*/
|
||||
// Download response is okay; begin streaming output to file
|
||||
NSString* parentPath = [filePath stringByDeletingLastPathComponent];
|
||||
|
||||
// create parent directories if needed
|
||||
NSError *error;
|
||||
if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
if (error) {
|
||||
[dictionary setObject:[NSString stringWithFormat:@"Could not create path to save downloaded file: %@", [error localizedDescription]] forKey:@"error"];
|
||||
} else {
|
||||
[dictionary setObject:@"Could not create path to save downloaded file" forKey:@"error"];
|
||||
}
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
NSData *data = (NSData *)responseObject;
|
||||
if (![data writeToFile:filePath atomically:YES]) {
|
||||
NSData *data = (NSData *)responseObject;
|
||||
if (![data writeToFile:filePath atomically:YES]) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
[dictionary setObject:@"Could not write the data to the given filePath." forKey:@"error"];
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
id filePlugin = [self.commandDelegate getCommandInstance:@"File"];
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
|
||||
[dictionary setObject:@"Could not write the data to the given filePath." forKey:@"error"];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
|
||||
[dictionary setObject:[filePlugin getDirectoryEntry:filePath isDirectory:NO] forKey:@"file"];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
[dictionary setObject:@"There was an error downloading the file" forKey:@"error"];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
id filePlugin = [self.commandDelegate getCommandInstance:@"File"];
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
|
||||
[dictionary setObject:[filePlugin getDirectoryEntry:filePath isDirectory:NO] forKey:@"file"];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
} failure:^(NSURLSessionTask *task, NSError *error) {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
|
||||
|
||||
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
|
||||
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self handleException:exception withCommand:command];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "AFURLRequestSerialization.h"
|
||||
|
||||
@interface TextRequestSerializer : AFHTTPRequestSerializer
|
||||
|
||||
+ (instancetype)serializer;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,53 @@
|
||||
#import "TextRequestSerializer.h"
|
||||
|
||||
@implementation TextRequestSerializer
|
||||
|
||||
+ (instancetype)serializer
|
||||
{
|
||||
TextRequestSerializer *serializer = [[self alloc] init];
|
||||
return serializer;
|
||||
}
|
||||
|
||||
#pragma mark - AFURLRequestSerialization
|
||||
|
||||
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
|
||||
withParameters:(id)parameters
|
||||
error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(request);
|
||||
|
||||
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
|
||||
return [super requestBySerializingRequest:request withParameters:parameters error:error];
|
||||
}
|
||||
|
||||
NSMutableURLRequest *mutableRequest = [request mutableCopy];
|
||||
|
||||
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
|
||||
if (![request valueForHTTPHeaderField:field]) {
|
||||
[mutableRequest setValue:value forHTTPHeaderField:field];
|
||||
}
|
||||
}];
|
||||
|
||||
if (parameters) {
|
||||
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
|
||||
[mutableRequest setValue:@"text/plain; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
|
||||
}
|
||||
|
||||
[mutableRequest setHTTPBody: [[parameters valueForKey:@"text"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
|
||||
return mutableRequest;
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
self = [super initWithCoder:decoder];
|
||||
if (!self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -5,4 +5,6 @@
|
||||
|
||||
+ (instancetype)serializer;
|
||||
|
||||
@end
|
||||
FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseBodyKey;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,32 +1,126 @@
|
||||
#import "TextResponseSerializer.h"
|
||||
|
||||
static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
|
||||
if ([error.domain isEqualToString:domain] && error.code == code) {
|
||||
return YES;
|
||||
} else if (error.userInfo[NSUnderlyingErrorKey]) {
|
||||
return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
|
||||
}
|
||||
NSString * const AFNetworkingOperationFailingURLResponseBodyKey = @"com.alamofire.serialization.response.error.body";
|
||||
NSStringEncoding const SupportedEncodings[6] = { NSUTF8StringEncoding, NSWindowsCP1252StringEncoding, NSISOLatin1StringEncoding, NSISOLatin2StringEncoding, NSASCIIStringEncoding, NSUnicodeStringEncoding };
|
||||
|
||||
return NO;
|
||||
static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
|
||||
if (!error) {
|
||||
return underlyingError;
|
||||
}
|
||||
|
||||
if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
|
||||
return error;
|
||||
}
|
||||
|
||||
NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
|
||||
mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;
|
||||
|
||||
return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
|
||||
}
|
||||
|
||||
static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
|
||||
if ([error.domain isEqualToString:domain] && error.code == code) {
|
||||
return YES;
|
||||
} else if (error.userInfo[NSUnderlyingErrorKey]) {
|
||||
return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@implementation TextResponseSerializer
|
||||
|
||||
+ (instancetype)serializer {
|
||||
TextResponseSerializer *serializer = [[self alloc] init];
|
||||
return serializer;
|
||||
TextResponseSerializer *serializer = [[self alloc] init];
|
||||
return serializer;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
self = [super init];
|
||||
|
||||
if (!self) {
|
||||
return nil;
|
||||
if (!self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
self.acceptableContentTypes = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*)decodeResponseData:(NSData*)rawResponseData withEncoding:(CFStringEncoding)cfEncoding {
|
||||
NSStringEncoding nsEncoding;
|
||||
NSString* decoded = nil;
|
||||
|
||||
if (cfEncoding != kCFStringEncodingInvalidId) {
|
||||
nsEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(SupportedEncodings) / sizeof(NSStringEncoding) && !decoded; ++i) {
|
||||
if (cfEncoding == kCFStringEncodingInvalidId || nsEncoding == SupportedEncodings[i]) {
|
||||
decoded = [[NSString alloc] initWithData:rawResponseData encoding:SupportedEncodings[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
- (CFStringEncoding) getEncoding:(NSURLResponse *)response {
|
||||
CFStringEncoding encoding = kCFStringEncodingInvalidId;
|
||||
|
||||
if (response.textEncodingName) {
|
||||
encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||
}
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
|
||||
data:(NSData *)data
|
||||
decoded:(NSString **)decoded
|
||||
error:(NSError * __autoreleasing *)error
|
||||
{
|
||||
BOOL responseIsValid = YES;
|
||||
NSError *validationError = nil;
|
||||
|
||||
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
if (data) {
|
||||
*decoded = [self decodeResponseData:data withEncoding:[self getEncoding:response]];
|
||||
}
|
||||
|
||||
self.acceptableContentTypes = nil;
|
||||
if (data && !*decoded) {
|
||||
NSMutableDictionary *mutableUserInfo = [@{
|
||||
NSURLErrorFailingURLErrorKey:[response URL],
|
||||
AFNetworkingOperationFailingURLResponseErrorKey: response,
|
||||
AFNetworkingOperationFailingURLResponseDataErrorKey: data,
|
||||
AFNetworkingOperationFailingURLResponseBodyKey: @"Could not decode response data due to invalid or unknown charset encoding",
|
||||
} mutableCopy];
|
||||
|
||||
return self;
|
||||
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
|
||||
responseIsValid = NO;
|
||||
} else if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
|
||||
NSMutableDictionary *mutableUserInfo = [@{
|
||||
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
|
||||
NSURLErrorFailingURLErrorKey: [response URL],
|
||||
AFNetworkingOperationFailingURLResponseErrorKey: response,
|
||||
} mutableCopy];
|
||||
|
||||
if (data) {
|
||||
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
|
||||
mutableUserInfo[AFNetworkingOperationFailingURLResponseBodyKey] = *decoded;
|
||||
}
|
||||
|
||||
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
|
||||
responseIsValid = NO;
|
||||
}
|
||||
}
|
||||
|
||||
if (error && !responseIsValid) {
|
||||
*error = validationError;
|
||||
}
|
||||
|
||||
return responseIsValid;
|
||||
}
|
||||
|
||||
#pragma mark - AFURLResponseSerialization
|
||||
@@ -35,25 +129,15 @@ static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger co
|
||||
data:(NSData *)data
|
||||
error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
|
||||
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
|
||||
return nil;
|
||||
}
|
||||
NSString* decoded = nil;
|
||||
|
||||
if (![self validateResponse:(NSHTTPURLResponse *)response data:data decoded:&decoded error:error]) {
|
||||
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
|
||||
// See https://github.com/rails/rails/issues/1742
|
||||
NSStringEncoding stringEncoding = self.stringEncoding;
|
||||
if (response.textEncodingName) {
|
||||
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
|
||||
if (encoding != kCFStringEncodingInvalidId) {
|
||||
stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
|
||||
|
||||
return responseString;
|
||||
return decoded;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Binary file not shown.
@@ -1,13 +1,17 @@
|
||||
const hooks = {
|
||||
onBeforeEachTest: function(done) {
|
||||
cordova.plugin.http.clearCookies();
|
||||
cordova.plugin.http.acceptAllCerts(false, done, done);
|
||||
cordova.plugin.http.acceptAllCerts(false, function() {
|
||||
cordova.plugin.http.enableSSLPinning(false, done, done);
|
||||
}, done);
|
||||
}
|
||||
};
|
||||
|
||||
const helpers = {
|
||||
acceptAllCerts: function(done) { cordova.plugin.http.acceptAllCerts(true, done, done); },
|
||||
enableSSLPinning: function(done) { cordova.plugin.http.enableSSLPinning(true, done, done); },
|
||||
setJsonSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('json')); },
|
||||
setUtf8StringSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('utf8')); },
|
||||
setUrlEncodedSerializer: function(done) { done(cordova.plugin.http.setDataSerializer('urlencoded')); },
|
||||
getWithXhr: function(done, url) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
@@ -382,6 +386,84 @@ const tests = [
|
||||
cookies.myCookie.should.be.equal('myValue');
|
||||
cookies.mySecondCookie.should.be.equal('mySecondValue');
|
||||
}
|
||||
},{
|
||||
description: 'should send UTF-8 encoded raw string correctly (POST) #34',
|
||||
expected: 'resolved: {"status": 200, "data": "{\\"data\\": \\"this is a test string\\"...',
|
||||
before: helpers.setUtf8StringSerializer,
|
||||
func: function(resolve, reject) {
|
||||
cordova.plugin.http.post('http://httpbin.org/anything', 'this is a test string', {}, resolve, reject);
|
||||
},
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
JSON.parse(result.data.data).data.should.be.equal('this is a test string');
|
||||
}
|
||||
},{
|
||||
description: 'should encode spaces in query string (params object) correctly (GET) #71',
|
||||
expected: 'resolved: {"status": 200, "data": "{\\"args\\": \\"query param\\": \\"and value with spaces\\"...',
|
||||
func: function(resolve, reject) {
|
||||
cordova.plugin.http.get('http://httpbin.org/get', { 'query param': 'and value with spaces' }, {}, resolve, reject);
|
||||
},
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
JSON.parse(result.data.data).args['query param'].should.be.equal('and value with spaces');
|
||||
}
|
||||
},{
|
||||
description: 'should decode latin1 (iso-8859-1) encoded body correctly (GET) #72',
|
||||
expected: 'resolved: {"status": 200, "data": "<!DOCTYPE HTML PUBLIC \\"-//W3C//DTD HTML 4.01 Transitional//EN\\"> ...',
|
||||
func: function(resolve, reject) {
|
||||
cordova.plugin.http.get('http://www.columbia.edu/kermit/latin1.html', {}, {}, resolve, reject);
|
||||
},
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
result.data.data.should.include('[¡] 161 10/01 241 A1 INVERTED EXCLAMATION MARK\n[¢] 162 10/02 242 A2 CENT SIGN');
|
||||
}
|
||||
},{
|
||||
description: 'should return empty body string correctly (GET)',
|
||||
expected: 'resolved: {"status": 200, "data": "" ...',
|
||||
func: function(resolve, reject) {
|
||||
cordova.plugin.http.get('http://httpbin.org/stream/0', {}, {}, resolve, reject);
|
||||
},
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
result.data.data.should.be.equal('');
|
||||
}
|
||||
},{
|
||||
description: 'should pin SSL cert correctly (GET)',
|
||||
expected: 'resolved: {"status": 200 ...',
|
||||
before: helpers.enableSSLPinning,
|
||||
func: function(resolve, reject) {
|
||||
cordova.plugin.http.get('https://httpbin.org', {}, {}, resolve, reject);
|
||||
},
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
}
|
||||
},{
|
||||
description: 'should send deeply structured JSON object correctly (POST) #65',
|
||||
expected: 'resolved: {"status": 200, "data": "{\\"data\\": \\"{\\\\"outerObj\\\\":{\\\\"innerStr\\\\":\\\\"testString\\\\",\\\\"innerArr\\\\":[1,2,3]}}\\" ...',
|
||||
before: helpers.setJsonSerializer,
|
||||
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', { outerObj: { innerStr: 'testString', innerArr: [1, 2, 3] }}, {}, resolve, reject); },
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
JSON.parse(result.data.data).json.should.eql({ outerObj: { innerStr: 'testString', innerArr: [1, 2, 3] }});
|
||||
}
|
||||
},{
|
||||
description: 'should override header "content-type" correctly (POST) #78',
|
||||
expected: 'resolved: {"status": 200, "headers": "{\\"Content-Type\\": \\"text/plain\\" ...',
|
||||
before: helpers.setJsonSerializer,
|
||||
func: function(resolve, reject) { cordova.plugin.http.post('http://httpbin.org/anything', {}, { 'Content-Type': 'text/plain' }, resolve, reject); },
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('resolved');
|
||||
JSON.parse(result.data.data).headers['Content-Type'].should.be.equal('text/plain');
|
||||
}
|
||||
},{
|
||||
description: 'should handle error during file download correctly (DOWNLOAD) #83',
|
||||
expected: 'rejected: {"status": 403, "error": "There was an error downloading the file" ...',
|
||||
func: function(resolve, reject) { cordova.plugin.http.downloadFile('http://httpbin.org/status/403', {}, {}, cordova.file.tempDirectory + 'testfile.txt', resolve, reject); },
|
||||
validationFunc: function(driver, result) {
|
||||
result.type.should.be.equal('rejected');
|
||||
result.data.status.should.be.equal(403);
|
||||
result.data.error.should.be.equal('There was an error downloading the file');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
+19
-9
@@ -3,12 +3,18 @@ const mock = require('mock-require');
|
||||
const path = require('path');
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
const HELPERS_ID = path.resolve(__dirname, '..', 'www', 'helpers');
|
||||
const PLUGIN_ID = path.resolve(__dirname, '..', 'www', 'advanced-http');
|
||||
|
||||
describe('Advanced HTTP www interface', function() {
|
||||
let http = {};
|
||||
let helpers = {};
|
||||
|
||||
const noop = () => { /* intentionally doing nothing */ };
|
||||
|
||||
const loadHttp = () => {
|
||||
mock(`${PLUGIN_ID}.helpers`, mock.reRequire('../www/helpers'));
|
||||
http = mock.reRequire('../www/advanced-http');
|
||||
};
|
||||
|
||||
@@ -19,28 +25,32 @@ describe('Advanced HTTP www interface', function() {
|
||||
global.btoa = decoded => new Buffer(decoded).toString('base64');
|
||||
|
||||
mock('cordova/exec', noop);
|
||||
mock(`${PLUGIN_ID}.angular-integration`, { registerService: noop });
|
||||
mock(`${PLUGIN_ID}.cookie-handler`, {});
|
||||
mock(`${HELPERS_ID}.cookie-handler`, {});
|
||||
mock(`${PLUGIN_ID}.messages`, require('../www/messages'));
|
||||
mock(`${HELPERS_ID}.messages`, require('../www/messages'));
|
||||
mock(`${PLUGIN_ID}.angular-integration`, { registerService: noop });
|
||||
|
||||
loadHttp();
|
||||
});
|
||||
|
||||
it('sets global headers correctly with two args (old interface)', () => {
|
||||
http.setHeader('myKey', 'myValue');
|
||||
http.headers['*'].myKey.should.equal('myValue');
|
||||
http.getHeaders('*').myKey.should.equal('myValue');
|
||||
});
|
||||
|
||||
it('sets global headers correctly with three args (new interface) #24', () => {
|
||||
http.setHeader('*', 'myKey', 'myValue');
|
||||
http.headers['*'].myKey.should.equal('myValue');
|
||||
http.getHeaders('*').myKey.should.equal('myValue');
|
||||
});
|
||||
|
||||
it('sets host headers correctly #24', () => {
|
||||
http.setHeader('www.google.de', 'myKey', 'myValue');
|
||||
http.headers['www.google.de'].myKey.should.equal('myValue');
|
||||
http.getHeaders('www.google.de').myKey.should.equal('myValue');
|
||||
});
|
||||
|
||||
it('resolves global headers correctly #24', () => {
|
||||
mock(`${PLUGIN_ID}.cookie-handler`, {
|
||||
mock(`${HELPERS_ID}.cookie-handler`, {
|
||||
getCookieString: () => 'fakeCookieString'
|
||||
});
|
||||
|
||||
@@ -59,7 +69,7 @@ describe('Advanced HTTP www interface', function() {
|
||||
});
|
||||
|
||||
it('resolves host headers correctly (set without port number) #37', () => {
|
||||
mock(`${PLUGIN_ID}.cookie-handler`, {
|
||||
mock(`${HELPERS_ID}.cookie-handler`, {
|
||||
getCookieString: () => 'fakeCookieString'
|
||||
});
|
||||
|
||||
@@ -78,7 +88,7 @@ describe('Advanced HTTP www interface', function() {
|
||||
});
|
||||
|
||||
it('resolves host headers correctly (set with port number) #37', () => {
|
||||
mock(`${PLUGIN_ID}.cookie-handler`, {
|
||||
mock(`${HELPERS_ID}.cookie-handler`, {
|
||||
getCookieString: () => 'fakeCookieString'
|
||||
});
|
||||
|
||||
@@ -97,7 +107,7 @@ describe('Advanced HTTP www interface', function() {
|
||||
});
|
||||
|
||||
it('resolves request headers correctly', () => {
|
||||
mock(`${PLUGIN_ID}.cookie-handler`, {
|
||||
mock(`${HELPERS_ID}.cookie-handler`, {
|
||||
getCookieString: () => 'fakeCookieString'
|
||||
});
|
||||
|
||||
@@ -116,7 +126,7 @@ describe('Advanced HTTP www interface', function() {
|
||||
|
||||
it('sets basic authentication header correctly #36', () => {
|
||||
http.useBasicAuth('name', 'pass');
|
||||
http.headers['*'].Authorization.should.equal('Basic bmFtZTpwYXNz');
|
||||
http.getHeaders('*').Authorization.should.equal('Basic bmFtZTpwYXNz');
|
||||
});
|
||||
|
||||
it('throws an Error when you try to add a cookie by using "setHeader" #46', () => {
|
||||
|
||||
+90
-214
@@ -20,166 +20,36 @@
|
||||
* under the License.
|
||||
*
|
||||
* Modified by Andrew Stephan for Sync OnSet
|
||||
* Modified by Sefa Ilkimen:
|
||||
* - added configurable params serializer
|
||||
* - added put and delete methods
|
||||
* - using cordova www module pattern
|
||||
* - some minor improvements
|
||||
*
|
||||
* Modified by Sefa Ilkimen
|
||||
*/
|
||||
|
||||
/*
|
||||
* An HTTP Plugin for PhoneGap.
|
||||
*/
|
||||
|
||||
var pluginId = module.id.slice(0, module.id.indexOf('.'));
|
||||
var validSerializers = ['urlencoded', 'json'];
|
||||
var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var angularIntegration = require(pluginId +'.angular-integration');
|
||||
var cookieHandler = require(pluginId + '.cookie-handler');
|
||||
var helpers = require(pluginId + '.helpers');
|
||||
var messages = require(pluginId + '.messages');
|
||||
|
||||
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';
|
||||
var internals = {
|
||||
headers: {},
|
||||
dataSerializer: 'urlencoded',
|
||||
timeoutInSeconds: 60.0,
|
||||
};
|
||||
|
||||
// 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) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
}));
|
||||
}
|
||||
|
||||
function mergeHeaders(globalHeaders, localHeaders) {
|
||||
var globalKeys = Object.keys(globalHeaders);
|
||||
var key;
|
||||
|
||||
for (var i = 0; i < globalKeys.length; i++) {
|
||||
key = globalKeys[i];
|
||||
|
||||
if (!localHeaders.hasOwnProperty(key)) {
|
||||
localHeaders[key] = globalHeaders[key];
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (validSerializers.indexOf(serializer) > -1) {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
return serializer[0];
|
||||
}
|
||||
|
||||
function resolveCookieString(headers) {
|
||||
var keys = Object.keys(headers || {});
|
||||
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
if (keys[i].match(/^set-cookie$/i)) {
|
||||
return headers[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function createFileEntry(rawEntry) {
|
||||
var entry = new (require('cordova-plugin-file.FileEntry'))();
|
||||
|
||||
entry.isDirectory = rawEntry.isDirectory;
|
||||
entry.isFile = rawEntry.isFile;
|
||||
entry.name = rawEntry.name;
|
||||
entry.fullPath = rawEntry.fullPath;
|
||||
entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
|
||||
entry.nativeURL = rawEntry.nativeURL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
function injectCookieHandler(url, cb) {
|
||||
return function(response) {
|
||||
cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
|
||||
function injectFileEntryHandler(cb) {
|
||||
return function(response) {
|
||||
cb(createFileEntry(response.file));
|
||||
}
|
||||
}
|
||||
|
||||
function getCookieHeader(url) {
|
||||
return { Cookie: cookieHandler.getCookieString(url) };
|
||||
}
|
||||
|
||||
function getMatchingHostHeaders(url, headersList) {
|
||||
var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
|
||||
var domain = matches && matches[1];
|
||||
|
||||
return headersList[domain] || null;
|
||||
}
|
||||
|
||||
function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
|
||||
var globalHeaders = predefinedHeaders['*'] || {};
|
||||
var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
|
||||
var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
|
||||
|
||||
mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
|
||||
mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
|
||||
|
||||
return mergedHeaders;
|
||||
}
|
||||
|
||||
function handleMissingCallbacks(successFn, failFn) {
|
||||
if (Object.prototype.toString.call(successFn) !== '[object Function]') {
|
||||
throw new Error(MANDATORY_SUCCESS);
|
||||
}
|
||||
|
||||
if (Object.prototype.toString.call(failFn) !== '[object Function]') {
|
||||
throw new Error(MANDATORY_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
var http = {
|
||||
headers: {},
|
||||
dataSerializer: 'urlencoded',
|
||||
sslPinning: false,
|
||||
timeoutInSeconds: 60.0,
|
||||
var publicInterface = {
|
||||
getBasicAuthHeader: function (username, password) {
|
||||
return {'Authorization': 'Basic ' + b64EncodeUnicode(username + ':' + password)};
|
||||
return {'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password)};
|
||||
},
|
||||
useBasicAuth: function (username, password) {
|
||||
this.setHeader('*', 'Authorization', 'Basic ' + b64EncodeUnicode(username + ':' + password));
|
||||
this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
|
||||
},
|
||||
getHeaders: function (host) {
|
||||
return internals.headers[host || '*'] || null;
|
||||
},
|
||||
setHeader: function () {
|
||||
// this one is for being backward compatible
|
||||
@@ -194,18 +64,21 @@ var http = {
|
||||
}
|
||||
|
||||
if (header.toLowerCase() === 'cookie') {
|
||||
throw new Error(ADDING_COOKIES_NOT_SUPPORTED);
|
||||
throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error(HEADER_VALUE_MUST_BE_STRING);
|
||||
if (helpers.getTypeOf(value) !== 'String') {
|
||||
throw new Error(messages.HEADER_VALUE_MUST_BE_STRING);
|
||||
}
|
||||
|
||||
this.headers[host] = this.headers[host] || {};
|
||||
this.headers[host][header] = value;
|
||||
internals.headers[host] = internals.headers[host] || {};
|
||||
internals.headers[host][header] = value;
|
||||
},
|
||||
getDataSerializer: function () {
|
||||
return internals.dataSerializer;
|
||||
},
|
||||
setDataSerializer: function (serializer) {
|
||||
this.dataSerializer = checkSerializer(serializer);
|
||||
internals.dataSerializer = helpers.checkSerializer(serializer);
|
||||
},
|
||||
setCookie: function (url, cookie, options) {
|
||||
cookieHandler.setCookie(url, cookie, options);
|
||||
@@ -219,8 +92,11 @@ var http = {
|
||||
getCookieString: function (url) {
|
||||
return cookieHandler.getCookieString(url);
|
||||
},
|
||||
getRequestTimeout: function () {
|
||||
return internals.timeoutInSeconds;
|
||||
},
|
||||
setRequestTimeout: function (timeout) {
|
||||
this.timeoutInSeconds = timeout;
|
||||
internals.timeoutInSeconds = timeout;
|
||||
},
|
||||
enableSSLPinning: function (enable, success, failure) {
|
||||
return exec(success, failure, 'CordovaHttpPlugin', 'enableSSLPinning', [enable]);
|
||||
@@ -232,131 +108,131 @@ var http = {
|
||||
return exec(success, failure, 'CordovaHttpPlugin', 'disableRedirect', [disable]);
|
||||
},
|
||||
validateDomainName: function (validate, success, failure) {
|
||||
failure('advanced-http: "validateDomainName" is no more supported, please see change log for further info');
|
||||
failure(messages.DEPRECATED_VDN);
|
||||
},
|
||||
post: function (url, data, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
data = data || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
data = helpers.getProcessedData(data, internals.dataSerializer);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'post', [url, data, this.dataSerializer, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'post', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
get: function (url, params, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
params = params || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'get', [url, params, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'get', [url, params, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
put: function (url, data, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
data = data || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
data = helpers.getProcessedData(data, internals.dataSerializer);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'put', [url, data, this.dataSerializer, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'put', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
|
||||
patch: function (url, data, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
data = data || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
data = helpers.getProcessedData(data, internals.dataSerializer);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'patch', [url, data, this.dataSerializer, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'patch', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
|
||||
delete: function (url, params, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
params = params || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'delete', [url, params, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'delete', [url, params, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
head: function (url, params, headers, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
params = params || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'head', [url, params, headers, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'head', [url, params, headers, internals.timeoutInSeconds]);
|
||||
},
|
||||
uploadFile: function (url, params, headers, filePath, name, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
params = params || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, success);
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, success);
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, params, headers, filePath, name, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, params, headers, filePath, name, internals.timeoutInSeconds]);
|
||||
},
|
||||
downloadFile: function (url, params, headers, filePath, success, failure) {
|
||||
handleMissingCallbacks(success, failure);
|
||||
helpers.handleMissingCallbacks(success, failure);
|
||||
|
||||
params = params || {};
|
||||
headers = getMergedHeaders(url, headers, this.headers);
|
||||
headers = helpers.getMergedHeaders(url, headers, internals.headers);
|
||||
|
||||
if (!checkHeaders(headers)) {
|
||||
return onInvalidHeader(failure);
|
||||
if (!helpers.checkHeaders(headers)) {
|
||||
return helpers.onInvalidHeader(failure);
|
||||
}
|
||||
|
||||
var onSuccess = injectCookieHandler(url, injectFileEntryHandler(success));
|
||||
var onFail = injectCookieHandler(url, failure);
|
||||
var onSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
|
||||
var onFail = helpers.injectCookieHandler(url, failure);
|
||||
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, params, headers, filePath, this.timeoutInSeconds]);
|
||||
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, params, headers, filePath, internals.timeoutInSeconds]);
|
||||
}
|
||||
};
|
||||
|
||||
angularIntegration.registerService(http);
|
||||
module.exports = http;
|
||||
angularIntegration.registerService(publicInterface);
|
||||
module.exports = publicInterface;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var pluginId = module.id.slice(0, module.id.indexOf('.'));
|
||||
var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
|
||||
var ToughCookie = require(pluginId + '.tough-cookie');
|
||||
var WebStorageCookieStore = require(pluginId + '.local-storage-store');
|
||||
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
|
||||
var cookieHandler = require(pluginId + '.cookie-handler');
|
||||
var messages = require(pluginId + '.messages');
|
||||
|
||||
var validSerializers = [ 'urlencoded', 'json', 'utf8' ];
|
||||
|
||||
module.exports = {
|
||||
b64EncodeUnicode: b64EncodeUnicode,
|
||||
getTypeOf: getTypeOf,
|
||||
checkHeaders: checkHeaders,
|
||||
onInvalidHeader: onInvalidHeader,
|
||||
checkSerializer: checkSerializer,
|
||||
injectCookieHandler: injectCookieHandler,
|
||||
injectFileEntryHandler: injectFileEntryHandler,
|
||||
getMergedHeaders: getMergedHeaders,
|
||||
getProcessedData: getProcessedData,
|
||||
handleMissingCallbacks: handleMissingCallbacks
|
||||
};
|
||||
|
||||
// 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) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
}));
|
||||
}
|
||||
|
||||
function mergeHeaders(globalHeaders, localHeaders) {
|
||||
var globalKeys = Object.keys(globalHeaders);
|
||||
var key;
|
||||
|
||||
for (var i = 0; i < globalKeys.length; i++) {
|
||||
key = globalKeys[i];
|
||||
|
||||
if (!localHeaders.hasOwnProperty(key)) {
|
||||
localHeaders[key] = globalHeaders[key];
|
||||
}
|
||||
}
|
||||
|
||||
return localHeaders;
|
||||
}
|
||||
|
||||
function checkHeaders(headers) {
|
||||
var keys = Object.keys(headers);
|
||||
var key;
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
key = keys[i];
|
||||
|
||||
if (getTypeOf(headers[key]) !== 'String') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function onInvalidHeader(handler) {
|
||||
handler({
|
||||
status: 0,
|
||||
error: messages.HEADER_VALUE_MUST_BE_STRING,
|
||||
headers: {}
|
||||
});
|
||||
}
|
||||
|
||||
function checkSerializer(serializer) {
|
||||
serializer = serializer || '';
|
||||
serializer = serializer.trim().toLowerCase();
|
||||
|
||||
if (validSerializers.indexOf(serializer) > -1) {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
return serializer[0];
|
||||
}
|
||||
|
||||
function resolveCookieString(headers) {
|
||||
var keys = Object.keys(headers || {});
|
||||
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
if (keys[i].match(/^set-cookie$/i)) {
|
||||
return headers[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function createFileEntry(rawEntry) {
|
||||
var entry = new (require('cordova-plugin-file.FileEntry'))();
|
||||
|
||||
entry.isDirectory = rawEntry.isDirectory;
|
||||
entry.isFile = rawEntry.isFile;
|
||||
entry.name = rawEntry.name;
|
||||
entry.fullPath = rawEntry.fullPath;
|
||||
entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
|
||||
entry.nativeURL = rawEntry.nativeURL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
function injectCookieHandler(url, cb) {
|
||||
return function(response) {
|
||||
cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
|
||||
cb(response);
|
||||
}
|
||||
}
|
||||
|
||||
function injectFileEntryHandler(cb) {
|
||||
return function(response) {
|
||||
cb(createFileEntry(response.file));
|
||||
}
|
||||
}
|
||||
|
||||
function getCookieHeader(url) {
|
||||
return { Cookie: cookieHandler.getCookieString(url) };
|
||||
}
|
||||
|
||||
function getMatchingHostHeaders(url, headersList) {
|
||||
var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
|
||||
var domain = matches && matches[1];
|
||||
|
||||
return headersList[domain] || null;
|
||||
}
|
||||
|
||||
function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
|
||||
var globalHeaders = predefinedHeaders['*'] || {};
|
||||
var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
|
||||
var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
|
||||
|
||||
mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
|
||||
mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
|
||||
|
||||
return mergedHeaders;
|
||||
}
|
||||
|
||||
// typeof is not working reliably in JS
|
||||
function getTypeOf(object) {
|
||||
switch (Object.prototype.toString.call(object)) {
|
||||
case '[object Array]':
|
||||
return 'Array';
|
||||
case '[object Boolean]':
|
||||
return 'Boolean';
|
||||
case '[object Function]':
|
||||
return 'Function';
|
||||
case '[object Null]':
|
||||
return 'Null';
|
||||
case '[object Number]':
|
||||
return 'Number';
|
||||
case '[object Object]':
|
||||
return 'Object';
|
||||
case '[object String]':
|
||||
return 'String';
|
||||
case '[object Undefined]':
|
||||
return 'Undefined';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
function getAllowedDataTypes(dataSerializer) {
|
||||
switch (dataSerializer) {
|
||||
case 'utf8':
|
||||
return ['String'];
|
||||
case 'urlencoded':
|
||||
return ['Object'];
|
||||
default:
|
||||
return ['Array', 'Object'];
|
||||
}
|
||||
}
|
||||
|
||||
function getProcessedData(data, dataSerializer) {
|
||||
data = data || {};
|
||||
|
||||
var currentDataType = getTypeOf(data);
|
||||
var allowedDataTypes = getAllowedDataTypes(dataSerializer);
|
||||
|
||||
if (allowedDataTypes.indexOf(currentDataType) === -1) {
|
||||
throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
|
||||
}
|
||||
|
||||
if (dataSerializer === 'utf8') {
|
||||
data = { text: data };
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function handleMissingCallbacks(successFn, failFn) {
|
||||
if (getTypeOf(successFn) !== 'Function') {
|
||||
throw new Error(messages.MANDATORY_SUCCESS);
|
||||
}
|
||||
|
||||
if (getTypeOf(failFn) !== 'Function') {
|
||||
throw new Error(messages.MANDATORY_FAIL);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var pluginId = module.id.slice(0, module.id.indexOf('.'));
|
||||
var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
|
||||
var ToughCookie = require(pluginId + '.tough-cookie');
|
||||
var _ = require(pluginId + '.lodash');
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
|
||||
DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
|
||||
DEPRECATED_VDN: 'advanced-http: "validateDomainName" is no more supported, please see change log for further info',
|
||||
HEADER_VALUE_MUST_BE_STRING: 'advanced-http: header values must be strings',
|
||||
MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
|
||||
MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function'
|
||||
};
|
||||
Reference in New Issue
Block a user