main.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include <algorithm>
  2. #include <set>
  3. extern "C"
  4. {
  5. #include <lua.h>
  6. #include <lauxlib.h>
  7. }
  8. #include "../common/HTTPS.h"
  9. #include "../common/config.h"
  10. static std::set<std::string> validMethod = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"};
  11. static std::string w_checkstring(lua_State *L, int idx)
  12. {
  13. size_t len;
  14. const char *str = luaL_checklstring(L, idx, &len);
  15. return std::string(str, len);
  16. }
  17. static void w_pushstring(lua_State *L, const std::string &str)
  18. {
  19. lua_pushlstring(L, str.data(), str.size());
  20. }
  21. static void w_readheaders(lua_State *L, int idx, HTTPSClient::header_map &headers)
  22. {
  23. if (idx < 0)
  24. idx += lua_gettop(L) + 1;
  25. lua_pushnil(L);
  26. while (lua_next(L, idx))
  27. {
  28. auto header = w_checkstring(L, -2);
  29. headers[header] = w_checkstring(L, -1);
  30. lua_pop(L, 1);
  31. }
  32. lua_pop(L, 1);
  33. }
  34. static std::string w_optmethod(lua_State *L, int idx, const std::string &defaultMethod)
  35. {
  36. if (lua_isnoneornil(L, idx))
  37. return defaultMethod;
  38. std::string str = w_checkstring(L, idx);
  39. std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return toupper(c); });
  40. if (validMethod.find(str) == validMethod.end())
  41. luaL_argerror(L, idx, "expected one of \"get\", \"head\", \"post\", \"put\", \"delete\", or \"patch\"");
  42. return str;
  43. }
  44. static int w_request(lua_State *L)
  45. {
  46. auto url = w_checkstring(L, 1);
  47. HTTPSClient::Request req(url);
  48. bool advanced = false;
  49. if (lua_istable(L, 2))
  50. {
  51. advanced = true;
  52. std::string defaultMethod = "GET";
  53. lua_getfield(L, 2, "data");
  54. if (!lua_isnoneornil(L, -1))
  55. {
  56. req.postdata = w_checkstring(L, -1);
  57. defaultMethod = "POST";
  58. }
  59. lua_pop(L, 1);
  60. lua_getfield(L, 2, "method");
  61. req.method = w_optmethod(L, -1, defaultMethod);
  62. lua_pop(L, 1);
  63. lua_getfield(L, 2, "headers");
  64. if (!lua_isnoneornil(L, -1))
  65. w_readheaders(L, -1, req.headers);
  66. lua_pop(L, 1);
  67. }
  68. HTTPSClient::Reply reply;
  69. try
  70. {
  71. reply = request(req);
  72. }
  73. catch (const std::exception& e)
  74. {
  75. std::string errorMessage = e.what();
  76. lua_pushnil(L);
  77. lua_pushstring(L, errorMessage.c_str());
  78. return 2;
  79. }
  80. lua_pushinteger(L, reply.responseCode);
  81. w_pushstring(L, reply.body);
  82. if (advanced)
  83. {
  84. lua_newtable(L);
  85. for (const auto &header : reply.headers)
  86. {
  87. w_pushstring(L, header.first);
  88. w_pushstring(L, header.second);
  89. lua_settable(L, -3);
  90. }
  91. }
  92. return advanced ? 3 : 2;
  93. }
  94. extern "C" int HTTPS_DLLEXPORT luaopen_https(lua_State *L)
  95. {
  96. lua_newtable(L);
  97. lua_pushcfunction(L, w_request);
  98. lua_setfield(L, -2, "request");
  99. return 1;
  100. }