mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 12:30:19 +00:00
103 lines
3.0 KiB
C++
103 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
#include "obj.h"
|
|
#include "vm.h"
|
|
#include "_generated.h"
|
|
|
|
#if __has_include("httplib.h")
|
|
#include "httplib.h"
|
|
|
|
namespace pkpy {
|
|
|
|
inline void add_module_requests(VM* vm){
|
|
static StrName m_requests("requests");
|
|
static StrName m_Response("Response");
|
|
PyObject* mod = vm->new_module(m_requests);
|
|
CodeObject_ code = vm->compile(kPythonLibs["requests"], "requests.py", EXEC_MODE);
|
|
vm->_exec(code, mod);
|
|
|
|
vm->bind_func<4>(mod, "_request", [](VM* vm, ArgsView args){
|
|
Str method = CAST(Str&, args[0]);
|
|
Str url = CAST(Str&, args[1]);
|
|
PyObject* headers = args[2]; // a dict object
|
|
PyObject* body = args[3]; // a bytes object
|
|
|
|
if(url.index("http://") != 0){
|
|
vm->ValueError("url must start with http://");
|
|
}
|
|
|
|
for(char c: url){
|
|
switch(c){
|
|
case '.':
|
|
case '-':
|
|
case '_':
|
|
case '~':
|
|
case ':':
|
|
case '/':
|
|
break;
|
|
default:
|
|
if(!isalnum(c)){
|
|
vm->ValueError(fmt("invalid character in url: '", c, "'"));
|
|
}
|
|
}
|
|
}
|
|
|
|
int slash = url.index("/", 7);
|
|
Str path = "/";
|
|
if(slash != -1){
|
|
path = url.substr(slash);
|
|
url = url.substr(0, slash);
|
|
if(path.empty()) path = "/";
|
|
}
|
|
|
|
httplib::Client client(url.str());
|
|
|
|
httplib::Headers h;
|
|
if(headers != vm->None){
|
|
List list = CAST(List&, headers);
|
|
for(auto& item : list){
|
|
Tuple t = CAST(Tuple&, item);
|
|
Str key = CAST(Str&, t[0]);
|
|
Str value = CAST(Str&, t[1]);
|
|
h.emplace(key.str(), value.str());
|
|
}
|
|
}
|
|
|
|
auto _to_resp = [=](const httplib::Result& res){
|
|
return vm->call(
|
|
vm->_modules[m_requests]->attr(m_Response),
|
|
VAR(res->status),
|
|
VAR(res->reason),
|
|
VAR(Bytes(res->body))
|
|
);
|
|
};
|
|
|
|
if(method == "GET"){
|
|
httplib::Result res = client.Get(path.str(), h);
|
|
return _to_resp(res);
|
|
}else if(method == "POST"){
|
|
Bytes b = CAST(Bytes&, body);
|
|
httplib::Result res = client.Post(path.str(), h, b.data(), b.size(), "application/octet-stream");
|
|
return _to_resp(res);
|
|
}else if(method == "PUT"){
|
|
Bytes b = CAST(Bytes&, body);
|
|
httplib::Result res = client.Put(path.str(), h, b.data(), b.size(), "application/octet-stream");
|
|
return _to_resp(res);
|
|
}else if(method == "DELETE"){
|
|
httplib::Result res = client.Delete(path.str(), h);
|
|
return _to_resp(res);
|
|
}else{
|
|
vm->ValueError("invalid method");
|
|
}
|
|
UNREACHABLE();
|
|
});
|
|
}
|
|
|
|
} // namespace pkpy
|
|
|
|
#else
|
|
|
|
inline void add_module_requests(void* vm){ }
|
|
|
|
#endif |