diff --git a/quickjs/src/main/assets/js/lib/http.js b/quickjs/src/main/assets/js/lib/http.js deleted file mode 100644 index a8c533389..000000000 --- a/quickjs/src/main/assets/js/lib/http.js +++ /dev/null @@ -1,13 +0,0 @@ -function http(url, options = {}) { - if (options?.async === false) return _http(url, options) - return new Promise(resolve => _http(url, Object.assign({ - complete: res => resolve(res) - }, options))).catch(err => { - console.error(err.name, err.message, err.stack) - return { - ok: false, - status: 500, - url - } - }) -} \ No newline at end of file diff --git a/quickjs/src/main/java/com/fongmi/quickjs/bean/Req.java b/quickjs/src/main/java/com/fongmi/quickjs/bean/Req.java index e62183f81..144180585 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/bean/Req.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/bean/Req.java @@ -48,7 +48,7 @@ public class Req { } public String getPostType() { - return TextUtils.isEmpty(postType) ? "" : postType; + return TextUtils.isEmpty(postType) ? "json" : postType; } public String getMethod() { diff --git a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java index d4ffd5bbb..a4cc90189 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java @@ -3,9 +3,10 @@ package com.fongmi.quickjs.method; import android.util.Base64; import androidx.annotation.Keep; +import androidx.annotation.NonNull; import com.fongmi.quickjs.bean.Req; -import com.fongmi.quickjs.utils.JSUtil; +import com.fongmi.quickjs.utils.Connect; import com.fongmi.quickjs.utils.Parser; import com.fongmi.quickjs.utils.Proxy; import com.google.gson.Gson; @@ -14,6 +15,7 @@ import com.whl.quickjs.wrapper.JSMethod; import com.whl.quickjs.wrapper.JSObject; import com.whl.quickjs.wrapper.QuickJSContext; +import java.io.IOException; import java.lang.reflect.Method; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -26,6 +28,8 @@ import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import okhttp3.Call; +import okhttp3.Callback; import okhttp3.Response; public class Global { @@ -83,20 +87,20 @@ public class Global { @Keep @JSMethod - public void _http(String url, JSObject options) { - + public JSObject _http(String url, JSObject options) throws IOException { + JSFunction complete = options.getJSFunction("complete"); + if (complete == null) return req(url, options); + Req req = Req.objectFrom(ctx.stringify(options)); + Connect.to(url, req).enqueue(getCallback(complete, req)); + return null; } @Keep @JSMethod - public JSObject req(String url, JSObject object) { - try { - Req req = Req.objectFrom(ctx.stringify(object)); - Response res = JSUtil.call(url, req).execute(); - return JSUtil.toResponse(ctx, res, req); - } catch (Throwable e) { - return JSUtil.toFailure(ctx); - } + public JSObject req(String url, JSObject options) throws IOException { + Req req = Req.objectFrom(ctx.stringify(options)); + Response res = Connect.to(url, req).execute(); + return Connect.success(ctx, req, res); } @Keep @@ -169,11 +173,31 @@ public class Global { } } + private Callback getCallback(JSFunction complete, Req req) { + return new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response res) { + executor.submit(() -> { + complete.call(Connect.success(ctx, req, res)); + }); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + executor.submit(() -> { + complete.call(Connect.error(ctx)); + }); + } + }; + } + private void schedule(JSFunction func, int delay) { timer.schedule(new TimerTask() { @Override public void run() { - if (!executor.isShutdown()) executor.submit(() -> {func.call();}); + if (!executor.isShutdown()) executor.submit(() -> { + func.call(); + }); } }, delay); } diff --git a/quickjs/src/main/java/com/fongmi/quickjs/utils/Connect.java b/quickjs/src/main/java/com/fongmi/quickjs/utils/Connect.java new file mode 100644 index 000000000..9bd14ef6f --- /dev/null +++ b/quickjs/src/main/java/com/fongmi/quickjs/utils/Connect.java @@ -0,0 +1,89 @@ +package com.fongmi.quickjs.utils; + +import com.fongmi.quickjs.bean.Req; +import com.github.catvod.net.OkHttp; +import com.github.catvod.utils.Json; +import com.github.catvod.utils.Util; +import com.google.common.net.HttpHeaders; +import com.whl.quickjs.wrapper.JSObject; +import com.whl.quickjs.wrapper.QuickJSContext; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import okhttp3.Call; +import okhttp3.FormBody; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class Connect { + + public static Call to(String url, Req req) { + OkHttpClient client = req.getRedirect() == 1 ? OkHttp.client() : OkHttp.noRedirect(); + client = client.newBuilder().connectTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).readTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).writeTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).build(); + return client.newCall(getRequest(url, req, Headers.of(req.getHeader()))); + } + + public static JSObject success(QuickJSContext ctx, Req req, Response res) { + try { + JSObject jsObject = ctx.createNewJSObject(); + JSObject jsHeader = ctx.createNewJSObject(); + setHeader(ctx, res, jsHeader); + jsObject.setProperty("headers", jsHeader); + if (req.getBuffer() == 0) jsObject.setProperty("content", new String(res.body().bytes(), req.getCharset())); + if (req.getBuffer() == 1) jsObject.setProperty("content", JSUtil.toArray(ctx, res.body().bytes())); + if (req.getBuffer() == 2) jsObject.setProperty("content", Util.base64(res.body().bytes())); + return jsObject; + } catch (Exception e) { + return error(ctx); + } + } + + public static JSObject error(QuickJSContext ctx) { + JSObject jsObject = ctx.createNewJSObject(); + JSObject jsHeader = ctx.createNewJSObject(); + jsObject.setProperty("headers", jsHeader); + jsObject.setProperty("content", ""); + return jsObject; + } + + private static Request getRequest(String url, Req req, Headers headers) { + if (req.getMethod().equalsIgnoreCase("post")) { + return new Request.Builder().url(url).headers(headers).post(getPostBody(req, headers.get(HttpHeaders.CONTENT_TYPE))).build(); + } else if (req.getMethod().equalsIgnoreCase("header")) { + return new Request.Builder().url(url).headers(headers).head().build(); + } else { + return new Request.Builder().url(url).headers(headers).get().build(); + } + } + + private static RequestBody getPostBody(Req req, String contentType) { + if (req.getData() != null && req.getPostType().equals("json")) return getJsonBody(req); + if (req.getData() != null && req.getPostType().equals("form")) return getFormBody(req); + if (req.getBody() != null && contentType != null) return RequestBody.create(req.getBody(), MediaType.get(contentType)); + return RequestBody.create("", null); + } + + private static RequestBody getJsonBody(Req req) { + return RequestBody.create(req.getData().toString(), MediaType.get("application/json")); + } + + private static RequestBody getFormBody(Req req) { + FormBody.Builder formBody = new FormBody.Builder(); + Map params = Json.toMap(req.getData()); + for (String key : params.keySet()) formBody.add(key, params.get(key)); + return formBody.build(); + } + + private static void setHeader(QuickJSContext ctx, Response res, JSObject object) { + for (Map.Entry> entry : res.headers().toMultimap().entrySet()) { + if (entry.getValue().size() == 1) object.setProperty(entry.getKey(), entry.getValue().get(0)); + if (entry.getValue().size() >= 2) object.setProperty(entry.getKey(), JSUtil.toArray(ctx, entry.getValue())); + } + } +} diff --git a/quickjs/src/main/java/com/fongmi/quickjs/utils/JSUtil.java b/quickjs/src/main/java/com/fongmi/quickjs/utils/JSUtil.java index 36ce6fd44..d48881def 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/utils/JSUtil.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/utils/JSUtil.java @@ -1,27 +1,11 @@ package com.fongmi.quickjs.utils; -import com.fongmi.quickjs.bean.Req; -import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Json; -import com.github.catvod.utils.Util; -import com.google.gson.Gson; import com.whl.quickjs.wrapper.JSArray; import com.whl.quickjs.wrapper.JSObject; import com.whl.quickjs.wrapper.QuickJSContext; -import java.io.IOException; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; - -import okhttp3.Call; -import okhttp3.FormBody; -import okhttp3.Headers; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; public class JSUtil { @@ -45,60 +29,4 @@ public class JSUtil { for (String s : map.keySet()) obj.setProperty(s, map.get(s)); return obj; } - - public static Call call(String url, Req req) { - OkHttpClient client = req.getRedirect() == 1 ? OkHttp.client() : OkHttp.noRedirect(); - client = client.newBuilder().connectTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).readTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).writeTimeout(req.getTimeout(), TimeUnit.MILLISECONDS).build(); - return client.newCall(getRequest(url, req, Headers.of(req.getHeader()))); - } - - public static JSObject toResponse(QuickJSContext ctx, Response response, Req req) throws IOException { - JSObject jsObject = ctx.createNewJSObject(); - JSObject jsHeader = ctx.createNewJSObject(); - setHeader(ctx, response, jsHeader); - jsObject.setProperty("headers", jsHeader); - if (req.getBuffer() == 0) jsObject.setProperty("content", new String(response.body().bytes(), req.getCharset())); - if (req.getBuffer() == 1) jsObject.setProperty("content", JSUtil.toArray(ctx, response.body().bytes())); - if (req.getBuffer() == 2) jsObject.setProperty("content", Util.base64(response.body().bytes())); - return jsObject; - } - - public static JSObject toFailure(QuickJSContext ctx) { - JSObject jsObject = ctx.createNewJSObject(); - JSObject jsHeader = ctx.createNewJSObject(); - jsObject.setProperty("headers", jsHeader); - jsObject.setProperty("content", ""); - return jsObject; - } - - private static Request getRequest(String url, Req req, Headers headers) { - if (req.getMethod().equalsIgnoreCase("post")) { - return new Request.Builder().url(url).headers(headers).post(getPostBody(req, headers.get("Content-Type"))).build(); - } else if (req.getMethod().equalsIgnoreCase("header")) { - return new Request.Builder().url(url).headers(headers).head().build(); - } else { - return new Request.Builder().url(url).headers(headers).get().build(); - } - } - - private static RequestBody getPostBody(Req req, String contentType) { - if (req.getData() != null && req.getPostType().equals("form")) return getFormBody(req); - if (req.getData() != null) return RequestBody.create(new Gson().toJson(req.getData()), MediaType.get("application/json")); - if (req.getBody() != null && contentType != null) return RequestBody.create(req.getBody(), MediaType.get(contentType)); - return RequestBody.create("", null); - } - - private static RequestBody getFormBody(Req req) { - FormBody.Builder formBody = new FormBody.Builder(); - Map params = Json.toMap(req.getData()); - for (String key : params.keySet()) formBody.add(key, params.get(key)); - return formBody.build(); - } - - private static void setHeader(QuickJSContext ctx, Response response, JSObject object) { - for (Map.Entry> entry : response.headers().toMultimap().entrySet()) { - if (entry.getValue().size() == 1) object.setProperty(entry.getKey(), entry.getValue().get(0)); - if (entry.getValue().size() >= 2) object.setProperty(entry.getKey(), JSUtil.toArray(ctx, entry.getValue())); - } - } }