#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