v0.4.8 - Implement web server functionality for embedded admin interface - serve HTML/CSS/JS from /api/ endpoint with proper MIME types, CORS headers, and performance optimizations
This commit is contained in:
161
src/websockets.c
161
src/websockets.c
@@ -26,6 +26,8 @@
|
||||
#include "sql_schema.h" // Embedded database schema
|
||||
#include "websockets.h" // WebSocket structures and constants
|
||||
#include "subscriptions.h" // Subscription structures and functions
|
||||
#include "embedded_web_content.h" // Embedded web content
|
||||
#include "api.h" // API for embedded files
|
||||
|
||||
// Forward declarations for logging functions
|
||||
void log_info(const char* message);
|
||||
@@ -47,6 +49,9 @@ void handle_nip42_auth_challenge_response(struct lws* wsi, struct per_session_da
|
||||
// Forward declarations for NIP-11 relay information handling
|
||||
int handle_nip11_http_request(struct lws* wsi, const char* accept_header);
|
||||
|
||||
// Forward declarations for embedded file handling
|
||||
int handle_embedded_file_writeable(struct lws* wsi);
|
||||
|
||||
// Forward declarations for database functions
|
||||
int store_event(cJSON* event);
|
||||
|
||||
@@ -105,80 +110,132 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
// Handle NIP-11 relay information requests (HTTP GET to root path)
|
||||
// Handle HTTP requests
|
||||
{
|
||||
char *requested_uri = (char *)in;
|
||||
log_info("HTTP request received");
|
||||
|
||||
|
||||
// Check if this is an OPTIONS request
|
||||
char method[16] = {0};
|
||||
int method_len = lws_hdr_copy(wsi, method, sizeof(method) - 1, WSI_TOKEN_GET_URI);
|
||||
if (method_len > 0) {
|
||||
method[method_len] = '\0';
|
||||
if (strcmp(method, "OPTIONS") == 0) {
|
||||
// Handle OPTIONS request with CORS headers
|
||||
unsigned char buf[LWS_PRE + 1024];
|
||||
unsigned char *p = &buf[LWS_PRE];
|
||||
unsigned char *start = p;
|
||||
unsigned char *end = &buf[sizeof(buf) - 1];
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) return -1;
|
||||
if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-origin:", (unsigned char*)"*", 1, &p, end)) return -1;
|
||||
if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-headers:", (unsigned char*)"content-type, accept", 20, &p, end)) return -1;
|
||||
if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-methods:", (unsigned char*)"GET, OPTIONS", 12, &p, end)) return -1;
|
||||
if (lws_add_http_header_by_name(wsi, (unsigned char*)"connection:", (unsigned char*)"close", 5, &p, end)) return -1;
|
||||
|
||||
if (lws_finalize_http_header(wsi, &p, end)) return -1;
|
||||
if (lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is a GET request to the root path
|
||||
if (strcmp(requested_uri, "/") == 0) {
|
||||
// Get Accept header
|
||||
char accept_header[256] = {0};
|
||||
int header_len = lws_hdr_copy(wsi, accept_header, sizeof(accept_header) - 1, WSI_TOKEN_HTTP_ACCEPT);
|
||||
|
||||
|
||||
if (header_len > 0) {
|
||||
accept_header[header_len] = '\0';
|
||||
|
||||
// Handle NIP-11 request
|
||||
if (handle_nip11_http_request(wsi, accept_header) == 0) {
|
||||
return 0; // Successfully handled
|
||||
|
||||
// Check if this is a NIP-11 request
|
||||
int is_nip11_request = (strstr(accept_header, "application/nostr+json") != NULL);
|
||||
|
||||
if (is_nip11_request) {
|
||||
// Handle NIP-11 request
|
||||
if (handle_nip11_http_request(wsi, accept_header) == 0) {
|
||||
return 0; // Successfully handled
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_warning("HTTP request without Accept header");
|
||||
}
|
||||
|
||||
// Return 404 for other requests
|
||||
|
||||
// Root path without NIP-11 Accept header - return 404
|
||||
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return 404 for non-root paths
|
||||
|
||||
// Check for embedded API files
|
||||
if (handle_embedded_file_request(wsi, requested_uri) == 0) {
|
||||
return 0; // Successfully handled
|
||||
}
|
||||
|
||||
// Return 404 for other paths
|
||||
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
// Handle NIP-11 HTTP body transmission with proper buffer management
|
||||
// Handle HTTP body transmission for NIP-11 or embedded files
|
||||
{
|
||||
struct nip11_session_data* session_data = (struct nip11_session_data*)lws_wsi_user(wsi);
|
||||
if (session_data && session_data->headers_sent && !session_data->body_sent) {
|
||||
// Allocate buffer for JSON body transmission
|
||||
unsigned char *json_buf = malloc(LWS_PRE + session_data->json_length);
|
||||
if (!json_buf) {
|
||||
log_error("Failed to allocate buffer for NIP-11 body transmission");
|
||||
// Clean up session data
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
return -1;
|
||||
void* user_data = lws_wsi_user(wsi);
|
||||
char debug_msg[256];
|
||||
snprintf(debug_msg, sizeof(debug_msg), "HTTP_WRITEABLE: user_data=%p", user_data);
|
||||
log_info(debug_msg);
|
||||
if (user_data) {
|
||||
int type = *(int*)user_data;
|
||||
if (type == 0) {
|
||||
// NIP-11
|
||||
struct nip11_session_data* session_data = (struct nip11_session_data*)user_data;
|
||||
snprintf(debug_msg, sizeof(debug_msg), "NIP-11: session_data=%p, type=%d, json_length=%zu, headers_sent=%d, body_sent=%d",
|
||||
session_data, session_data->type, session_data->json_length, session_data->headers_sent, session_data->body_sent);
|
||||
log_info(debug_msg);
|
||||
if (session_data->headers_sent && !session_data->body_sent) {
|
||||
snprintf(debug_msg, sizeof(debug_msg), "NIP-11: Attempting to send body, json_length=%zu", session_data->json_length);
|
||||
log_info(debug_msg);
|
||||
// Allocate buffer for JSON body transmission (no LWS_PRE needed for body)
|
||||
unsigned char *json_buf = malloc(session_data->json_length);
|
||||
if (!json_buf) {
|
||||
log_error("Failed to allocate buffer for NIP-11 body transmission");
|
||||
// Clean up session data
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
return -1;
|
||||
}
|
||||
log_info("NIP-11: Buffer allocated successfully");
|
||||
|
||||
// Copy JSON data to buffer
|
||||
memcpy(json_buf, session_data->json_buffer, session_data->json_length);
|
||||
|
||||
// Write JSON body
|
||||
int write_result = lws_write(wsi, json_buf, session_data->json_length, LWS_WRITE_HTTP);
|
||||
|
||||
// Free the transmission buffer immediately (it's been copied by libwebsockets)
|
||||
free(json_buf);
|
||||
|
||||
if (write_result < 0) {
|
||||
log_error("Failed to write NIP-11 JSON body");
|
||||
// Clean up session data
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Mark body as sent and clean up session data
|
||||
session_data->body_sent = 1;
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
|
||||
log_success("NIP-11 relay information served successfully");
|
||||
return 0; // Close connection after successful transmission
|
||||
}
|
||||
} else if (type == 1) {
|
||||
// Embedded file
|
||||
return handle_embedded_file_writeable(wsi);
|
||||
}
|
||||
|
||||
// Copy JSON data to buffer
|
||||
memcpy(json_buf + LWS_PRE, session_data->json_buffer, session_data->json_length);
|
||||
|
||||
// Write JSON body
|
||||
int write_result = lws_write(wsi, json_buf + LWS_PRE, session_data->json_length, LWS_WRITE_HTTP);
|
||||
|
||||
// Free the transmission buffer immediately (it's been copied by libwebsockets)
|
||||
free(json_buf);
|
||||
|
||||
if (write_result < 0) {
|
||||
log_error("Failed to write NIP-11 JSON body");
|
||||
// Clean up session data
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Mark body as sent and clean up session data
|
||||
session_data->body_sent = 1;
|
||||
free(session_data->json_buffer);
|
||||
free(session_data);
|
||||
lws_set_wsi_user(wsi, NULL);
|
||||
|
||||
log_success("NIP-11 relay information served successfully");
|
||||
return 0; // Close connection after successful transmission
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user