首页 > 其他分享 >quickjs集成http功能

quickjs集成http功能

时间:2023-12-11 14:48:41浏览次数:38  
标签:集成 quickjs http ctx JS curl js data

零、前言

  默认的quickjs,是js引擎,需要自己移植类似curl库,才能使quickjs有http请求功能。js引擎+一些本地功能调用=js运行时。

一、libcurl库

  这个库的安装或编译,也是比较麻烦的事情,特别是需要使其支持https访问,配置和编译更是麻烦。因此,还是使用上次提到的vcpkg。通过vcpkg search curl,然后根据需要安装对应支持ssl证书的。然后安装好的libcurl.dll libcrypto-3-x64.dll libssl-3-x64.dll 文件放到运行目录,同时也要复制对应include头文件到对应目录。

  一个curl例子

 1 #include <stdio.h>
 2 #include "curl/curl.h"
 3 
 4 
 5 size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
 6 {
 7   int len = size * nmemb;
 8     char buf[10240] = {'\0'};
 9     strncpy(buf, ptr, len);
10     printf("=========================get Data=====================\n");
11     printf("%s\n",buf);
12     printf("======================================================\n");
13   return len;
14 }
15 
16 int main()
17 {
18   CURL *curl;
19   CURLcode res;
20   curl = curl_easy_init();
21 
22   if (curl)
23   {
24     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
25     curl_easy_setopt(curl, CURLOPT_URL, "https://mock.apifox.com/m2/385371-0-default/33329355");
26     
27     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
28     curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
29     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);//忽略证书检查
30     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
31 
32     struct curl_slist *headers = NULL;
33     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
34     const char *data = "{}";
35     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
36     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);
37 
38     res = curl_easy_perform(curl);
39     printf("res = %d\n", res);
40     if (res != CURLE_OK)
41       fprintf(stderr, "%s\n", curl_easy_strerror(res));
42 
43   }
44   curl_easy_cleanup(curl);
45   printf("Hello World!\n");
46   return 0;
47 }

  输出结果

1 D:\test\quickjs\examples\libuv>bin\main.exe
2 =========================get Data=====================
3 {"msg":"ok"}
4 ======================================================
5 res = 0
6 Hello World!

  CMakeList.txt

 1 cmake_minimum_required(VERSION 3.10)
 2 project(quickjs_libuv)
 3 
 4 SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 
 5 
 6 include_directories(${PROJECT_SOURCE_DIR})
 7 include_directories(${PROJECT_SOURCE_DIR}/include)
 8 
 9 link_directories(${PROJECT_SOURCE_DIR}/bin)
10 # add_executable(main main.c)
11 add_executable(main test_curl.c)
12 target_link_libraries(main quickjs uv curl)

