parent
099f726b0a
commit
383f325547
|
@ -14,7 +14,7 @@ void route_test(struct uh_connection *con)
|
||||||
struct uh_value *header_host = uh_get_header(con, "Host");
|
struct uh_value *header_host = uh_get_header(con, "Host");
|
||||||
struct uh_value *header_ua = uh_get_header(con, "User-Agent");
|
struct uh_value *header_ua = uh_get_header(con, "User-Agent");
|
||||||
|
|
||||||
uh_send_head(con, 200, -1, NULL);
|
uh_send_head(con, UH_STATUS_OK, -1, NULL);
|
||||||
uh_printf_chunk(con, "<h1>Hello World</h1>");
|
uh_printf_chunk(con, "<h1>Hello World</h1>");
|
||||||
uh_printf_chunk(con, "<h1>Libuhttp v%s</h1>", uh_version());
|
uh_printf_chunk(con, "<h1>Libuhttp v%s</h1>", uh_version());
|
||||||
uh_printf_chunk(con, "<h1>Url: %.*s</h1>", (int)url->len, url->at);
|
uh_printf_chunk(con, "<h1>Url: %.*s</h1>", (int)url->len, url->at);
|
||||||
|
|
88
src/uhttp.c
88
src/uhttp.c
|
@ -13,18 +13,65 @@ static struct {
|
||||||
int code;
|
int code;
|
||||||
const char *reason;
|
const char *reason;
|
||||||
} http_status_message[] = {
|
} http_status_message[] = {
|
||||||
{200, "OK"},
|
{UH_STATUS_CONTINUE, "Continue"},
|
||||||
{301, "Moved"},
|
{UH_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols"},
|
||||||
{302, "Found"},
|
{UH_STATUS_PROCESSING, "Processing"},
|
||||||
{400, "Bad Request"},
|
{UH_STATUS_OK, "OK"},
|
||||||
{401, "Unauthorized"},
|
{UH_STATUS_CREATED, "Created"},
|
||||||
{403, "Forbidden"},
|
{UH_STATUS_ACCEPTED, "Accepted"},
|
||||||
{404, "Not Found"},
|
{UH_STATUS_NON_AUTHORITATIVE_INFORMATION, "Non-Authoritative Information"},
|
||||||
{500, "Internal Server Error"},
|
{UH_STATUS_NO_CONTENT, "No Content"},
|
||||||
{501, "Not Implemented"},
|
{UH_STATUS_RESET_CONTENT, "Reset Content"},
|
||||||
{502, "Bad Gateway"},
|
{UH_STATUS_PARTIAL_CONTENT, "Partial Content"},
|
||||||
{503, "Service Unavailable"},
|
{UH_STATUS_MULTI_STATUS, "Multi-Status"},
|
||||||
{-1, NULL}
|
{UH_STATUS_ALREADY_REPORTED, "Already Reported"},
|
||||||
|
{UH_STATUS_IM_USED, "IM Used"},
|
||||||
|
{UH_STATUS_MULTIPLE_CHOICES, "Multiple Choices"},
|
||||||
|
{UH_STATUS_MOVED_PERMANENTLY, "Moved Permanently"},
|
||||||
|
{UH_STATUS_FOUND, "Found"},
|
||||||
|
{UH_STATUS_SEE_OTHER, "See Other"},
|
||||||
|
{UH_STATUS_NOT_MODIFIED, "Not Modified"},
|
||||||
|
{UH_STATUS_USE_PROXY, "Use Proxy"},
|
||||||
|
{UH_STATUS_TEMPORARY_REDIRECT, "Temporary Redirect"},
|
||||||
|
{UH_STATUS_PERMANENT_REDIRECT, "Permanent Redirect"},
|
||||||
|
{UH_STATUS_BAD_REQUEST, "Bad Request"},
|
||||||
|
{UH_STATUS_UNAUTHORIZED, "Unauthorized"},
|
||||||
|
{UH_STATUS_PAYMENT_REQUIRED, "Payment Required"},
|
||||||
|
{UH_STATUS_FORBIDDEN, "Forbidden"},
|
||||||
|
{UH_STATUS_NOT_FOUND, "Not Found"},
|
||||||
|
{UH_STATUS_METHOD_NOT_ALLOWED, "Method Not Allowed"},
|
||||||
|
{UH_STATUS_NOT_ACCEPTABLE, "Not Acceptable"},
|
||||||
|
{UH_STATUS_PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required"},
|
||||||
|
{UH_STATUS_REQUEST_TIMEOUT, "Request Timeout"},
|
||||||
|
{UH_STATUS_CONFLICT, "Conflict"},
|
||||||
|
{UH_STATUS_GONE, "Gone"},
|
||||||
|
{UH_STATUS_LENGTH_REQUIRED, "Length Required"},
|
||||||
|
{UH_STATUS_PRECONDITION_FAILED, "Precondition Failed"},
|
||||||
|
{UH_STATUS_PAYLOAD_TOO_LARGE, "Payload Too Large"},
|
||||||
|
{UH_STATUS_URI_TOO_LONG, "URI Too Long"},
|
||||||
|
{UH_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"},
|
||||||
|
{UH_STATUS_RANGE_NOT_SATISFIABLE, "Range Not Satisfiable"},
|
||||||
|
{UH_STATUS_EXPECTATION_FAILED, "Expectation Failed"},
|
||||||
|
{UH_STATUS_MISDIRECTED_REQUEST, "Misdirected Request"},
|
||||||
|
{UH_STATUS_UNPROCESSABLE_ENTITY, "Unprocessable Entity"},
|
||||||
|
{UH_STATUS_LOCKED, "Locked"},
|
||||||
|
{UH_STATUS_FAILED_DEPENDENCY, "Failed Dependency"},
|
||||||
|
{UH_STATUS_UPGRADE_REQUIRED, "Upgrade Required"},
|
||||||
|
{UH_STATUS_PRECONDITION_REQUIRED, "Precondition Required"},
|
||||||
|
{UH_STATUS_TOO_MANY_REQUESTS, "Too Many Requests"},
|
||||||
|
{UH_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large"},
|
||||||
|
{UH_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons"},
|
||||||
|
{UH_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error"},
|
||||||
|
{UH_STATUS_NOT_IMPLEMENTED, "Not Implemented"},
|
||||||
|
{UH_STATUS_BAD_GATEWAY, "Bad Gateway"},
|
||||||
|
{UH_STATUS_SERVICE_UNAVAILABLE, "Service Unavailable"},
|
||||||
|
{UH_STATUS_GATEWAY_TIMEOUT, "Gateway Timeout"},
|
||||||
|
{UH_STATUS_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported"},
|
||||||
|
{UH_STATUS_VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates"},
|
||||||
|
{UH_STATUS_INSUFFICIENT_STORAGE, "Insufficient Storage"},
|
||||||
|
{UH_STATUS_LOOP_DETECTED, "Loop Detected"},
|
||||||
|
{UH_STATUS_NOT_EXTENDED, "Not Extended"},
|
||||||
|
{UH_STATUS_NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required"}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *uh_version()
|
const char *uh_version()
|
||||||
|
@ -70,6 +117,7 @@ static void connection_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents
|
||||||
{
|
{
|
||||||
struct uh_connection *con = container_of(w, struct uh_connection, timer_watcher);
|
struct uh_connection *con = container_of(w, struct uh_connection, timer_watcher);
|
||||||
uh_log_info("connection(%p) timeout", con);
|
uh_log_info("connection(%p) timeout", con);
|
||||||
|
uh_send_error(con, UH_STATUS_REQUEST_TIMEOUT, NULL);
|
||||||
uh_connection_destroy(con);
|
uh_connection_destroy(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +209,7 @@ static int on_message_complete(http_parser *parser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uh_send_error(con, 404, NULL);
|
uh_send_error(con, UH_STATUS_NOT_FOUND, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -214,19 +262,23 @@ handshake_done:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(con->flags & UH_CON_PARSERING)) {
|
if (!(con->flags & UH_CON_PARSERING)) {
|
||||||
if (!memmem(buf->base, buf->len, "\r\n\r\n", 4))
|
if (!memmem(buf->base, buf->len, "\r\n\r\n", 4)) {
|
||||||
|
if (buf->len > UH_MAX_HTTP_HEAD_SIZE) {
|
||||||
|
uh_log_err("HTTP head size too big");
|
||||||
|
uh_send_error(con, UH_STATUS_BAD_REQUEST, NULL);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
con->flags |= UH_CON_PARSERING;
|
|
||||||
|
|
||||||
base = buf->base;
|
base = buf->base;
|
||||||
len = buf->len;
|
len = buf->len;
|
||||||
|
con->flags |= UH_CON_PARSERING;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsered = http_parser_execute(&con->parser, &parser_settings, base, len);
|
parsered = http_parser_execute(&con->parser, &parser_settings, base, len);
|
||||||
if (unlikely(parsered != len)){
|
if (unlikely(parsered != len)){
|
||||||
uh_log_err("http parser failed:%s", http_errno_description(HTTP_PARSER_ERRNO(&con->parser)));
|
uh_log_err("http parser failed:%s", http_errno_description(HTTP_PARSER_ERRNO(&con->parser)));
|
||||||
uh_send_error(con, 400, NULL);
|
uh_send_error(con, UH_STATUS_BAD_REQUEST, NULL);
|
||||||
} else {
|
} else {
|
||||||
ev_timer_mode(loop, &con->timer_watcher, UH_CONNECTION_TIMEOUT, 0);
|
ev_timer_mode(loop, &con->timer_watcher, UH_CONNECTION_TIMEOUT, 0);
|
||||||
}
|
}
|
||||||
|
@ -435,7 +487,7 @@ void uh_send_error(struct uh_connection *con, int code, const char *reason)
|
||||||
if (!reason)
|
if (!reason)
|
||||||
reason = get_http_status_message(code);
|
reason = get_http_status_message(code);
|
||||||
|
|
||||||
if (http_should_keep_alive(parser) && code < 400) {
|
if (http_should_keep_alive(parser) && code < UH_STATUS_BAD_REQUEST) {
|
||||||
uh_send_head(con, code, strlen(reason), "Content-Type: text/plain\r\nConnection: keep-alive\r\n");
|
uh_send_head(con, code, strlen(reason), "Content-Type: text/plain\r\nConnection: keep-alive\r\n");
|
||||||
} else {
|
} else {
|
||||||
uh_send_head(con, code, strlen(reason), "Content-Type: text/plain\r\nConnection: close\r\n");
|
uh_send_head(con, code, strlen(reason), "Content-Type: text/plain\r\nConnection: close\r\n");
|
||||||
|
|
63
src/uhttp.h
63
src/uhttp.h
|
@ -6,6 +6,69 @@
|
||||||
#include "uhttp_log.h"
|
#include "uhttp_log.h"
|
||||||
#include "uhttp_buf.h"
|
#include "uhttp_buf.h"
|
||||||
|
|
||||||
|
/* HTTP Status Codes */
|
||||||
|
enum uh_status {
|
||||||
|
UH_STATUS_CONTINUE = 100,
|
||||||
|
UH_STATUS_SWITCHING_PROTOCOLS = 101,
|
||||||
|
UH_STATUS_PROCESSING = 102,
|
||||||
|
UH_STATUS_OK = 200,
|
||||||
|
UH_STATUS_CREATED = 201,
|
||||||
|
UH_STATUS_ACCEPTED = 202,
|
||||||
|
UH_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
|
||||||
|
UH_STATUS_NO_CONTENT = 204,
|
||||||
|
UH_STATUS_RESET_CONTENT = 205,
|
||||||
|
UH_STATUS_PARTIAL_CONTENT = 206,
|
||||||
|
UH_STATUS_MULTI_STATUS = 207,
|
||||||
|
UH_STATUS_ALREADY_REPORTED = 208,
|
||||||
|
UH_STATUS_IM_USED = 226,
|
||||||
|
UH_STATUS_MULTIPLE_CHOICES = 300,
|
||||||
|
UH_STATUS_MOVED_PERMANENTLY = 301,
|
||||||
|
UH_STATUS_FOUND = 302,
|
||||||
|
UH_STATUS_SEE_OTHER = 303,
|
||||||
|
UH_STATUS_NOT_MODIFIED = 304,
|
||||||
|
UH_STATUS_USE_PROXY = 305,
|
||||||
|
UH_STATUS_TEMPORARY_REDIRECT = 307,
|
||||||
|
UH_STATUS_PERMANENT_REDIRECT = 308,
|
||||||
|
UH_STATUS_BAD_REQUEST = 400,
|
||||||
|
UH_STATUS_UNAUTHORIZED = 401,
|
||||||
|
UH_STATUS_PAYMENT_REQUIRED = 402,
|
||||||
|
UH_STATUS_FORBIDDEN = 403,
|
||||||
|
UH_STATUS_NOT_FOUND = 404,
|
||||||
|
UH_STATUS_METHOD_NOT_ALLOWED = 405,
|
||||||
|
UH_STATUS_NOT_ACCEPTABLE = 406,
|
||||||
|
UH_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
|
||||||
|
UH_STATUS_REQUEST_TIMEOUT = 408,
|
||||||
|
UH_STATUS_CONFLICT = 409,
|
||||||
|
UH_STATUS_GONE = 410,
|
||||||
|
UH_STATUS_LENGTH_REQUIRED = 411,
|
||||||
|
UH_STATUS_PRECONDITION_FAILED = 412,
|
||||||
|
UH_STATUS_PAYLOAD_TOO_LARGE = 413,
|
||||||
|
UH_STATUS_URI_TOO_LONG = 414,
|
||||||
|
UH_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
|
||||||
|
UH_STATUS_RANGE_NOT_SATISFIABLE = 416,
|
||||||
|
UH_STATUS_EXPECTATION_FAILED = 417,
|
||||||
|
UH_STATUS_MISDIRECTED_REQUEST = 421,
|
||||||
|
UH_STATUS_UNPROCESSABLE_ENTITY = 422,
|
||||||
|
UH_STATUS_LOCKED = 423,
|
||||||
|
UH_STATUS_FAILED_DEPENDENCY = 424,
|
||||||
|
UH_STATUS_UPGRADE_REQUIRED = 426,
|
||||||
|
UH_STATUS_PRECONDITION_REQUIRED = 428,
|
||||||
|
UH_STATUS_TOO_MANY_REQUESTS = 429,
|
||||||
|
UH_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
|
||||||
|
UH_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
|
||||||
|
UH_STATUS_INTERNAL_SERVER_ERROR = 500,
|
||||||
|
UH_STATUS_NOT_IMPLEMENTED = 501,
|
||||||
|
UH_STATUS_BAD_GATEWAY = 502,
|
||||||
|
UH_STATUS_SERVICE_UNAVAILABLE = 503,
|
||||||
|
UH_STATUS_GATEWAY_TIMEOUT = 504,
|
||||||
|
UH_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505,
|
||||||
|
UH_STATUS_VARIANT_ALSO_NEGOTIATES = 506,
|
||||||
|
UH_STATUS_INSUFFICIENT_STORAGE = 507,
|
||||||
|
UH_STATUS_LOOP_DETECTED = 508,
|
||||||
|
UH_STATUS_NOT_EXTENDED = 510,
|
||||||
|
UH_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511
|
||||||
|
};
|
||||||
|
|
||||||
struct uh_server;
|
struct uh_server;
|
||||||
struct uh_connection;
|
struct uh_connection;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#define UH_BUFFER_SIZE 2048
|
#define UH_BUFFER_SIZE 2048
|
||||||
#define UH_CONNECTION_TIMEOUT 30
|
#define UH_CONNECTION_TIMEOUT 30
|
||||||
|
#define UH_MAX_HTTP_HEAD_SIZE 1024
|
||||||
|
#define UH_MAX_HTTP_BODY_SIZE (2 * 1024 * 1024)
|
||||||
#define UH_MAX_HTTP_HEADERS 20
|
#define UH_MAX_HTTP_HEADERS 20
|
||||||
|
|
||||||
#define UH_CON_CLOSE (1 << 0)
|
#define UH_CON_CLOSE (1 << 0)
|
||||||
|
|
Loading…
Reference in New Issue