mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-10 18:34:21 +02:00
Return HTTP response headers to Lua
Also accept request headers in a string array format, beside the old string-string dictionary format.
This commit is contained in:
@@ -77,10 +77,10 @@ namespace http
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Request::AddHeader(ByteString name, ByteString value)
|
void Request::AddHeader(ByteString header)
|
||||||
{
|
{
|
||||||
#ifndef NOHTTP
|
#ifndef NOHTTP
|
||||||
headers = curl_slist_append(headers, (name + ": " + value).c_str());
|
headers = curl_slist_append(headers, header.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,17 +131,32 @@ namespace http
|
|||||||
{
|
{
|
||||||
if (session.size())
|
if (session.size())
|
||||||
{
|
{
|
||||||
AddHeader("X-Auth-User-Id", ID);
|
AddHeader("X-Auth-User-Id: " + ID);
|
||||||
AddHeader("X-Auth-Session-Key", session);
|
AddHeader("X-Auth-Session-Key: " + session);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddHeader("X-Auth-User", ID);
|
AddHeader("X-Auth-User: " + ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NOHTTP
|
#ifndef NOHTTP
|
||||||
|
size_t Request::HeaderDataHandler(char *ptr, size_t size, size_t count, void *userdata)
|
||||||
|
{
|
||||||
|
Request *req = (Request *)userdata;
|
||||||
|
auto actual_size = size * count;
|
||||||
|
if (actual_size >= 2 && ptr[actual_size - 2] == '\r' && ptr[actual_size - 1] == '\n')
|
||||||
|
{
|
||||||
|
if (actual_size > 2) // don't include header list terminator (but include the status line)
|
||||||
|
{
|
||||||
|
req->response_headers.push_back(ByteString(ptr, ptr + actual_size - 2));
|
||||||
|
}
|
||||||
|
return actual_size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t Request::WriteDataHandler(char *ptr, size_t size, size_t count, void *userdata)
|
size_t Request::WriteDataHandler(char *ptr, size_t size, size_t count, void *userdata)
|
||||||
{
|
{
|
||||||
Request *req = (Request *)userdata;
|
Request *req = (Request *)userdata;
|
||||||
@@ -231,6 +246,9 @@ namespace http
|
|||||||
curl_easy_setopt(easy, CURLOPT_PRIVATE, (void *)this);
|
curl_easy_setopt(easy, CURLOPT_PRIVATE, (void *)this);
|
||||||
curl_easy_setopt(easy, CURLOPT_USERAGENT, user_agent.c_str());
|
curl_easy_setopt(easy, CURLOPT_USERAGENT, user_agent.c_str());
|
||||||
|
|
||||||
|
curl_easy_setopt(easy, CURLOPT_HEADERDATA, (void *)this);
|
||||||
|
curl_easy_setopt(easy, CURLOPT_HEADERFUNCTION, Request::HeaderDataHandler);
|
||||||
|
|
||||||
curl_easy_setopt(easy, CURLOPT_WRITEDATA, (void *)this);
|
curl_easy_setopt(easy, CURLOPT_WRITEDATA, (void *)this);
|
||||||
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, Request::WriteDataHandler);
|
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, Request::WriteDataHandler);
|
||||||
}
|
}
|
||||||
@@ -245,7 +263,7 @@ namespace http
|
|||||||
|
|
||||||
|
|
||||||
// finish the request (if called before the request is done, this will block)
|
// finish the request (if called before the request is done, this will block)
|
||||||
ByteString Request::Finish(int *status_out)
|
ByteString Request::Finish(int *status_out, std::vector<ByteString> *headers_out)
|
||||||
{
|
{
|
||||||
#ifndef NOHTTP
|
#ifndef NOHTTP
|
||||||
if (CheckCanceled())
|
if (CheckCanceled())
|
||||||
@@ -263,6 +281,10 @@ namespace http
|
|||||||
{
|
{
|
||||||
*status_out = status;
|
*status_out = status;
|
||||||
}
|
}
|
||||||
|
if (headers_out)
|
||||||
|
{
|
||||||
|
*headers_out = std::move(response_headers);
|
||||||
|
}
|
||||||
response_out = std::move(response_body);
|
response_out = std::move(response_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@ namespace http
|
|||||||
{
|
{
|
||||||
#ifndef NOHTTP
|
#ifndef NOHTTP
|
||||||
ByteString uri;
|
ByteString uri;
|
||||||
|
std::vector<ByteString> response_headers;
|
||||||
ByteString response_body;
|
ByteString response_body;
|
||||||
|
|
||||||
CURL *easy;
|
CURL *easy;
|
||||||
@@ -58,19 +59,20 @@ namespace http
|
|||||||
|
|
||||||
std::condition_variable done_cv;
|
std::condition_variable done_cv;
|
||||||
|
|
||||||
static size_t WriteDataHandler(char * ptr, size_t size, size_t count, void * userdata);
|
static size_t HeaderDataHandler(char *ptr, size_t size, size_t count, void *userdata);
|
||||||
|
static size_t WriteDataHandler(char *ptr, size_t size, size_t count, void *userdata);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Request(ByteString uri);
|
Request(ByteString uri);
|
||||||
virtual ~Request();
|
virtual ~Request();
|
||||||
|
|
||||||
void AddHeader(ByteString name, ByteString value);
|
void AddHeader(ByteString header);
|
||||||
void AddPostData(std::map<ByteString, ByteString> data);
|
void AddPostData(std::map<ByteString, ByteString> data);
|
||||||
void AuthHeaders(ByteString ID, ByteString session);
|
void AuthHeaders(ByteString ID, ByteString session);
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
ByteString Finish(int *status);
|
ByteString Finish(int *status, std::vector<ByteString> *headers = nullptr);
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
void CheckProgress(int *total, int *done);
|
void CheckProgress(int *total, int *done);
|
||||||
|
@@ -4048,13 +4048,13 @@ class RequestHandle
|
|||||||
bool dead;
|
bool dead;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RequestHandle(ByteString &uri, bool isPost, std::map<ByteString, ByteString> &post_data, std::map<ByteString, ByteString> &headers)
|
RequestHandle(ByteString &uri, bool isPost, std::map<ByteString, ByteString> &post_data, std::vector<ByteString> &headers)
|
||||||
{
|
{
|
||||||
dead = false;
|
dead = false;
|
||||||
request = new http::Request(uri);
|
request = new http::Request(uri);
|
||||||
for (auto &header : headers)
|
for (auto &header : headers)
|
||||||
{
|
{
|
||||||
request->AddHeader(header.first, header.second);
|
request->AddHeader(header);
|
||||||
}
|
}
|
||||||
if (isPost)
|
if (isPost)
|
||||||
request->AddPostData(post_data);
|
request->AddPostData(post_data);
|
||||||
@@ -4096,14 +4096,14 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString Finish(int *status_out)
|
ByteString Finish(int &status_out, std::vector<ByteString> &headers)
|
||||||
{
|
{
|
||||||
ByteString data;
|
ByteString data;
|
||||||
if (!dead)
|
if (!dead)
|
||||||
{
|
{
|
||||||
if (request->CheckDone())
|
if (request->CheckDone())
|
||||||
{
|
{
|
||||||
data = request->Finish(status_out);
|
data = request->Finish(&status_out, &headers);
|
||||||
dead = true;
|
dead = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4166,10 +4166,17 @@ static int http_request_finish(lua_State *l)
|
|||||||
if (!rh->Dead())
|
if (!rh->Dead())
|
||||||
{
|
{
|
||||||
int status_out;
|
int status_out;
|
||||||
ByteString data = rh->Finish(&status_out);
|
std::vector<ByteString> headers;
|
||||||
|
ByteString data = rh->Finish(status_out, headers);
|
||||||
lua_pushlstring(l, data.c_str(), data.size());
|
lua_pushlstring(l, data.c_str(), data.size());
|
||||||
lua_pushinteger(l, status_out);
|
lua_pushinteger(l, status_out);
|
||||||
return 2;
|
lua_newtable(l);
|
||||||
|
for (auto i = 0; i < int(headers.size()); ++i)
|
||||||
|
{
|
||||||
|
lua_pushlstring(l, headers[i].data(), headers[i].size());
|
||||||
|
lua_rawseti(l, -2, i + 1);
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4192,15 +4199,30 @@ static int http_request(lua_State *l, bool isPost)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ByteString, ByteString> headers;
|
std::vector<ByteString> headers;
|
||||||
if (lua_istable(l, isPost ? 3 : 2))
|
auto headersIndex = isPost ? 3 : 2;
|
||||||
|
if (lua_istable(l, headersIndex))
|
||||||
{
|
{
|
||||||
lua_pushnil(l);
|
auto size = lua_objlen(l, headersIndex);
|
||||||
while (lua_next(l, isPost ? 3 : 2))
|
if (size)
|
||||||
{
|
{
|
||||||
lua_pushvalue(l, -2);
|
for (auto i = 0U; i < size; ++i)
|
||||||
headers.emplace(lua_tostring(l, -1), lua_tostring(l, -2));
|
{
|
||||||
lua_pop(l, 2);
|
lua_rawgeti(l, headersIndex, i + 1);
|
||||||
|
headers.push_back(lua_tostring(l, -1));
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// old dictionary format
|
||||||
|
lua_pushnil(l);
|
||||||
|
while (lua_next(l, headersIndex))
|
||||||
|
{
|
||||||
|
lua_pushvalue(l, -2);
|
||||||
|
headers.push_back(lua_tostring(l, -1) + ByteString(": ") + lua_tostring(l, -2));
|
||||||
|
lua_pop(l, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle));
|
auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle));
|
||||||
|
Reference in New Issue
Block a user