二、quickjs绑定

   1. 通过使用curl_easy_setopt函数设置 CURLOPT_WRITEDATA,实现请求结果回调。

 1 size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
 2 {
 3   http_ctx_t *ctx = (http_ctx_t *)stream;
 4   int len = size * nmemb;
 5   char buf[10240] = {'\0'};
 6   strncpy(buf, ptr, len);
 7   printf("=========================get Data=====================\n");
 8   // printf("%s\n", buf);
 9   JSValue func = ctx->func;
10   JSValueConst this_obj = JS_UNDEFINED;
11   JSValueConst argv[1] = {JS_NewString(ctx->ctx, buf)};
12   JSValue ret = JS_Call(ctx->ctx, func, this_obj, 1, argv);
13   JS_FreeValue(ctx->ctx, func);
14   if(JS_IsException(ret)){
15     js_std_dump_error(ctx->ctx);
16   }
17   JS_FreeValue(ctx->ctx, argv[0]);
18   JS_FreeValue(ctx->ctx, ret);
19   printf("======================================================\n");
20   return len;
21 }

  2. 实现两种调用方式,一种是同步调用,那就是简单的在js绑定函数处调用上一步的curl_request。另一种是异步调用方式,利用libuv,实现异步调用curl_request。 

 1 static JSValue js_http_get_request(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
 2 {
 3   const char* url = JS_ToCString(ctx, argv[0]);
 4   JSValueConst func = argv[1];
 5   int sync = JS_ToBool(ctx, argv[2]);
 6   if(!JS_IsFunction(ctx, func)){
 7     printf("not a function\n");
 8     return JS_EXCEPTION;
 9   }
10   JS_FreeValue(ctx, argv[0]);
11   http_ctx_t *data = calloc(1, sizeof(http_ctx_t));
12   data->url = url;
13   data->ctx = ctx;
14   data->func = JS_DupValue(ctx, func);
15   if(sync){
16     printf("c sync req\n");
17     curl_main(url, data);
18   }else{
19     printf("c async req\n");
20     data->handle.data = data;
21     uv_timer_init(loop, &data->handle);
22     uv_timer_start(&data->handle, js_http_get_request_async, 0, 0);
23   }
24   return JS_UNDEFINED;
25 }
26 static const JSCFunctionListEntry js_http_funcs[] = {
27   JS_CFUNC_DEF("get_request", 1, js_http_get_request),
28 };
29 static int js_http_init(JSContext *ctx, JSModuleDef *m)
30 {
31   return JS_SetModuleExportList(ctx, m, js_http_funcs, countof(js_http_funcs));
32 }
33 JSModuleDef *js_init_module_http(JSContext *ctx, const char *module_name)
34 {
35   JSModuleDef *m = JS_NewCModule(ctx, module_name, js_http_init);
36   if (!m)
37     return NULL;
38   JS_AddModuleExportList(ctx, m, js_http_funcs, countof(js_http_funcs));
39   return m;
40 }

 

三、代码如下

  tes_curl.c

  1 #include <stdio.h>
  2 #include "curl/curl.h"
  3 #include "quickjs.h"
  4 #include "quickjs-libc.h"
  5 #include "uv.h"
  6 #include "cutils.h"
  7 #include <string.h>
  8 
  9 uv_loop_t *loop;
 10 typedef struct _http_ctx_t{
 11   JSContext *ctx;
 12   JSValueConst func;
 13   uv_timer_t handle;
 14   const char * url;
 15 } http_ctx_t;
 16 
 17 size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
 18 {
 19   http_ctx_t *ctx = (http_ctx_t *)stream;
 20   int len = size * nmemb;
 21   char buf[10240] = {'\0'};
 22   strncpy(buf, ptr, len);
 23   printf("=========================get Data=====================\n");
 24   // printf("%s\n", buf);
 25   JSValue func = ctx->func;
 26   JSValueConst this_obj = JS_UNDEFINED;
 27   JSValueConst argv[1] = {JS_NewString(ctx->ctx, buf)};
 28   JSValue ret = JS_Call(ctx->ctx, func, this_obj, 1, argv);
 29   JS_FreeValue(ctx->ctx, func);
 30   if(JS_IsException(ret)){
 31     js_std_dump_error(ctx->ctx);
 32   }
 33   JS_FreeValue(ctx->ctx, argv[0]);
 34   JS_FreeValue(ctx->ctx, ret);
 35   printf("======================================================\n");
 36   return len;
 37 }
 38 
 39 void curl_main(const char * url, http_ctx_t *ctx)
 40 {
 41   CURL *curl;
 42   CURLcode res;
 43   curl = curl_easy_init();
 44 
 45   if (curl)
 46   {
 47     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
 48     curl_easy_setopt(curl, CURLOPT_URL, url);
 49 
 50     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
 51     curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
 52     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); // 忽略证书检查
 53     curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
 54 
 55     struct curl_slist *headers = NULL;
 56     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
 57     const char *data = "{}";
 58     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
 59     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);
 60     curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
 61     // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
 62 
 63     res = curl_easy_perform(curl);
 64     // printf("res = %d\n", res);
 65     if (res != CURLE_OK)
 66       fprintf(stderr, "%s\n", curl_easy_strerror(res));
 67   }
 68   curl_easy_cleanup(curl);
 69 }
 70 /*js绑定*/
 71 static void js_http_get_request_async(uv_timer_t *handle)
 72 {
 73   http_ctx_t *data = (http_ctx_t *)handle->data;
 74   curl_main(data->url, data);
 75 }
 76 static JSValue js_http_get_request(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
 77 {
 78   const char* url = JS_ToCString(ctx, argv[0]);
 79   JSValueConst func = argv[1];
 80   int sync = JS_ToBool(ctx, argv[2]);
 81   if(!JS_IsFunction(ctx, func)){
 82     printf("not a function\n");
 83     return JS_EXCEPTION;
 84   }
 85   JS_FreeValue(ctx, argv[0]);
 86   http_ctx_t *data = calloc(1, sizeof(http_ctx_t));
 87   data->url = url;
 88   data->ctx = ctx;
 89   data->func = JS_DupValue(ctx, func);
 90   if(sync){
 91     printf("c sync req\n");
 92     curl_main(url, data);
 93   }else{
 94     printf("c async req\n");
 95     data->handle.data = data;
 96     uv_timer_init(loop, &data->handle);
 97     uv_timer_start(&data->handle, js_http_get_request_async, 0, 0);
 98   }
 99   return JS_UNDEFINED;
100 }
101 static const JSCFunctionListEntry js_http_funcs[] = {
102   JS_CFUNC_DEF("get_request", 1, js_http_get_request),
103 };
104 static int js_http_init(JSContext *ctx, JSModuleDef *m)
105 {
106   return JS_SetModuleExportList(ctx, m, js_http_funcs, countof(js_http_funcs));
107 }
108 JSModuleDef *js_init_module_http(JSContext *ctx, const char *module_name)
109 {
110   JSModuleDef *m = JS_NewCModule(ctx, module_name, js_http_init);
111   if (!m)
112     return NULL;
113   JS_AddModuleExportList(ctx, m, js_http_funcs, countof(js_http_funcs));
114   return m;
115 }
116 
117 JSContext *js_init_context()
118 {
119   JSRuntime *rt = JS_NewRuntime();
120   js_std_init_handlers(rt);
121   JSContext *ctx = JS_NewContext(rt);
122   js_init_module_os(ctx, "os");
123   js_init_module_std(ctx, "std");
124   js_init_module_http(ctx, "http");
125   return ctx;
126 }
127 void run_js(JSContext *ctx)
128 {
129   const char *str =
130       "import * as std from 'std'\n"
131       "import * as http from 'http'\n"
132       "import * as os from 'os'\n"
133       "globalThis.std = std\n"
134       "globalThis.http = http\n"
135       "globalThis.os = os\n"
136       "var console = {};\n"
137       "console.log = function(msg) {\n"
138       "  std.printf(msg + '\\n');\n"
139       "}\n"
140       "globalThis.console = console;\n";
141   JSValue init_compile = JS_Eval(
142       ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
143   js_module_set_import_meta(ctx, init_compile, 1, 1);
144   JSValue init_run = JS_EvalFunction(ctx, init_compile);
145 
146   const char *buf = "console.log('start sync req');\n"
147   "var url = 'https://mock.apifox.com/m2/385371-0-default/33329355';\n"
148   "http.get_request(url, function(data){\n"
149   "  console.log('sync->>' + data);\n"
150   "}, true);\n"
151   "console.log('end sync req');\n"
152   "console.log('start async req');\n"
153   "var url = 'https://mock.apifox.com/m2/385371-0-default/33329355';\n"
154   "http.get_request(url, function(data){\n"
155   "  console.log('async->>' + data);\n"
156   "}, false);\n"
157   "console.log('end async req');"
158   ;
159   JSValue result = JS_Eval(ctx, buf, strlen(buf), "test", JS_EVAL_TYPE_GLOBAL);
160   js_std_loop(ctx);
161   int clen;
162   if (JS_ToInt32(ctx, &clen, result) != 0)
163   {
164     js_std_dump_error(ctx);
165   }
166   printf("exit run_js\n");
167 }
168 
169 int main()
170 {
171   loop = uv_default_loop();
172   JSContext *ctx = js_init_context();
173   run_js(ctx);
174   while(uv_run(loop, UV_RUN_NOWAIT)){
175     ;
176   }
177   JS_FreeContext(ctx);
178   JS_FreeRuntime(JS_GetRuntime(ctx));
179   printf("Success!\n");
180   return 0;
181 }

  运行结果打印

 1 D:\test\quickjs\examples\libuv>bin\main.exe
 2 start sync req
 3 c sync req
 4 =========================get Data=====================
 5 sync->>{"msg":"ok"}
 6 ======================================================
 7 end sync req
 8 start async req
 9 c async req
10 end async req
11 exit run_js
12 =========================get Data=====================
13 async->>{"msg":"ok"}
14 ======================================================
15 QuickJS memory usage -- BigNum 2021-03-27 version, 64-bit, malloc limit: -1
16 
17   712 + 0   JSRuntime
18   488 + 0   JSContext
19    80 + 0   JSObject
20    40 + 0   JSString
21   136 + 0   JSFunctionBytecode
22 
23 JSObject classes
24 
25 NAME                    COUNT     SIZE
26 memory allocated          548    54711  (99.8 per block)
27 memory used               398    31337  (8 overhead, 58.7 average slack)
28 atoms                     307    22887  (74.6 per atom)
29 strings                     1       46  (46.0 per string)
30 Success!

 

 

 

本文地址:https://www.cnblogs.com/wunaozai/p/17888426.html

系列目录:https://www.cnblogs.com/wunaozai/p/17853962.html

标签:集成,quickjs,http,ctx,JS,curl,js,data
From: https://www.cnblogs.com/wunaozai/p/17888426.html

相关文章

  • 手摸手入门Springboot2.7集成Swagger2.9.2
    环境介绍技术栈springboot+mybatis-plus+mysql+oracle+Swagger软件版本mysql8IDEAIntelliJIDEA2022.2.1JDK1.8SpringBoot2.7.13mybatis-plus3.5.3.2REST软件架构风格REST即表述性状态传递(英文:RepresentationalStateTransfer,简称REST,中文:表示层状态转移)是RoyFielding博士在20......
  • Spring Boot 3 集成 MyBatis详解
    MyBatis是一款开源的持久层框架,它极大地简化了与数据库的交互流程。与类似Hibernate的ORM框架不同,MyBatis更具灵活性,允许开发者直接使用SQL语句与数据库进行交互。SpringBoot和MyBatis分别是两个功能强大的框架,它们的协同使用可以极大地简化数据访问层的开发,提高整体的开发效率。......
  • 前端歌谣-第五拾一课-node之http模块之stream流
    前言我是歌谣微信公众号关注前端小歌谣一起学习前端知识今天继续给大家讲解node中stream模块的讲解案例constfs=require("fs")constrs=fs.createReadStream("./1.txt","utf-8")rs.on("data",(chunk)=>{console.log(chunk)})rs.on("end",()=>{......
  • 前端歌谣-第五十课-node之http模块之fs模块(续)
    前言我是歌谣微信公众号关注前端小歌谣一起学习前端知识今天继续给大家讲解node中fs模块的讲解同步创建constfs=require("fs")fs.mkdirSync("./geyao1",(err)=>{console.log(err)if(err&&err.code==="EEXIST"){console.log("目录已经存在")}})运行......
  • Http的演进
    Http的演进Http在1.1版本之前具有无状态的特点,每次请求都需要通过TCP三次握手四次挥手与服务器重新建立连接。比如某个客户端在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户请求,所以每次需要重新响应请求、耗费不必要的时间和流量。为了节省资源消耗,Http也进行了......
  • Python神器!WEB自动化测试集成工具 DrissionPage
    Python神器!WEB自动化测试集成工具DrissionPage 一、前言用requests做数据采集面对要登录的网站时,要分析数据包、JS源码,构造复杂的请求,往往还要应付验证码、JS混淆、签名参数等反爬手段,门槛较高。若数据是由JS计算生成的,还须重现计算过程,体验不好,开发效率不高。使用浏览器,......
  • 模拟集成电路设计系列博客——4.2.2 线性区晶体管跨导器
    4.2.2线性区晶体管跨导器本节我们将讨论使用工作在线性区的晶体管构成的跨导器。需要说明的是,在下面介绍的电路中,并不是所有的晶体管都处于先行区。一些晶体管被偏置在饱和区,但是电路的跨导由一到两个被偏置在线性区的关键晶体管来决定。首先我们会议一下对于n管来说线性区的电......
  • Netty内置的http报文解码流程
    netty解码netty通过内置处理器HttpRequestDecoder和HttpObjectAggregator对Http请求报文进行解码之后,Netty会将Http请求封装成一个FullHttpRequest实例,然后发送给下一站。Netty内置的与Http请求报文相对应的类大致有如下几个:(1)FullHttpRequest:包含整个Http请求的信息,包含对Htt......
  • Apache HTTP Server 的安装与配置
    一、概要1.环境(1)RockyLinux9.3二、安装与配置1.安装(1)安装sudodnfinstallhttpd-y(2)服务sudosystemctlstarthttpdsudosystemctlenablehttpdsystemctlstatushttpd(3)防火墙sudofirewall-cmd--add-service={http,https}--permanentsudo......
  • 前端歌谣-第四拾九课-node之http模块之fs模块
    前言我是歌谣微信公众号关注前端小歌谣一起学习前端知识今天继续给大家讲解node中fs模块的讲解创建文件constfs=require("fs")fs.mkdir("./geyao",(err)=>{console.log(err)if(err&&err.code==="EEXIST"){console.log("目录已经存在")}})运行结果重命......