Send a valid HTTP response and shutdown the connection.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4679 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2023-12-17 17:44:54 +00:00
parent 067f546580
commit 7b3a9e0f63
3 changed files with 71 additions and 13 deletions

View File

@ -6,6 +6,7 @@
#include "picohttpparser.h"
#include "uv.h"
#include <assert.h>
#include <string.h>
#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(_WIN32)
@ -121,16 +122,6 @@ void _http_on_read(uv_stream_t* stream, ssize_t read_size, const uv_buf_t* buffe
.user_data = connection->user_data,
};
connection->callback(&request);
const char* payload = "HTTP/1.0 200 OK\r\nContent-Length: 13\r\n\r\nHello, world!";
uv_write_t* write = tf_malloc(sizeof(uv_write_t) + strlen(payload));
*write = (uv_write_t) { 0 };
memcpy(write + 1, payload, strlen(payload));
int r = uv_write(write, stream, &(uv_buf_t) { .base = (char*)(write + 1), .len = strlen(payload) }, 1, _http_on_write);
if (r)
{
tf_printf("uv_write: %s\n", uv_strerror(r));
}
}
}
else
@ -231,3 +222,56 @@ void tf_http_destroy(tf_http_t* http)
{
tf_free(http);
}
static const char* _http_status_text(int status)
{
switch (status)
{
case 200: return "OK";
case 404: return "File not found";
default: return "Unknown";
}
}
static void _http_on_shutdown(uv_shutdown_t* request, int status)
{
tf_free(request);
}
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, void* body, size_t content_length)
{
const char* status_text = _http_status_text(status);
/* HTTP/1.x 200 OK\r\n */
int headers_length = 8 + 1 + 3 + 1 + strlen(status_text) + 2;
for (int i = 0; i < headers_count; i += 2)
{
/* Key: Value\r\n */
headers_length += strlen(headers[i]) + 2 + strlen(headers[i + 1]) + 2;
}
/* \r\n */
headers_length += 2;
uv_write_t* write = tf_malloc(sizeof(uv_write_t) + headers_length + content_length + 1);
*write = (uv_write_t) { .data = request->connection };
char* buffer = (char*)(write + 1);
int offset = snprintf(buffer, headers_length + 1, "HTTP/1.0 %03d %s\r\n", status, status_text);
for (int i = 0; i < headers_count; i += 2)
{
offset += snprintf(buffer + offset, headers_length + 1 - offset, "%s: %s\r\n", headers[i], headers[i + 1]);
}
offset += snprintf(buffer + offset, headers_length + 1 - offset, "\r\n");
assert(offset == headers_length);
if (content_length)
{
memcpy(buffer + offset, body, content_length);
}
int r = uv_write(write, (uv_stream_t*)&request->connection->tcp, &(uv_buf_t) { .base = buffer, .len = headers_length + content_length }, 1, _http_on_write);
if (r)
{
tf_printf("uv_write: %s\n", uv_strerror(r));
}
uv_shutdown_t* shutdown_request = tf_malloc(sizeof(uv_shutdown_t));
*shutdown_request = (uv_shutdown_t) { .data = request };
uv_shutdown(shutdown_request, (uv_stream_t*)&request->connection->tcp, _http_on_shutdown);
}