| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #include <lua.hpp>
- // Sorry for the ifdef soup ahead
- #include "common/config.h"
- #include "common/HTTPSClient.h"
- #include "common/ConnectionClient.h"
- #ifdef USE_CURL_BACKEND
- # include "generic/CurlClient.h"
- #endif
- #ifdef USE_OPENSSL_BACKEND
- # include "generic/OpenSSLConnection.h"
- #endif
- #ifdef USE_SCHANNEL_BACKEND
- # include "windows/SChannelConnection.h"
- #endif
- #ifdef USE_NSURL_BACKEND
- # include "macos/NSURLClient.h"
- #endif
- #ifdef USE_ANDROID_BACKEND
- # include "android/AndroidClient.h"
- #endif
- #ifdef USE_CURL_BACKEND
- static CurlClient curlclient;
- #endif
- #ifdef USE_OPENSSL_BACKEND
- static ConnectionClient<OpenSSLConnection> opensslclient;
- #endif
- #ifdef USE_SCHANNEL_BACKEND
- static ConnectionClient<SChannelConnection> schannelclient;
- #endif
- #ifdef USE_NSURL_BACKEND
- static NSURLClient nsurlclient;
- #endif
- #ifdef USE_ANDROID_BACKEND
- static AndroidClient androidclient;
- #endif
- static HTTPSClient *clients[] = {
- #ifdef USE_CURL_BACKEND
- &curlclient,
- #endif
- #ifdef USE_OPENSSL_BACKEND
- &opensslclient,
- #endif
- #ifdef USE_SCHANNEL_BACKEND
- &schannelclient,
- #endif
- #ifdef USE_NSURL_BACKEND
- &nsurlclient,
- #endif
- #ifdef USE_ANDROID_BACKEND
- &androidclient,
- #endif
- nullptr,
- };
- static std::string w_checkstring(lua_State *L, int idx)
- {
- size_t len;
- const char *str = luaL_checklstring(L, idx, &len);
- return std::string(str, len);
- }
- static void w_pushstring(lua_State *L, const std::string &str)
- {
- lua_pushlstring(L, str.data(), str.size());
- }
- static void w_readheaders(lua_State *L, int idx, HTTPSClient::header_map &headers)
- {
- if (idx < 0)
- idx += lua_gettop(L) + 1;
- lua_pushnil(L);
- while (lua_next(L, idx))
- {
- auto header = w_checkstring(L, -2);
- headers[header] = w_checkstring(L, -1);
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- }
- static HTTPSClient::Request::Method w_optmethod(lua_State *L, int idx, HTTPSClient::Request::Method defaultMethod)
- {
- if (lua_isnoneornil(L, idx))
- return defaultMethod;
- auto str = w_checkstring(L, idx);
- if (str == "get")
- return HTTPSClient::Request::GET;
- else if (str == "post")
- return HTTPSClient::Request::POST;
- else
- luaL_argerror(L, idx, "expected one of \"get\" or \"set\"");
- return defaultMethod;
- }
- static int w_request(lua_State *L)
- {
- auto url = w_checkstring(L, 1);
- HTTPSClient::Request req(url);
- std::string errorMessage("No applicable implementation found");
- bool foundClient = false;
- bool advanced = false;
- if (lua_istable(L, 2))
- {
- advanced = true;
- HTTPSClient::Request::Method defaultMethod = HTTPSClient::Request::GET;
- lua_getfield(L, 2, "data");
- if (!lua_isnoneornil(L, -1))
- {
- req.postdata = w_checkstring(L, -1);
- defaultMethod = HTTPSClient::Request::POST;
- }
- lua_pop(L, 1);
- lua_getfield(L, 2, "method");
- req.method = w_optmethod(L, -1, defaultMethod);
- lua_pop(L, 1);
- lua_getfield(L, 2, "headers");
- if (!lua_isnoneornil(L, -1))
- w_readheaders(L, -1, req.headers);
- lua_pop(L, 1);
- }
- for (size_t i = 0; clients[i]; ++i)
- {
- HTTPSClient &client = *clients[i];
- HTTPSClient::Reply reply;
- if (!client.valid())
- continue;
- try
- {
- reply = client.request(req);
- }
- catch(const std::exception& e)
- {
- errorMessage = e.what();
- break;
- }
-
- lua_pushinteger(L, reply.responseCode);
- w_pushstring(L, reply.body);
- if (advanced)
- {
- lua_newtable(L);
- for (const auto &header : reply.headers)
- {
- w_pushstring(L, header.first);
- w_pushstring(L, header.second);
- lua_settable(L, -3);
- }
- }
- foundClient = true;
- break;
- }
- if (!foundClient)
- {
- lua_pushnil(L);
- lua_pushstring(L, errorMessage.c_str());
- }
- return (advanced && foundClient) ? 3 : 2;
- }
- extern "C" int DLLEXPORT luaopen_https(lua_State *L)
- {
- lua_newtable(L);
- lua_pushcfunction(L, w_request);
- lua_setfield(L, -2, "request");
- return 1;
- }
|