Fixed ajax and fetch interceptor when the data/body sent is not a string, fix #724, updated nodejs test server
This commit is contained in:
parent
bcc5fc68ba
commit
6f356be623
@ -9,6 +9,12 @@
|
||||
- Fixed wrong mapping of `NavigationAction` class on Android for `androidHasGesture` and `androidIsRedirect` properties
|
||||
- Fixed "Pull to refresh creating problem in some webpages on Android" [#719](https://github.com/pichillilorenzo/flutter_inappwebview/issues/719)
|
||||
- Fixed iOS sometimes `scrollView.contentSize` doesn't fit all the `frame.size` available
|
||||
- Fixed ajax and fetch interceptor when the data/body sent is not a string
|
||||
- Fixed "InAppLocalhostServer - Error: type 'List<dynamic>' is not a subtype of type 'List<int>' in type cast" [#724](https://github.com/pichillilorenzo/flutter_inappwebview/issues/724)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- `FetchRequest.body` is a dynamic type now
|
||||
|
||||
## 5.1.0+4
|
||||
|
||||
|
@ -274,4 +274,17 @@ public class Util {
|
||||
public static String replaceAll(String s, String oldString, String newString) {
|
||||
return TextUtils.join(newString, s.split(Pattern.quote(oldString)));
|
||||
}
|
||||
|
||||
public static void log(String tag, String message) {
|
||||
// Split by line, then ensure each line can fit into Log's maximum length.
|
||||
for (int i = 0, length = message.length(); i < length; i++) {
|
||||
int newline = message.indexOf('\n', i);
|
||||
newline = newline != -1 ? newline : length;
|
||||
do {
|
||||
int end = Math.min(newline, i + 4000);
|
||||
Log.d(tag, message.substring(i, end));
|
||||
i = end;
|
||||
} while (i < newline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,46 +183,63 @@ public class InterceptAjaxRequestJS {
|
||||
" this.addEventListener('error', handleEvent);" +
|
||||
" this.addEventListener('abort', handleEvent);" +
|
||||
" this.addEventListener('timeout', handleEvent);" +
|
||||
" var ajaxRequest = {" +
|
||||
" data: data," +
|
||||
" method: this._flutter_inappwebview_method," +
|
||||
" url: this._flutter_inappwebview_url," +
|
||||
" isAsync: this._flutter_inappwebview_isAsync," +
|
||||
" user: this._flutter_inappwebview_user," +
|
||||
" password: this._flutter_inappwebview_password," +
|
||||
" withCredentials: this.withCredentials," +
|
||||
" headers: this._flutter_inappwebview_request_headers," +
|
||||
" responseType: this.responseType" +
|
||||
" };" +
|
||||
" window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) {" +
|
||||
" if (result != null) {" +
|
||||
" switch (result.action) {" +
|
||||
" case 0:" +
|
||||
" self.abort();" +
|
||||
" return;" +
|
||||
" };" +
|
||||
" data = result.data;" +
|
||||
" self.withCredentials = result.withCredentials;" +
|
||||
" if (result.responseType != null) {" +
|
||||
" self.responseType = result.responseType;" +
|
||||
" };" +
|
||||
" for (var header in result.headers) {" +
|
||||
" var value = result.headers[header];" +
|
||||
" var flutter_inappwebview_value = self._flutter_inappwebview_request_headers[header];" +
|
||||
" if (flutter_inappwebview_value == null) {" +
|
||||
" self._flutter_inappwebview_request_headers[header] = value;" +
|
||||
" } else {" +
|
||||
" self._flutter_inappwebview_request_headers[header] += ', ' + value;" +
|
||||
" " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertBodyRequest(data).then(function(data) {" +
|
||||
" var ajaxRequest = {" +
|
||||
" data: data," +
|
||||
" method: self._flutter_inappwebview_method," +
|
||||
" url: self._flutter_inappwebview_url," +
|
||||
" isAsync: self._flutter_inappwebview_isAsync," +
|
||||
" user: self._flutter_inappwebview_user," +
|
||||
" password: self._flutter_inappwebview_password," +
|
||||
" withCredentials: self.withCredentials," +
|
||||
" headers: self._flutter_inappwebview_request_headers," +
|
||||
" responseType: self.responseType" +
|
||||
" };" +
|
||||
" window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) {" +
|
||||
" if (result != null) {" +
|
||||
" switch (result.action) {" +
|
||||
" case 0:" +
|
||||
" self.abort();" +
|
||||
" return;" +
|
||||
" };" +
|
||||
" if (result.data != null && !" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isString(result.data) && result.data.length > 0) {" +
|
||||
" var bodyString = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".arrayBufferToString(result.data);" +
|
||||
" if (" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isBodyFormData(bodyString)) {" +
|
||||
" var formDataContentType = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".getFormDataContentType(bodyString);" +
|
||||
" if (result.headers != null) {" +
|
||||
" result.headers['Content-Type'] = result.headers['Content-Type'] == null ? formDataContentType : result.headers['Content-Type'];" +
|
||||
" } else {" +
|
||||
" result.headers = { 'Content-Type': formDataContentType };" +
|
||||
" }" +
|
||||
" }" +
|
||||
" }" +
|
||||
" if (" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isString(result.data) || result.data == null) {" +
|
||||
" data = result.data;" +
|
||||
" } else if (result.data.length > 0) {" +
|
||||
" data = new Uint8Array(result.data);" +
|
||||
" }" +
|
||||
" self.withCredentials = result.withCredentials;" +
|
||||
" if (result.responseType != null) {" +
|
||||
" self.responseType = result.responseType;" +
|
||||
" };" +
|
||||
" for (var header in result.headers) {" +
|
||||
" var value = result.headers[header];" +
|
||||
" var flutter_inappwebview_value = self._flutter_inappwebview_request_headers[header];" +
|
||||
" if (flutter_inappwebview_value == null) {" +
|
||||
" self._flutter_inappwebview_request_headers[header] = value;" +
|
||||
" } else {" +
|
||||
" self._flutter_inappwebview_request_headers[header] += ', ' + value;" +
|
||||
" }" +
|
||||
" setRequestHeader.call(self, header, value);" +
|
||||
" };" +
|
||||
" if ((self._flutter_inappwebview_method != result.method && result.method != null) || (self._flutter_inappwebview_url != result.url && result.url != null)) {" +
|
||||
" self.abort();" +
|
||||
" self.open(result.method, result.url, result.isAsync, result.user, result.password);" +
|
||||
" return;" +
|
||||
" }" +
|
||||
" setRequestHeader.call(self, header, value);" +
|
||||
" };" +
|
||||
" if ((self._flutter_inappwebview_method != result.method && result.method != null) || (self._flutter_inappwebview_url != result.url && result.url != null)) {" +
|
||||
" self.abort();" +
|
||||
" self.open(result.method, result.url, result.isAsync, result.user, result.password);" +
|
||||
" return;" +
|
||||
" }" +
|
||||
" }" +
|
||||
" send.call(self, data);" +
|
||||
" send.call(self, data);" +
|
||||
" });" +
|
||||
" });" +
|
||||
" } else {" +
|
||||
" send.call(this, data);" +
|
||||
|
@ -21,68 +21,6 @@ public class InterceptFetchRequestJS {
|
||||
" if (fetch == null) {" +
|
||||
" return;" +
|
||||
" }" +
|
||||
" function convertHeadersToJson(headers) {" +
|
||||
" var headersObj = {};" +
|
||||
" for (var header of headers.keys()) {" +
|
||||
" var value = headers.get(header);" +
|
||||
" headersObj[header] = value;" +
|
||||
" }" +
|
||||
" return headersObj;" +
|
||||
" }" +
|
||||
" function convertJsonToHeaders(headersJson) {" +
|
||||
" return new Headers(headersJson);" +
|
||||
" }" +
|
||||
" function convertBodyToArray(body) {" +
|
||||
" return new Response(body).arrayBuffer().then(function(arrayBuffer) {" +
|
||||
" var arr = Array.from(new Uint8Array(arrayBuffer));" +
|
||||
" return arr;" +
|
||||
" })" +
|
||||
" }" +
|
||||
" function convertArrayIntBodyToUint8Array(arrayIntBody) {" +
|
||||
" return new Uint8Array(arrayIntBody);" +
|
||||
" }" +
|
||||
" function convertCredentialsToJson(credentials) {" +
|
||||
" var credentialsObj = {};" +
|
||||
" if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {" +
|
||||
" credentialsObj.type = credentials.type;" +
|
||||
" credentialsObj.id = credentials.id;" +
|
||||
" credentialsObj.name = credentials.name;" +
|
||||
" credentialsObj.protocol = credentials.protocol;" +
|
||||
" credentialsObj.provider = credentials.provider;" +
|
||||
" credentialsObj.iconURL = credentials.iconURL;" +
|
||||
" } else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {" +
|
||||
" credentialsObj.type = credentials.type;" +
|
||||
" credentialsObj.id = credentials.id;" +
|
||||
" credentialsObj.name = credentials.name;" +
|
||||
" credentialsObj.password = credentials.password;" +
|
||||
" credentialsObj.iconURL = credentials.iconURL;" +
|
||||
" } else {" +
|
||||
" credentialsObj.type = 'default';" +
|
||||
" credentialsObj.value = credentials;" +
|
||||
" }" +
|
||||
" }" +
|
||||
" function convertJsonToCredential(credentialsJson) {" +
|
||||
" var credentials;" +
|
||||
" if (window.FederatedCredential != null && credentialsJson.type === 'federated') {" +
|
||||
" credentials = new FederatedCredential({" +
|
||||
" id: credentialsJson.id," +
|
||||
" name: credentialsJson.name," +
|
||||
" protocol: credentialsJson.protocol," +
|
||||
" provider: credentialsJson.provider," +
|
||||
" iconURL: credentialsJson.iconURL" +
|
||||
" });" +
|
||||
" } else if (window.PasswordCredential != null && credentialsJson.type === 'password') {" +
|
||||
" credentials = new PasswordCredential({" +
|
||||
" id: credentialsJson.id," +
|
||||
" name: credentialsJson.name," +
|
||||
" password: credentialsJson.password," +
|
||||
" iconURL: credentialsJson.iconURL" +
|
||||
" });" +
|
||||
" } else {" +
|
||||
" credentials = credentialsJson;" +
|
||||
" }" +
|
||||
" return credentials;" +
|
||||
" }" +
|
||||
" window.fetch = async function(resource, init) {" +
|
||||
" var w = (window.top == null || window.top === window) ? window : window.top;" +
|
||||
" if (w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_FETCH_REQUEST_JS_SOURCE + " == null || w." + FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_FETCH_REQUEST_JS_SOURCE + " == true) {" +
|
||||
@ -114,7 +52,7 @@ public class InterceptFetchRequestJS {
|
||||
" fetchRequest.integrity = resource.integrity;" +
|
||||
" fetchRequest.keepalive = resource.keepalive;" +
|
||||
" } else {" +
|
||||
" fetchRequest.url = resource;" +
|
||||
" fetchRequest.url = resource != null ? resource.toString() : null;" +
|
||||
" if (init != null) {" +
|
||||
" fetchRequest.method = init.method;" +
|
||||
" fetchRequest.headers = init.headers;" +
|
||||
@ -130,10 +68,10 @@ public class InterceptFetchRequestJS {
|
||||
" }" +
|
||||
" }" +
|
||||
" if (fetchRequest.headers instanceof Headers) {" +
|
||||
" fetchRequest.headers = convertHeadersToJson(fetchRequest.headers);" +
|
||||
" fetchRequest.headers = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertHeadersToJson(fetchRequest.headers);" +
|
||||
" }" +
|
||||
" fetchRequest.credentials = convertCredentialsToJson(fetchRequest.credentials);" +
|
||||
" return convertBodyToArray(fetchRequest.body).then(function(body) {" +
|
||||
" fetchRequest.credentials = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertCredentialsToJson(fetchRequest.credentials);" +
|
||||
" return " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertBodyRequest(fetchRequest.body).then(function(body) {" +
|
||||
" fetchRequest.body = body;" +
|
||||
" return window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) {" +
|
||||
" if (result != null) {" +
|
||||
@ -150,7 +88,18 @@ public class InterceptFetchRequestJS {
|
||||
" controller.abort();" +
|
||||
" break;" +
|
||||
" }" +
|
||||
" resource = (result.url != null) ? result.url : resource;" +
|
||||
" if (result.body != null && !" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isString(result.body) && result.body.length > 0) {" +
|
||||
" var bodyString = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".arrayBufferToString(result.body);" +
|
||||
" if (" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isBodyFormData(bodyString)) {" +
|
||||
" var formDataContentType = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".getFormDataContentType(bodyString);" +
|
||||
" if (result.headers != null) {" +
|
||||
" result.headers['Content-Type'] = result.headers['Content-Type'] == null ? formDataContentType : result.headers['Content-Type'];" +
|
||||
" } else {" +
|
||||
" result.headers = { 'Content-Type': formDataContentType };" +
|
||||
" }" +
|
||||
" }" +
|
||||
" }" +
|
||||
" resource = result.url;" +
|
||||
" if (init == null) {" +
|
||||
" init = {};" +
|
||||
" }" +
|
||||
@ -158,16 +107,18 @@ public class InterceptFetchRequestJS {
|
||||
" init.method = result.method;" +
|
||||
" }" +
|
||||
" if (result.headers != null && Object.keys(result.headers).length > 0) {" +
|
||||
" init.headers = convertJsonToHeaders(result.headers);" +
|
||||
" init.headers = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertJsonToHeaders(result.headers);" +
|
||||
" }" +
|
||||
" if (result.body != null && result.body.length > 0) {" +
|
||||
" init.body = convertArrayIntBodyToUint8Array(result.body);" +
|
||||
" if (" + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".isString(result.body) || result.body == null) {" +
|
||||
" init.body = result.body;" +
|
||||
" } else if (result.body.length > 0) {" +
|
||||
" init.body = new Uint8Array(result.body);" +
|
||||
" }" +
|
||||
" if (result.mode != null && result.mode.length > 0) {" +
|
||||
" init.mode = result.mode;" +
|
||||
" }" +
|
||||
" if (result.credentials != null) {" +
|
||||
" init.credentials = convertJsonToCredential(result.credentials);" +
|
||||
" init.credentials = " + JavaScriptBridgeJS.JAVASCRIPT_UTIL_VAR_NAME + ".convertJsonToCredential(result.credentials);" +
|
||||
" }" +
|
||||
" if (result.cache != null && result.cache.length > 0) {" +
|
||||
" init.cache = result.cache;" +
|
||||
|
@ -14,6 +14,203 @@ public class JavaScriptBridgeJS {
|
||||
true
|
||||
);
|
||||
|
||||
public static final String JAVASCRIPT_UTIL_VAR_NAME = "window." + JAVASCRIPT_BRIDGE_NAME + "._Util";
|
||||
|
||||
public static final String UTIL_JS_SOURCE = JAVASCRIPT_UTIL_VAR_NAME + " = {" +
|
||||
" support: {" +
|
||||
" searchParams: 'URLSearchParams' in window," +
|
||||
" iterable: 'Symbol' in window && 'iterator' in Symbol," +
|
||||
" blob:" +
|
||||
" 'FileReader' in window &&" +
|
||||
" 'Blob' in window &&" +
|
||||
" (function() {" +
|
||||
" try {" +
|
||||
" new Blob();" +
|
||||
" return true;" +
|
||||
" } catch (e) {" +
|
||||
" return false;" +
|
||||
" }" +
|
||||
" })()," +
|
||||
" formData: 'FormData' in window," +
|
||||
" arrayBuffer: 'ArrayBuffer' in window" +
|
||||
" }," +
|
||||
" isDataView: function(obj) {" +
|
||||
" return obj && DataView.prototype.isPrototypeOf(obj);" +
|
||||
" }," +
|
||||
" fileReaderReady: function(reader) {" +
|
||||
" return new Promise(function(resolve, reject) {" +
|
||||
" reader.onload = function() {" +
|
||||
" resolve(reader.result);" +
|
||||
" };" +
|
||||
" reader.onerror = function() {" +
|
||||
" reject(reader.error);" +
|
||||
" };" +
|
||||
" });" +
|
||||
" }," +
|
||||
" readBlobAsArrayBuffer: function(blob) {" +
|
||||
" var reader = new FileReader();" +
|
||||
" var promise = " + JAVASCRIPT_UTIL_VAR_NAME + ".fileReaderReady(reader);" +
|
||||
" reader.readAsArrayBuffer(blob);" +
|
||||
" return promise;" +
|
||||
" }," +
|
||||
" convertBodyToArrayBuffer: function(body) {" +
|
||||
" var viewClasses = [" +
|
||||
" '[object Int8Array]'," +
|
||||
" '[object Uint8Array]'," +
|
||||
" '[object Uint8ClampedArray]'," +
|
||||
" '[object Int16Array]'," +
|
||||
" '[object Uint16Array]'," +
|
||||
" '[object Int32Array]'," +
|
||||
" '[object Uint32Array]'," +
|
||||
" '[object Float32Array]'," +
|
||||
" '[object Float64Array]'" +
|
||||
" ];" +
|
||||
" var isArrayBufferView = null;" +
|
||||
" if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.arrayBuffer) {" +
|
||||
" isArrayBufferView =" +
|
||||
" ArrayBuffer.isView ||" +
|
||||
" function(obj) {" +
|
||||
" return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;" +
|
||||
" };" +
|
||||
" }" +
|
||||
" var bodyUsed = false;" +
|
||||
" this._bodyInit = body;" +
|
||||
" if (!body) {" +
|
||||
" this._bodyText = '';" +
|
||||
" } else if (typeof body === 'string') {" +
|
||||
" this._bodyText = body;" +
|
||||
" } else if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.blob && Blob.prototype.isPrototypeOf(body)) {" +
|
||||
" this._bodyBlob = body;" +
|
||||
" } else if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.formData && FormData.prototype.isPrototypeOf(body)) {" +
|
||||
" this._bodyFormData = body;" +
|
||||
" } else if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {" +
|
||||
" this._bodyText = body.toString();" +
|
||||
" } else if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.arrayBuffer && " + JAVASCRIPT_UTIL_VAR_NAME + ".support.blob && " + JAVASCRIPT_UTIL_VAR_NAME + ".isDataView(body)) {" +
|
||||
" this._bodyArrayBuffer = bufferClone(body.buffer);" +
|
||||
" this._bodyInit = new Blob([this._bodyArrayBuffer]);" +
|
||||
" } else if (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {" +
|
||||
" this._bodyArrayBuffer = bufferClone(body);" +
|
||||
" } else {" +
|
||||
" this._bodyText = body = Object.prototype.toString.call(body);" +
|
||||
" }" +
|
||||
" this.blob = function () {" +
|
||||
" if (bodyUsed) {" +
|
||||
" return Promise.reject(new TypeError('Already read'));" +
|
||||
" }" +
|
||||
" bodyUsed = true;" +
|
||||
" if (this._bodyBlob) {" +
|
||||
" return Promise.resolve(this._bodyBlob);" +
|
||||
" } else if (this._bodyArrayBuffer) {" +
|
||||
" return Promise.resolve(new Blob([this._bodyArrayBuffer]));" +
|
||||
" } else if (this._bodyFormData) {" +
|
||||
" throw new Error('could not read FormData body as blob');" +
|
||||
" } else {" +
|
||||
" return Promise.resolve(new Blob([this._bodyText]));" +
|
||||
" }" +
|
||||
" };" +
|
||||
" if (this._bodyArrayBuffer) {" +
|
||||
" if (bodyUsed) {" +
|
||||
" return Promise.reject(new TypeError('Already read'));" +
|
||||
" }" +
|
||||
" bodyUsed = true;" +
|
||||
" if (ArrayBuffer.isView(this._bodyArrayBuffer)) {" +
|
||||
" return Promise.resolve(" +
|
||||
" this._bodyArrayBuffer.buffer.slice(" +
|
||||
" this._bodyArrayBuffer.byteOffset," +
|
||||
" this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength" +
|
||||
" )" +
|
||||
" );" +
|
||||
" } else {" +
|
||||
" return Promise.resolve(this._bodyArrayBuffer);" +
|
||||
" }" +
|
||||
" }" +
|
||||
" return this.blob().then(" + JAVASCRIPT_UTIL_VAR_NAME + ".readBlobAsArrayBuffer);" +
|
||||
" }," +
|
||||
" isString: function(variable) {" +
|
||||
" return typeof variable === 'string' || variable instanceof String;" +
|
||||
" }," +
|
||||
" convertBodyRequest: function(body) {" +
|
||||
" if (body == null) {" +
|
||||
" return new Promise((resolve, reject) => resolve(null));" +
|
||||
" }" +
|
||||
" if (" + JAVASCRIPT_UTIL_VAR_NAME + ".isString(body) || (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.searchParams && body instanceof URLSearchParams)) {" +
|
||||
" return new Promise((resolve, reject) => resolve(body.toString()));" +
|
||||
" }" +
|
||||
" if (window.Response != null) {" +
|
||||
" return new Response(body).arrayBuffer().then(function(arrayBuffer) {" +
|
||||
" return Array.from(new Uint8Array(arrayBuffer));" +
|
||||
" });" +
|
||||
" }" +
|
||||
" return " + JAVASCRIPT_UTIL_VAR_NAME + ".convertBodyToArrayBuffer(body).then(function(arrayBuffer) {" +
|
||||
" return Array.from(new Uint8Array(arrayBuffer));" +
|
||||
" });" +
|
||||
" }," +
|
||||
" arrayBufferToString: function(arrayBuffer) {" +
|
||||
" return String.fromCharCode.apply(String, arrayBuffer);" +
|
||||
" }," +
|
||||
" isBodyFormData: function(bodyString) {" +
|
||||
" return bodyString.indexOf('------WebKitFormBoundary') >= 0;" +
|
||||
" }," +
|
||||
" getFormDataContentType: function(bodyString) {" +
|
||||
" var boundary = bodyString.substr(2, 40);" +
|
||||
" return 'multipart/form-data; boundary=' + boundary;" +
|
||||
" }," +
|
||||
" convertHeadersToJson: function(headers) {" +
|
||||
" var headersObj = {};" +
|
||||
" for (var header of headers.keys()) {" +
|
||||
" var value = headers.get(header);" +
|
||||
" headersObj[header] = value;" +
|
||||
" }" +
|
||||
" return headersObj;" +
|
||||
" }," +
|
||||
" convertJsonToHeaders: function(headersJson) {" +
|
||||
" return new Headers(headersJson);" +
|
||||
" }," +
|
||||
" convertCredentialsToJson: function(credentials) {" +
|
||||
" var credentialsObj = {};" +
|
||||
" if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {" +
|
||||
" credentialsObj.type = credentials.type;" +
|
||||
" credentialsObj.id = credentials.id;" +
|
||||
" credentialsObj.name = credentials.name;" +
|
||||
" credentialsObj.protocol = credentials.protocol;" +
|
||||
" credentialsObj.provider = credentials.provider;" +
|
||||
" credentialsObj.iconURL = credentials.iconURL;" +
|
||||
" } else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {" +
|
||||
" credentialsObj.type = credentials.type;" +
|
||||
" credentialsObj.id = credentials.id;" +
|
||||
" credentialsObj.name = credentials.name;" +
|
||||
" credentialsObj.password = credentials.password;" +
|
||||
" credentialsObj.iconURL = credentials.iconURL;" +
|
||||
" } else {" +
|
||||
" credentialsObj.type = 'default';" +
|
||||
" credentialsObj.value = credentials;" +
|
||||
" }" +
|
||||
" return credentialsObj;" +
|
||||
" }," +
|
||||
" convertJsonToCredential: function(credentialsJson) {" +
|
||||
" var credentials;" +
|
||||
" if (window.FederatedCredential != null && credentialsJson.type === 'federated') {" +
|
||||
" credentials = new FederatedCredential({" +
|
||||
" id: credentialsJson.id," +
|
||||
" name: credentialsJson.name," +
|
||||
" protocol: credentialsJson.protocol," +
|
||||
" provider: credentialsJson.provider," +
|
||||
" iconURL: credentialsJson.iconURL" +
|
||||
" });" +
|
||||
" } else if (window.PasswordCredential != null && credentialsJson.type === 'password') {" +
|
||||
" credentials = new PasswordCredential({" +
|
||||
" id: credentialsJson.id," +
|
||||
" name: credentialsJson.name," +
|
||||
" password: credentialsJson.password," +
|
||||
" iconURL: credentialsJson.iconURL" +
|
||||
" });" +
|
||||
" } else {" +
|
||||
" credentials = credentialsJson.value == null ? undefined : credentialsJson.value;" +
|
||||
" }" +
|
||||
" return credentials;" +
|
||||
" }" +
|
||||
"};";
|
||||
|
||||
public static final String JAVASCRIPT_BRIDGE_JS_SOURCE = "if (window.top == null || window.top === window) {" +
|
||||
" window." + JAVASCRIPT_BRIDGE_NAME + ".callHandler = function() {" +
|
||||
" var _callHandlerID = setTimeout(function(){});" +
|
||||
@ -30,8 +227,9 @@ public class JavaScriptBridgeJS {
|
||||
" return new Promise(function(resolve, reject) {" +
|
||||
" window.top." + JAVASCRIPT_BRIDGE_NAME + "[_callHandlerID] = resolve;" +
|
||||
" });" +
|
||||
" };"+
|
||||
"}";
|
||||
" };" +
|
||||
"}" +
|
||||
UTIL_JS_SOURCE;
|
||||
|
||||
public static final String PLATFORM_READY_JS_SOURCE = "(function() {" +
|
||||
" if ((window.top == null || window.top === window) && window." + JAVASCRIPT_BRIDGE_NAME + "._platformReady == null) {" +
|
||||
|
@ -1706,20 +1706,21 @@ void main() {
|
||||
skip: !Platform.isAndroid,
|
||||
);
|
||||
|
||||
testWidgets('intercept ajax request', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer shouldInterceptAjaxPostRequestCompleter =
|
||||
Completer<void>();
|
||||
final Completer<Map<String, dynamic>> onAjaxReadyStateChangeCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<Map<String, dynamic>> onAjaxProgressCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
group('intercept ajax request', () {
|
||||
testWidgets('send string data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer shouldInterceptAjaxPostRequestCompleter =
|
||||
Completer<void>();
|
||||
final Completer<Map<String, dynamic>> onAjaxReadyStateChangeCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<Map<String, dynamic>> onAjaxProgressCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@ -1736,117 +1737,347 @@ void main() {
|
||||
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
|
||||
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhttp.send("firstname=Foo&lastname=Bar");
|
||||
|
||||
var xhttp2 = new XMLHttpRequest();
|
||||
xhttp2.open("GET", "http://${environment["NODE_SERVER_IP"]}:8082/test-download-file");
|
||||
xhttp2.send();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.url!.toString().endsWith("/test-ajax-post")) {
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
|
||||
expect(ajaxRequest.data, "firstname=Foo&lastname=Bar");
|
||||
|
||||
ajaxRequest.responseType = 'json';
|
||||
ajaxRequest.data = "firstname=Foo2&lastname=Bar2";
|
||||
shouldInterceptAjaxPostRequestCompleter.complete(controller);
|
||||
}
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE &&
|
||||
ajaxRequest.status == 200 &&
|
||||
ajaxRequest.url!.toString().endsWith("/test-ajax-post")) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxReadyStateChangeCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.event!.type == AjaxRequestEventType.LOAD &&
|
||||
ajaxRequest.url!.toString().endsWith("/test-ajax-post")) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxProgressCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE &&
|
||||
ajaxRequest.status == 200) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxReadyStateChangeCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.event!.type == AjaxRequestEventType.LOAD) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxProgressCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
await shouldInterceptAjaxPostRequestCompleter.future;
|
||||
final Map<String, dynamic> onAjaxReadyStateChangeValue =
|
||||
await onAjaxReadyStateChangeCompleter.future;
|
||||
final Map<String, dynamic> onAjaxProgressValue =
|
||||
await onAjaxProgressCompleter.future;
|
||||
await shouldInterceptAjaxPostRequestCompleter.future;
|
||||
final Map<String, dynamic> onAjaxReadyStateChangeValue =
|
||||
await onAjaxReadyStateChangeCompleter.future;
|
||||
final Map<String, dynamic> onAjaxProgressValue =
|
||||
await onAjaxProgressCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(onAjaxReadyStateChangeValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(
|
||||
onAjaxProgressValue, {'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(onAjaxReadyStateChangeValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(
|
||||
onAjaxProgressValue, {'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send json data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer shouldInterceptAjaxPostRequestCompleter =
|
||||
Completer<void>();
|
||||
final Completer<Map<String, dynamic>> onAjaxReadyStateChangeCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<Map<String, dynamic>> onAjaxProgressCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewAjaxTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewAjaxTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var jsonData = {
|
||||
firstname: 'Foo',
|
||||
lastname: 'Bar'
|
||||
};
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
|
||||
xhttp.setRequestHeader("Content-type", "application/json");
|
||||
xhttp.send(JSON.stringify(jsonData));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
|
||||
expect(ajaxRequest.data, '{"firstname":"Foo","lastname":"Bar"}');
|
||||
|
||||
ajaxRequest.responseType = 'json';
|
||||
ajaxRequest.data = "{'firstname': 'Foo2', 'lastname': 'Bar2'}";
|
||||
shouldInterceptAjaxPostRequestCompleter.complete(controller);
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE &&
|
||||
ajaxRequest.status == 200) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxReadyStateChangeCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.event!.type == AjaxRequestEventType.LOAD) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxProgressCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await shouldInterceptAjaxPostRequestCompleter.future;
|
||||
final Map<String, dynamic> onAjaxReadyStateChangeValue =
|
||||
await onAjaxReadyStateChangeCompleter.future;
|
||||
final Map<String, dynamic> onAjaxProgressValue =
|
||||
await onAjaxProgressCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(onAjaxReadyStateChangeValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(
|
||||
onAjaxProgressValue, {'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send URLSearchParams data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer shouldInterceptAjaxPostRequestCompleter =
|
||||
Completer<void>();
|
||||
final Completer<Map<String, dynamic>> onAjaxReadyStateChangeCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<Map<String, dynamic>> onAjaxProgressCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewAjaxTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewAjaxTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var paramsString = "firstname=Foo&lastname=Bar";
|
||||
var searchParams = new URLSearchParams(paramsString);
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
|
||||
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhttp.send(searchParams);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
|
||||
expect(ajaxRequest.data, "firstname=Foo&lastname=Bar");
|
||||
|
||||
ajaxRequest.responseType = 'json';
|
||||
ajaxRequest.data = "firstname=Foo2&lastname=Bar2";
|
||||
shouldInterceptAjaxPostRequestCompleter.complete(controller);
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE &&
|
||||
ajaxRequest.status == 200) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxReadyStateChangeCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.event!.type == AjaxRequestEventType.LOAD) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxProgressCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await shouldInterceptAjaxPostRequestCompleter.future;
|
||||
final Map<String, dynamic> onAjaxReadyStateChangeValue =
|
||||
await onAjaxReadyStateChangeCompleter.future;
|
||||
final Map<String, dynamic> onAjaxProgressValue =
|
||||
await onAjaxProgressCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(onAjaxReadyStateChangeValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(
|
||||
onAjaxProgressValue, {'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send FormData', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer shouldInterceptAjaxPostRequestCompleter =
|
||||
Completer<void>();
|
||||
final Completer<Map<String, dynamic>> onAjaxReadyStateChangeCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<Map<String, dynamic>> onAjaxProgressCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewAjaxTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewAjaxTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var formData = new FormData();
|
||||
formData.append('firstname', 'Foo');
|
||||
formData.append('lastname', 'Bar');
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST", "http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post");
|
||||
xhttp.send(formData);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptAjaxRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
|
||||
expect(ajaxRequest.data, isNotNull);
|
||||
|
||||
var body = ajaxRequest.data.cast<int>();
|
||||
var bodyString = String.fromCharCodes(body);
|
||||
expect(bodyString.indexOf("WebKitFormBoundary") >= 0, true);
|
||||
|
||||
ajaxRequest.data = utf8.encode(bodyString.replaceFirst("Foo", "Foo2").replaceFirst("Bar", "Bar2"));
|
||||
ajaxRequest.responseType = 'json';
|
||||
shouldInterceptAjaxPostRequestCompleter.complete(controller);
|
||||
return ajaxRequest;
|
||||
},
|
||||
onAjaxReadyStateChange: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.readyState == AjaxRequestReadyState.DONE &&
|
||||
ajaxRequest.status == 200) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxReadyStateChangeCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
onAjaxProgress: (controller, ajaxRequest) async {
|
||||
if (ajaxRequest.event!.type == AjaxRequestEventType.LOAD) {
|
||||
Map<String, dynamic> res = ajaxRequest.response;
|
||||
onAjaxProgressCompleter.complete(res);
|
||||
}
|
||||
return AjaxRequestAction.PROCEED;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await shouldInterceptAjaxPostRequestCompleter.future;
|
||||
final Map<String, dynamic> onAjaxReadyStateChangeValue =
|
||||
await onAjaxReadyStateChangeCompleter.future;
|
||||
final Map<String, dynamic> onAjaxProgressValue =
|
||||
await onAjaxProgressCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(onAjaxReadyStateChangeValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
expect(
|
||||
mapEquals(
|
||||
onAjaxProgressValue, {'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('Content Blocker', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<void> pageLoaded = Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialUrlRequest:
|
||||
URLRequest(url: Uri.parse('https://flutter.dev/')),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform:
|
||||
InAppWebViewOptions(clearCache: true, contentBlockers: [
|
||||
ContentBlocker(
|
||||
trigger:
|
||||
ContentBlockerTrigger(urlFilter: ".*", resourceType: [
|
||||
ContentBlockerTriggerResourceType.IMAGE,
|
||||
ContentBlockerTriggerResourceType.STYLE_SHEET
|
||||
], ifTopUrl: [
|
||||
"https://flutter.dev/"
|
||||
]),
|
||||
action: ContentBlockerAction(
|
||||
type: ContentBlockerActionType.BLOCK))
|
||||
])),
|
||||
onLoadStop: (controller, url) {
|
||||
pageLoaded.complete();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
await expectLater(pageLoaded.future, completes);
|
||||
});
|
||||
|
||||
testWidgets('intercept fetch request', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> fetchGetCompleter = Completer<String>();
|
||||
final Completer<Map<String, dynamic>> fetchPostCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<void> shouldInterceptFetchPostRequestCompleter =
|
||||
Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
group('intercept fetch request', () {
|
||||
testWidgets('send string data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> fetchGetCompleter = Completer<String>();
|
||||
final Completer<Map<String, dynamic>> fetchPostCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<void> shouldInterceptFetchPostRequestCompleter =
|
||||
Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@ -1859,21 +2090,12 @@ void main() {
|
||||
<h1>InAppWebViewFetchTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
fetch(new Request("http://${environment["NODE_SERVER_IP"]}:8082/test-download-file")).then(function(response) {
|
||||
window.flutter_inappwebview.callHandler('fetchGet', response.status);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchGet', "ERROR: " + error);
|
||||
});
|
||||
|
||||
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
firstname: 'Foo',
|
||||
lastname: 'Bar'
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: "firstname=Foo&lastname=Bar"
|
||||
}).then(function(response) {
|
||||
response.json().then(function(value) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', value);
|
||||
@ -1888,52 +2110,338 @@ void main() {
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchPost",
|
||||
callback: (args) {
|
||||
fetchPostCompleter
|
||||
.complete(args[0] as Map<String, dynamic>);
|
||||
});
|
||||
},
|
||||
shouldInterceptFetchRequest: (controller, fetchRequest) async {
|
||||
expect(fetchRequest.body, "firstname=Foo&lastname=Bar");
|
||||
|
||||
fetchRequest.body = "firstname=Foo2&lastname=Bar2";
|
||||
shouldInterceptFetchPostRequestCompleter.complete();
|
||||
return fetchRequest;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var fetchGetCompleterValue = await fetchGetCompleter.future;
|
||||
expect(fetchGetCompleterValue, '200');
|
||||
|
||||
await shouldInterceptFetchPostRequestCompleter.future;
|
||||
var fetchPostCompleterValue = await fetchPostCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(fetchPostCompleterValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send json data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> fetchGetCompleter = Completer<String>();
|
||||
final Completer<Map<String, dynamic>> fetchPostCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<void> shouldInterceptFetchPostRequestCompleter =
|
||||
Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewFetchTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewFetchTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var jsonData = {
|
||||
firstname: 'Foo',
|
||||
lastname: 'Bar'
|
||||
};
|
||||
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(jsonData)
|
||||
}).then(function(response) {
|
||||
response.json().then(function(value) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', value);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchPost",
|
||||
callback: (args) {
|
||||
fetchPostCompleter
|
||||
.complete(args[0] as Map<String, dynamic>);
|
||||
});
|
||||
},
|
||||
shouldInterceptFetchRequest: (controller, fetchRequest) async {
|
||||
expect(fetchRequest.body, '{"firstname":"Foo","lastname":"Bar"}');
|
||||
|
||||
fetchRequest.body = "{'firstname': 'Foo2', 'lastname': 'Bar2'}";
|
||||
shouldInterceptFetchPostRequestCompleter.complete();
|
||||
return fetchRequest;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var fetchGetCompleterValue = await fetchGetCompleter.future;
|
||||
expect(fetchGetCompleterValue, '200');
|
||||
|
||||
await shouldInterceptFetchPostRequestCompleter.future;
|
||||
var fetchPostCompleterValue = await fetchPostCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(fetchPostCompleterValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send URLSearchParams data', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> fetchGetCompleter = Completer<String>();
|
||||
final Completer<Map<String, dynamic>> fetchPostCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<void> shouldInterceptFetchPostRequestCompleter =
|
||||
Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewFetchTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewFetchTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var paramsString = "firstname=Foo&lastname=Bar";
|
||||
var searchParams = new URLSearchParams(paramsString);
|
||||
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: searchParams
|
||||
}).then(function(response) {
|
||||
response.json().then(function(value) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', value);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchPost",
|
||||
callback: (args) {
|
||||
fetchPostCompleter
|
||||
.complete(args[0] as Map<String, dynamic>);
|
||||
});
|
||||
},
|
||||
shouldInterceptFetchRequest: (controller, fetchRequest) async {
|
||||
expect(fetchRequest.body, "firstname=Foo&lastname=Bar");
|
||||
|
||||
fetchRequest.body = "firstname=Foo2&lastname=Bar2";
|
||||
shouldInterceptFetchPostRequestCompleter.complete();
|
||||
return fetchRequest;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var fetchGetCompleterValue = await fetchGetCompleter.future;
|
||||
expect(fetchGetCompleterValue, '200');
|
||||
|
||||
await shouldInterceptFetchPostRequestCompleter.future;
|
||||
var fetchPostCompleterValue = await fetchPostCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(fetchPostCompleterValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
|
||||
testWidgets('send FormData', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> fetchGetCompleter = Completer<String>();
|
||||
final Completer<Map<String, dynamic>> fetchPostCompleter =
|
||||
Completer<Map<String, dynamic>>();
|
||||
final Completer<void> shouldInterceptFetchPostRequestCompleter =
|
||||
Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialData: InAppWebViewInitialData(data: """
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>InAppWebViewFetchTest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>InAppWebViewFetchTest</h1>
|
||||
<script>
|
||||
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
|
||||
var formData = new FormData();
|
||||
formData.append('firstname', 'Foo');
|
||||
formData.append('lastname', 'Bar');
|
||||
fetch("http://${environment["NODE_SERVER_IP"]}:8082/test-ajax-post", {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then(function(response) {
|
||||
response.json().then(function(value) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', value);
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
}).catch(function(error) {
|
||||
window.flutter_inappwebview.callHandler('fetchPost', "ERROR: " + error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"""),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
useShouldInterceptFetchRequest: true,
|
||||
)),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchPost",
|
||||
callback: (args) {
|
||||
fetchPostCompleter
|
||||
.complete(args[0] as Map<String, dynamic>);
|
||||
});
|
||||
},
|
||||
shouldInterceptFetchRequest: (controller, fetchRequest) async {
|
||||
expect(fetchRequest.body, isNotNull);
|
||||
|
||||
var body = fetchRequest.body.cast<int>();
|
||||
var bodyString = String.fromCharCodes(body);
|
||||
expect(bodyString.indexOf("WebKitFormBoundary") >= 0, true);
|
||||
|
||||
fetchRequest.body = utf8.encode(bodyString.replaceFirst("Foo", "Foo2").replaceFirst("Bar", "Bar2"));
|
||||
shouldInterceptFetchPostRequestCompleter.complete();
|
||||
return fetchRequest;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var fetchGetCompleterValue = await fetchGetCompleter.future;
|
||||
expect(fetchGetCompleterValue, '200');
|
||||
|
||||
await shouldInterceptFetchPostRequestCompleter.future;
|
||||
var fetchPostCompleterValue = await fetchPostCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(fetchPostCompleterValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('Content Blocker', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<void> pageLoaded = Completer<void>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialUrlRequest:
|
||||
URLRequest(url: Uri.parse('https://flutter.dev/')),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchGet",
|
||||
callback: (args) {
|
||||
fetchGetCompleter.complete(args[0].toString());
|
||||
});
|
||||
|
||||
controller.addJavaScriptHandler(
|
||||
handlerName: "fetchPost",
|
||||
callback: (args) {
|
||||
fetchPostCompleter
|
||||
.complete(args[0] as Map<String, dynamic>);
|
||||
});
|
||||
},
|
||||
shouldInterceptFetchRequest: (controller, fetchRequest) async {
|
||||
if (fetchRequest.url!.toString().endsWith("/test-ajax-post")) {
|
||||
fetchRequest.body = utf8.encode("""{
|
||||
"firstname": "Foo2",
|
||||
"lastname": "Bar2"
|
||||
}
|
||||
""") as Uint8List;
|
||||
shouldInterceptFetchPostRequestCompleter.complete();
|
||||
}
|
||||
return fetchRequest;
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform:
|
||||
InAppWebViewOptions(clearCache: true, contentBlockers: [
|
||||
ContentBlocker(
|
||||
trigger:
|
||||
ContentBlockerTrigger(urlFilter: ".*", resourceType: [
|
||||
ContentBlockerTriggerResourceType.IMAGE,
|
||||
ContentBlockerTriggerResourceType.STYLE_SHEET
|
||||
], ifTopUrl: [
|
||||
"https://flutter.dev/"
|
||||
]),
|
||||
action: ContentBlockerAction(
|
||||
type: ContentBlockerActionType.BLOCK))
|
||||
])),
|
||||
onLoadStop: (controller, url) {
|
||||
pageLoaded.complete();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var fetchGetCompleterValue = await fetchGetCompleter.future;
|
||||
expect(fetchGetCompleterValue, '200');
|
||||
|
||||
await shouldInterceptFetchPostRequestCompleter.future;
|
||||
var fetchPostCompleterValue = await fetchPostCompleter.future;
|
||||
|
||||
expect(
|
||||
mapEquals(fetchPostCompleterValue,
|
||||
{'firstname': 'Foo2', 'lastname': 'Bar2'}),
|
||||
true);
|
||||
await expectLater(pageLoaded.future, completes);
|
||||
});
|
||||
|
||||
testWidgets('Http Auth Credential Database', (WidgetTester tester) async {
|
||||
@ -5001,4 +5509,37 @@ setTimeout(function() {
|
||||
expect(chromeSafariBrowser.isOpened(), false);
|
||||
});
|
||||
});
|
||||
|
||||
group('InAppLocalhostServer', () {
|
||||
final InAppLocalhostServer localhostServer = InAppLocalhostServer();
|
||||
|
||||
setUpAll(() async {
|
||||
localhostServer.start();
|
||||
});
|
||||
|
||||
testWidgets('load asset file', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: InAppWebView(
|
||||
key: GlobalKey(),
|
||||
initialUrlRequest:
|
||||
URLRequest(url: Uri.parse('http://localhost:8080/test_assets/index.html')),
|
||||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
final InAppWebViewController controller =
|
||||
await controllerCompleter.future;
|
||||
final String? currentUrl = (await controller.getUrl())?.toString();
|
||||
expect(currentUrl, 'http://localhost:8080/test_assets/index.html');
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
localhostServer.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -183,46 +183,65 @@ let INTERCEPT_AJAX_REQUEST_JS_SOURCE = """
|
||||
this.addEventListener('error', handleEvent);
|
||||
this.addEventListener('abort', handleEvent);
|
||||
this.addEventListener('timeout', handleEvent);
|
||||
var ajaxRequest = {
|
||||
data: data,
|
||||
method: this._flutter_inappwebview_method,
|
||||
url: this._flutter_inappwebview_url,
|
||||
isAsync: this._flutter_inappwebview_isAsync,
|
||||
user: this._flutter_inappwebview_user,
|
||||
password: this._flutter_inappwebview_password,
|
||||
withCredentials: this.withCredentials,
|
||||
headers: this._flutter_inappwebview_request_headers,
|
||||
responseType: this.responseType
|
||||
};
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) {
|
||||
if (result != null) {
|
||||
switch (result.action) {
|
||||
case 0:
|
||||
self.abort();
|
||||
return;
|
||||
\(JAVASCRIPT_UTIL_VAR_NAME).convertBodyRequest(data).then(function(data) {
|
||||
var ajaxRequest = {
|
||||
data: data,
|
||||
method: self._flutter_inappwebview_method,
|
||||
url: self._flutter_inappwebview_url,
|
||||
isAsync: self._flutter_inappwebview_isAsync,
|
||||
user: self._flutter_inappwebview_user,
|
||||
password: self._flutter_inappwebview_password,
|
||||
withCredentials: self.withCredentials,
|
||||
headers: self._flutter_inappwebview_request_headers,
|
||||
responseType: self.responseType
|
||||
};
|
||||
data = result.data;
|
||||
self.withCredentials = result.withCredentials;
|
||||
if (result.responseType != null) {
|
||||
self.responseType = result.responseType;
|
||||
};
|
||||
for (var header in result.headers) {
|
||||
var value = result.headers[header];
|
||||
var flutter_inappwebview_value = self._flutter_inappwebview_request_headers[header];
|
||||
if (flutter_inappwebview_value == null) {
|
||||
self._flutter_inappwebview_request_headers[header] = value;
|
||||
} else {
|
||||
self._flutter_inappwebview_request_headers[header] += ', ' + value;
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) {
|
||||
if (result != null) {
|
||||
switch (result.action) {
|
||||
case 0:
|
||||
self.abort();
|
||||
return;
|
||||
};
|
||||
if (result.data != null && !\(JAVASCRIPT_UTIL_VAR_NAME).isString(result.data) && result.data.length > 0) {
|
||||
var bodyString = \(JAVASCRIPT_UTIL_VAR_NAME).arrayBufferToString(result.data);
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).isBodyFormData(bodyString)) {
|
||||
var formDataContentType = \(JAVASCRIPT_UTIL_VAR_NAME).getFormDataContentType(bodyString);
|
||||
if (result.headers != null) {
|
||||
result.headers['Content-Type'] = result.headers['Content-Type'] == null ? formDataContentType : result.headers['Content-Type'];
|
||||
} else {
|
||||
result.headers = { 'Content-Type': formDataContentType };
|
||||
}
|
||||
}
|
||||
}
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).isString(result.data) || result.data == null) {
|
||||
data = result.data;
|
||||
} else if (result.data.length > 0) {
|
||||
data = new Uint8Array(result.data);
|
||||
}
|
||||
self.withCredentials = result.withCredentials;
|
||||
if (result.responseType != null) {
|
||||
self.responseType = result.responseType;
|
||||
};
|
||||
if (result.headers != null) {
|
||||
for (var header in result.headers) {
|
||||
var value = result.headers[header];
|
||||
var flutter_inappwebview_value = self._flutter_inappwebview_request_headers[header];
|
||||
if (flutter_inappwebview_value == null) {
|
||||
self._flutter_inappwebview_request_headers[header] = value;
|
||||
} else {
|
||||
self._flutter_inappwebview_request_headers[header] += ', ' + value;
|
||||
}
|
||||
setRequestHeader.call(self, header, value);
|
||||
};
|
||||
}
|
||||
if ((self._flutter_inappwebview_method != result.method && result.method != null) || (self._flutter_inappwebview_url != result.url && result.url != null)) {
|
||||
self.abort();
|
||||
self.open(result.method, result.url, result.isAsync, result.user, result.password);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setRequestHeader.call(self, header, value);
|
||||
};
|
||||
if ((self._flutter_inappwebview_method != result.method && result.method != null) || (self._flutter_inappwebview_url != result.url && result.url != null)) {
|
||||
self.abort();
|
||||
self.open(result.method, result.url, result.isAsync, result.user, result.password);
|
||||
return;
|
||||
}
|
||||
}
|
||||
send.call(self, data);
|
||||
send.call(self, data);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
send.call(this, data);
|
||||
|
@ -24,68 +24,6 @@ let INTERCEPT_FETCH_REQUEST_JS_SOURCE = """
|
||||
if (fetch == null) {
|
||||
return;
|
||||
}
|
||||
function convertHeadersToJson(headers) {
|
||||
var headersObj = {};
|
||||
for (var header of headers.keys()) {
|
||||
var value = headers.get(header);
|
||||
headersObj[header] = value;
|
||||
}
|
||||
return headersObj;
|
||||
}
|
||||
function convertJsonToHeaders(headersJson) {
|
||||
return new Headers(headersJson);
|
||||
}
|
||||
function convertBodyToArray(body) {
|
||||
return new Response(body).arrayBuffer().then(function(arrayBuffer) {
|
||||
var arr = Array.from(new Uint8Array(arrayBuffer));
|
||||
return arr;
|
||||
})
|
||||
}
|
||||
function convertArrayIntBodyToUint8Array(arrayIntBody) {
|
||||
return new Uint8Array(arrayIntBody);
|
||||
}
|
||||
function convertCredentialsToJson(credentials) {
|
||||
var credentialsObj = {};
|
||||
if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {
|
||||
credentialsObj.type = credentials.type;
|
||||
credentialsObj.id = credentials.id;
|
||||
credentialsObj.name = credentials.name;
|
||||
credentialsObj.protocol = credentials.protocol;
|
||||
credentialsObj.provider = credentials.provider;
|
||||
credentialsObj.iconURL = credentials.iconURL;
|
||||
} else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {
|
||||
credentialsObj.type = credentials.type;
|
||||
credentialsObj.id = credentials.id;
|
||||
credentialsObj.name = credentials.name;
|
||||
credentialsObj.password = credentials.password;
|
||||
credentialsObj.iconURL = credentials.iconURL;
|
||||
} else {
|
||||
credentialsObj.type = 'default';
|
||||
credentialsObj.value = credentials;
|
||||
}
|
||||
}
|
||||
function convertJsonToCredential(credentialsJson) {
|
||||
var credentials;
|
||||
if (window.FederatedCredential != null && credentialsJson.type === 'federated') {
|
||||
credentials = new FederatedCredential({
|
||||
id: credentialsJson.id,
|
||||
name: credentialsJson.name,
|
||||
protocol: credentialsJson.protocol,
|
||||
provider: credentialsJson.provider,
|
||||
iconURL: credentialsJson.iconURL
|
||||
});
|
||||
} else if (window.PasswordCredential != null && credentialsJson.type === 'password') {
|
||||
credentials = new PasswordCredential({
|
||||
id: credentialsJson.id,
|
||||
name: credentialsJson.name,
|
||||
password: credentialsJson.password,
|
||||
iconURL: credentialsJson.iconURL
|
||||
});
|
||||
} else {
|
||||
credentials = credentialsJson;
|
||||
}
|
||||
return credentials;
|
||||
}
|
||||
window.fetch = async function(resource, init) {
|
||||
if (\(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_FETCH_REQUEST_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_SHOULD_INTERCEPT_FETCH_REQUEST_JS_SOURCE) == true) {
|
||||
var fetchRequest = {
|
||||
@ -116,7 +54,7 @@ let INTERCEPT_FETCH_REQUEST_JS_SOURCE = """
|
||||
fetchRequest.integrity = resource.integrity;
|
||||
fetchRequest.keepalive = resource.keepalive;
|
||||
} else {
|
||||
fetchRequest.url = resource;
|
||||
fetchRequest.url = resource != null ? resource.toString() : null;
|
||||
if (init != null) {
|
||||
fetchRequest.method = init.method;
|
||||
fetchRequest.headers = init.headers;
|
||||
@ -132,10 +70,10 @@ let INTERCEPT_FETCH_REQUEST_JS_SOURCE = """
|
||||
}
|
||||
}
|
||||
if (fetchRequest.headers instanceof Headers) {
|
||||
fetchRequest.headers = convertHeadersToJson(fetchRequest.headers);
|
||||
fetchRequest.headers = \(JAVASCRIPT_UTIL_VAR_NAME).convertHeadersToJson(fetchRequest.headers);
|
||||
}
|
||||
fetchRequest.credentials = convertCredentialsToJson(fetchRequest.credentials);
|
||||
return convertBodyToArray(fetchRequest.body).then(function(body) {
|
||||
fetchRequest.credentials = \(JAVASCRIPT_UTIL_VAR_NAME).convertCredentialsToJson(fetchRequest.credentials);
|
||||
return \(JAVASCRIPT_UTIL_VAR_NAME).convertBodyRequest(fetchRequest.body).then(function(body) {
|
||||
fetchRequest.body = body;
|
||||
return window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) {
|
||||
if (result != null) {
|
||||
@ -152,7 +90,18 @@ let INTERCEPT_FETCH_REQUEST_JS_SOURCE = """
|
||||
controller.abort();
|
||||
break;
|
||||
}
|
||||
resource = (result.url != null) ? result.url : resource;
|
||||
if (result.body != null && !\(JAVASCRIPT_UTIL_VAR_NAME).isString(result.body) && result.body.length > 0) {
|
||||
var bodyString = \(JAVASCRIPT_UTIL_VAR_NAME).arrayBufferToString(result.body);
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).isBodyFormData(bodyString)) {
|
||||
var formDataContentType = \(JAVASCRIPT_UTIL_VAR_NAME).getFormDataContentType(bodyString);
|
||||
if (result.headers != null) {
|
||||
result.headers['Content-Type'] = result.headers['Content-Type'] == null ? formDataContentType : result.headers['Content-Type'];
|
||||
} else {
|
||||
result.headers = { 'Content-Type': formDataContentType };
|
||||
}
|
||||
}
|
||||
}
|
||||
resource = result.url;
|
||||
if (init == null) {
|
||||
init = {};
|
||||
}
|
||||
@ -160,16 +109,18 @@ let INTERCEPT_FETCH_REQUEST_JS_SOURCE = """
|
||||
init.method = result.method;
|
||||
}
|
||||
if (result.headers != null && Object.keys(result.headers).length > 0) {
|
||||
init.headers = convertJsonToHeaders(result.headers);
|
||||
init.headers = \(JAVASCRIPT_UTIL_VAR_NAME).convertJsonToHeaders(result.headers);
|
||||
}
|
||||
if (result.body != null && result.body.length > 0) {
|
||||
init.body = convertArrayIntBodyToUint8Array(result.body);
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).isString(result.body) || result.body == null) {
|
||||
init.body = result.body;
|
||||
} else if (result.body.length > 0) {
|
||||
init.body = new Uint8Array(result.body);
|
||||
}
|
||||
if (result.mode != null && result.mode.length > 0) {
|
||||
init.mode = result.mode;
|
||||
}
|
||||
if (result.credentials != null) {
|
||||
init.credentials = convertJsonToCredential(result.credentials);
|
||||
init.credentials = \(JAVASCRIPT_UTIL_VAR_NAME).convertJsonToCredential(result.credentials);
|
||||
}
|
||||
if (result.cache != null && result.cache.length > 0) {
|
||||
init.cache = result.cache;
|
||||
|
@ -30,6 +30,213 @@ window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() {
|
||||
});
|
||||
};
|
||||
\(WEB_MESSAGE_LISTENER_JS_SOURCE)
|
||||
\(UTIL_JS_SOURCE)
|
||||
"""
|
||||
|
||||
let PLATFORM_READY_JS_SOURCE = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
|
||||
|
||||
let JAVASCRIPT_UTIL_VAR_NAME = "window.\(JAVASCRIPT_BRIDGE_NAME)._Util"
|
||||
|
||||
/*
|
||||
https://github.com/github/fetch/blob/master/fetch.js
|
||||
*/
|
||||
let UTIL_JS_SOURCE = """
|
||||
\(JAVASCRIPT_UTIL_VAR_NAME) = {
|
||||
support: {
|
||||
searchParams: 'URLSearchParams' in window,
|
||||
iterable: 'Symbol' in window && 'iterator' in Symbol,
|
||||
blob:
|
||||
'FileReader' in window &&
|
||||
'Blob' in window &&
|
||||
(function() {
|
||||
try {
|
||||
new Blob();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
formData: 'FormData' in window,
|
||||
arrayBuffer: 'ArrayBuffer' in window
|
||||
},
|
||||
isDataView: function(obj) {
|
||||
return obj && DataView.prototype.isPrototypeOf(obj);
|
||||
},
|
||||
fileReaderReady: function(reader) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
reader.onload = function() {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.onerror = function() {
|
||||
reject(reader.error);
|
||||
};
|
||||
});
|
||||
},
|
||||
readBlobAsArrayBuffer: function(blob) {
|
||||
var reader = new FileReader();
|
||||
var promise = \(JAVASCRIPT_UTIL_VAR_NAME).fileReaderReady(reader);
|
||||
reader.readAsArrayBuffer(blob);
|
||||
return promise;
|
||||
},
|
||||
convertBodyToArrayBuffer: function(body) {
|
||||
var viewClasses = [
|
||||
'[object Int8Array]',
|
||||
'[object Uint8Array]',
|
||||
'[object Uint8ClampedArray]',
|
||||
'[object Int16Array]',
|
||||
'[object Uint16Array]',
|
||||
'[object Int32Array]',
|
||||
'[object Uint32Array]',
|
||||
'[object Float32Array]',
|
||||
'[object Float64Array]'
|
||||
];
|
||||
var isArrayBufferView = null;
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).support.arrayBuffer) {
|
||||
isArrayBufferView =
|
||||
ArrayBuffer.isView ||
|
||||
function(obj) {
|
||||
return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
|
||||
};
|
||||
}
|
||||
|
||||
var bodyUsed = false;
|
||||
|
||||
this._bodyInit = body;
|
||||
if (!body) {
|
||||
this._bodyText = '';
|
||||
} else if (typeof body === 'string') {
|
||||
this._bodyText = body;
|
||||
} else if (\(JAVASCRIPT_UTIL_VAR_NAME).support.blob && Blob.prototype.isPrototypeOf(body)) {
|
||||
this._bodyBlob = body;
|
||||
} else if (\(JAVASCRIPT_UTIL_VAR_NAME).support.formData && FormData.prototype.isPrototypeOf(body)) {
|
||||
this._bodyFormData = body;
|
||||
} else if (\(JAVASCRIPT_UTIL_VAR_NAME).support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
|
||||
this._bodyText = body.toString();
|
||||
} else if (\(JAVASCRIPT_UTIL_VAR_NAME).support.arrayBuffer && \(JAVASCRIPT_UTIL_VAR_NAME).support.blob && \(JAVASCRIPT_UTIL_VAR_NAME).isDataView(body)) {
|
||||
this._bodyArrayBuffer = bufferClone(body.buffer);
|
||||
this._bodyInit = new Blob([this._bodyArrayBuffer]);
|
||||
} else if (\(JAVASCRIPT_UTIL_VAR_NAME).support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
|
||||
this._bodyArrayBuffer = bufferClone(body);
|
||||
} else {
|
||||
this._bodyText = body = Object.prototype.toString.call(body);
|
||||
}
|
||||
|
||||
this.blob = function () {
|
||||
if (bodyUsed) {
|
||||
return Promise.reject(new TypeError('Already read'));
|
||||
}
|
||||
bodyUsed = true;
|
||||
if (this._bodyBlob) {
|
||||
return Promise.resolve(this._bodyBlob);
|
||||
} else if (this._bodyArrayBuffer) {
|
||||
return Promise.resolve(new Blob([this._bodyArrayBuffer]));
|
||||
} else if (this._bodyFormData) {
|
||||
throw new Error('could not read FormData body as blob');
|
||||
} else {
|
||||
return Promise.resolve(new Blob([this._bodyText]));
|
||||
}
|
||||
};
|
||||
|
||||
if (this._bodyArrayBuffer) {
|
||||
if (bodyUsed) {
|
||||
return Promise.reject(new TypeError('Already read'));
|
||||
}
|
||||
bodyUsed = true;
|
||||
if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
|
||||
return Promise.resolve(
|
||||
this._bodyArrayBuffer.buffer.slice(
|
||||
this._bodyArrayBuffer.byteOffset,
|
||||
this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return Promise.resolve(this._bodyArrayBuffer);
|
||||
}
|
||||
}
|
||||
return this.blob().then(\(JAVASCRIPT_UTIL_VAR_NAME).readBlobAsArrayBuffer);
|
||||
},
|
||||
isString: function(variable) {
|
||||
return typeof variable === 'string' || variable instanceof String;
|
||||
},
|
||||
convertBodyRequest: function(body) {
|
||||
if (body == null) {
|
||||
return new Promise((resolve, reject) => resolve(null));
|
||||
}
|
||||
if (\(JAVASCRIPT_UTIL_VAR_NAME).isString(body) || (\(JAVASCRIPT_UTIL_VAR_NAME).support.searchParams && body instanceof URLSearchParams)) {
|
||||
return new Promise((resolve, reject) => resolve(body.toString()));
|
||||
}
|
||||
if (window.Response != null) {
|
||||
return new Response(body).arrayBuffer().then(function(arrayBuffer) {
|
||||
return Array.from(new Uint8Array(arrayBuffer));
|
||||
});
|
||||
}
|
||||
return \(JAVASCRIPT_UTIL_VAR_NAME).convertBodyToArrayBuffer(body).then(function(arrayBuffer) {
|
||||
return Array.from(new Uint8Array(arrayBuffer));
|
||||
});
|
||||
},
|
||||
arrayBufferToString: function(arrayBuffer) {
|
||||
return String.fromCharCode.apply(String, arrayBuffer);
|
||||
},
|
||||
isBodyFormData: function(bodyString) {
|
||||
return bodyString.indexOf('------WebKitFormBoundary') >= 0;
|
||||
},
|
||||
getFormDataContentType: function(bodyString) {
|
||||
var boundary = bodyString.substr(2, 40);
|
||||
return 'multipart/form-data; boundary=' + boundary;
|
||||
},
|
||||
convertHeadersToJson: function(headers) {
|
||||
var headersObj = {};
|
||||
for (var header of headers.keys()) {
|
||||
var value = headers.get(header);
|
||||
headersObj[header] = value;
|
||||
}
|
||||
return headersObj;
|
||||
},
|
||||
convertJsonToHeaders: function(headersJson) {
|
||||
return new Headers(headersJson);
|
||||
},
|
||||
convertCredentialsToJson: function(credentials) {
|
||||
var credentialsObj = {};
|
||||
if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {
|
||||
credentialsObj.type = credentials.type;
|
||||
credentialsObj.id = credentials.id;
|
||||
credentialsObj.name = credentials.name;
|
||||
credentialsObj.protocol = credentials.protocol;
|
||||
credentialsObj.provider = credentials.provider;
|
||||
credentialsObj.iconURL = credentials.iconURL;
|
||||
} else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {
|
||||
credentialsObj.type = credentials.type;
|
||||
credentialsObj.id = credentials.id;
|
||||
credentialsObj.name = credentials.name;
|
||||
credentialsObj.password = credentials.password;
|
||||
credentialsObj.iconURL = credentials.iconURL;
|
||||
} else {
|
||||
credentialsObj.type = 'default';
|
||||
credentialsObj.value = credentials;
|
||||
}
|
||||
return credentialsObj;
|
||||
},
|
||||
convertJsonToCredential: function(credentialsJson) {
|
||||
var credentials;
|
||||
if (window.FederatedCredential != null && credentialsJson.type === 'federated') {
|
||||
credentials = new FederatedCredential({
|
||||
id: credentialsJson.id,
|
||||
name: credentialsJson.name,
|
||||
protocol: credentialsJson.protocol,
|
||||
provider: credentialsJson.provider,
|
||||
iconURL: credentialsJson.iconURL
|
||||
});
|
||||
} else if (window.PasswordCredential != null && credentialsJson.type === 'password') {
|
||||
credentials = new PasswordCredential({
|
||||
id: credentialsJson.id,
|
||||
name: credentialsJson.name,
|
||||
password: credentialsJson.password,
|
||||
iconURL: credentialsJson.iconURL
|
||||
});
|
||||
} else {
|
||||
credentials = credentialsJson.value == null ? undefined : credentialsJson.value;
|
||||
}
|
||||
return credentials;
|
||||
}
|
||||
};
|
||||
"""
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
@ -39,7 +40,8 @@ class InAppLocalhostServer {
|
||||
this._server = server;
|
||||
|
||||
server.listen((HttpRequest request) async {
|
||||
var body = [] as List<int>;
|
||||
Uint8List body = Uint8List(0);
|
||||
|
||||
var path = request.requestedUri.path;
|
||||
path = (path.startsWith('/')) ? path.substring(1) : path;
|
||||
path += (path.endsWith('/')) ? 'index.html' : '';
|
||||
|
@ -2873,7 +2873,7 @@ class AjaxRequestHeaders {
|
||||
///Class that represents a JavaScript [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) object.
|
||||
class AjaxRequest {
|
||||
///Data passed as a parameter to the `XMLHttpRequest.send()` method.
|
||||
dynamic data;
|
||||
dynamic? data;
|
||||
|
||||
///The HTTP request method of the `XMLHttpRequest` request.
|
||||
String? method;
|
||||
@ -3225,7 +3225,7 @@ class FetchRequest {
|
||||
Map<String, dynamic>? headers;
|
||||
|
||||
///Body of the request.
|
||||
Uint8List? body;
|
||||
dynamic? body;
|
||||
|
||||
///The mode used by the request.
|
||||
String? mode;
|
||||
@ -3291,9 +3291,7 @@ class FetchRequest {
|
||||
url: map["url"] != null ? Uri.parse(map["url"]) : null,
|
||||
method: map["method"],
|
||||
headers: map["headers"]?.cast<String, dynamic>(),
|
||||
body: map["body"] != null
|
||||
? Uint8List.fromList(map["body"].cast<int>())
|
||||
: null,
|
||||
body: map["body"],
|
||||
mode: map["mode"],
|
||||
credentials: credentials,
|
||||
cache: map["cache"],
|
||||
|
@ -9,6 +9,8 @@ const appHttps = express()
|
||||
const appAuthBasic = express()
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const bodyParser = require('body-parser');
|
||||
const multiparty = require('multiparty');
|
||||
|
||||
var options = {
|
||||
key: fs.readFileSync('server-key.pem'),
|
||||
@ -117,14 +119,11 @@ appAuthBasic.get('/test-index', (req, res) => {
|
||||
appAuthBasic.listen(8081);
|
||||
|
||||
|
||||
|
||||
// Parse URL-encoded bodies (as sent by HTML forms)
|
||||
app.use(express.urlencoded());
|
||||
|
||||
app.use(cors());
|
||||
|
||||
app.use(bodyParser.urlencoded({extended: false}));
|
||||
// Parse JSON bodies (as sent by API clients)
|
||||
app.use(express.json());
|
||||
app.use(bodyParser.json());
|
||||
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
@ -162,14 +161,27 @@ app.post("/test-post", (req, res) => {
|
||||
})
|
||||
|
||||
app.post("/test-ajax-post", (req, res) => {
|
||||
console.log(JSON.stringify(req.headers))
|
||||
console.log(JSON.stringify(req.body))
|
||||
res.set("Content-Type", "application/json")
|
||||
res.send(JSON.stringify({
|
||||
"firstname": req.body.firstname,
|
||||
"lastname": req.body.lastname,
|
||||
}))
|
||||
res.end()
|
||||
console.log(JSON.stringify(req.headers));
|
||||
if (req.headers["content-type"].indexOf("multipart/form-data;") === 0) {
|
||||
const form = new multiparty.Form();
|
||||
form.parse(req, function(err, fields, files) {
|
||||
console.log(fields);
|
||||
res.set("Content-Type", "application/json")
|
||||
res.send(JSON.stringify({
|
||||
"firstname": fields.firstname[0],
|
||||
"lastname": fields.lastname[0],
|
||||
}));
|
||||
res.end();
|
||||
});
|
||||
} else {
|
||||
console.log(req.body);
|
||||
res.set("Content-Type", "application/json")
|
||||
res.send(JSON.stringify({
|
||||
"firstname": req.body.firstname,
|
||||
"lastname": req.body.lastname,
|
||||
}));
|
||||
res.end();
|
||||
}
|
||||
})
|
||||
|
||||
app.get("/test-download-file", (req, res) => {
|
||||
@ -184,4 +196,4 @@ app.get("/test-download-file", (req, res) => {
|
||||
res.end();
|
||||
})
|
||||
|
||||
app.listen(8082)
|
||||
app.listen(8082)
|
||||
|
@ -252,6 +252,45 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"multiparty": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.2.tgz",
|
||||
"integrity": "sha512-NtZLjlvsjcoGrzojtwQwn/Tm90aWJ6XXtPppYF4WmOk/6ncdwMMKggFY2NlRRN9yiCEIVxpOfPWahVEG2HAG8Q==",
|
||||
"requires": {
|
||||
"http-errors": "~1.8.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"uid-safe": "2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"http-errors": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
|
||||
"integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
@ -294,6 +333,11 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@ -382,6 +426,14 @@
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||
"requires": {
|
||||
"random-bytes": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
@ -10,8 +10,10 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"basic-auth": "latest",
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "latest",
|
||||
"https": "latest"
|
||||
"https": "latest",
|
||||
"multiparty": "^4.2.2"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user