feat: split route into route & query
							parent
							
								
									7ece0eb4e5
								
							
						
					
					
						commit
						4d436aa8aa
					
				| 
						 | 
					@ -34,6 +34,8 @@ typedef struct http_request {
 | 
				
			||||||
  size_t method_len;
 | 
					  size_t method_len;
 | 
				
			||||||
  const char *path;
 | 
					  const char *path;
 | 
				
			||||||
  size_t path_len;
 | 
					  size_t path_len;
 | 
				
			||||||
 | 
					  const char *query;
 | 
				
			||||||
 | 
					  size_t query_len;
 | 
				
			||||||
  struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS];
 | 
					  struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS];
 | 
				
			||||||
} http_request;
 | 
					} http_request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +45,6 @@ typedef enum http_parse_error {
 | 
				
			||||||
  http_parse_error_invalid = 2,
 | 
					  http_parse_error_invalid = 2,
 | 
				
			||||||
} http_parse_error;
 | 
					} http_parse_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
http_parse_error http_parse_request(http_request *req, const char *path,
 | 
					 | 
				
			||||||
                                    size_t path_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* void http_route(event_loop_conn *conn); */
 | 
					/* void http_route(event_loop_conn *conn); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum http_response_type {
 | 
					typedef enum http_response_type {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,8 @@ void http_loop_ctx_free(http_loop_ctx *ctx);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool http_loop_handle_request(event_loop_conn *conn);
 | 
					bool http_loop_handle_request(event_loop_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					http_parse_error http_loop_parse_request(event_loop_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool http_loop_route_request(event_loop_conn *conn);
 | 
					bool http_loop_route_request(event_loop_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void http_loop_process_request(event_loop_conn *conn);
 | 
					void http_loop_process_request(event_loop_conn *conn);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,9 +27,7 @@ bool http_loop_handle_request(event_loop_conn *conn) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If route is defined, we're currently processing a request
 | 
					  // If route is defined, we're currently processing a request
 | 
				
			||||||
  if (ctx->route == NULL) {
 | 
					  if (ctx->route == NULL) {
 | 
				
			||||||
    http_parse_error res = http_parse_request(
 | 
					    http_parse_error res = http_loop_parse_request(conn);
 | 
				
			||||||
        &ctx->req, (const char *)&conn->rbuf[conn->rbuf_read],
 | 
					 | 
				
			||||||
        conn->rbuf_size - conn->rbuf_read);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (res == http_parse_error_invalid ||
 | 
					    if (res == http_parse_error_invalid ||
 | 
				
			||||||
        (res == http_parse_error_incomplete &&
 | 
					        (res == http_parse_error_incomplete &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
#include "http.h"
 | 
					 | 
				
			||||||
#include "picohttpparser.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * given the HTTP path, parse the request
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
http_parse_error http_parse_request(http_request *req, const char *buf,
 | 
					 | 
				
			||||||
                                    size_t buf_size) {
 | 
					 | 
				
			||||||
  // First we try to parse the incoming HTTP request
 | 
					 | 
				
			||||||
  size_t num_headers = HTTP_MAX_ALLOWED_HEADERS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int res = phr_parse_request(buf, buf_size, &req->method, &req->method_len,
 | 
					 | 
				
			||||||
                              &req->path, &req->path_len, &req->minor_version,
 | 
					 | 
				
			||||||
                              req->headers, &num_headers, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (res == -1) {
 | 
					 | 
				
			||||||
    return http_parse_error_invalid;
 | 
					 | 
				
			||||||
  } else if (res == -2) {
 | 
					 | 
				
			||||||
    return http_parse_error_incomplete;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  req->len = res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return http_parse_error_ok;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,58 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "http_loop.h"
 | 
					#include "http_loop.h"
 | 
				
			||||||
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					http_parse_error http_loop_parse_request(event_loop_conn *conn) {
 | 
				
			||||||
 | 
					  http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // First we try to parse the incoming HTTP request
 | 
				
			||||||
 | 
					  size_t num_headers = HTTP_MAX_ALLOWED_HEADERS;
 | 
				
			||||||
 | 
					  http_request *req = &ctx->req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int res =
 | 
				
			||||||
 | 
					      phr_parse_request((const char *)&conn->rbuf[conn->rbuf_read],
 | 
				
			||||||
 | 
					                        conn->rbuf_size - conn->rbuf_read, &req->method,
 | 
				
			||||||
 | 
					                        &req->method_len, &req->path, &req->path_len,
 | 
				
			||||||
 | 
					                        &req->minor_version, req->headers, &num_headers, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (res == -1) {
 | 
				
			||||||
 | 
					    return http_parse_error_invalid;
 | 
				
			||||||
 | 
					  } else if (res == -2) {
 | 
				
			||||||
 | 
					    return http_parse_error_incomplete;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  req->len = res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Split path into path & query
 | 
				
			||||||
 | 
					  size_t i = 0;
 | 
				
			||||||
 | 
					  bool no_query = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (no_query && i < req->path_len) {
 | 
				
			||||||
 | 
					    if (req->path[i] == '?') {
 | 
				
			||||||
 | 
					      // Ensure we don't store an invalid pointer if the request simply ends
 | 
				
			||||||
 | 
					      // with '?'
 | 
				
			||||||
 | 
					      if (i + 1 < req->path_len) {
 | 
				
			||||||
 | 
					        req->query = &req->path[i + 1];
 | 
				
			||||||
 | 
					        req->query_len = req->path_len - (i + 1);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      req->path_len = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      no_query = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    i++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Ensure we clear the old request's query
 | 
				
			||||||
 | 
					  if (no_query) {
 | 
				
			||||||
 | 
					    req->query = NULL;
 | 
				
			||||||
 | 
					    req->query_len = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return http_parse_error_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void http_loop_process_request(event_loop_conn *conn) {
 | 
					void http_loop_process_request(event_loop_conn *conn) {
 | 
				
			||||||
  http_loop_ctx *ctx = conn->ctx;
 | 
					  http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
| 
						 | 
					@ -25,6 +77,9 @@ bool http_loop_route_request(event_loop_conn *conn) {
 | 
				
			||||||
  http_loop_ctx *ctx = conn->ctx;
 | 
					  http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
  http_loop_gctx *gctx = ctx->g;
 | 
					  http_loop_gctx *gctx = ctx->g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  info("%.*s %.*s", ctx->req.method_len, ctx->req.method, ctx->req.path_len,
 | 
				
			||||||
 | 
					       ctx->req.path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  http_route *route;
 | 
					  http_route *route;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (size_t i = 0; i < gctx->route_count; i++) {
 | 
					  for (size_t i = 0; i < gctx->route_count; i++) {
 | 
				
			||||||
| 
						 | 
					@ -32,7 +87,7 @@ bool http_loop_route_request(event_loop_conn *conn) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (route->type) {
 | 
					    switch (route->type) {
 | 
				
			||||||
    case http_route_literal:
 | 
					    case http_route_literal:
 | 
				
			||||||
      if (strncmp(route->path, ctx->req.method, ctx->req.method_len)) {
 | 
					      if (strncmp(route->path, ctx->req.path, ctx->req.path_len) == 0) {
 | 
				
			||||||
        ctx->route = route;
 | 
					        ctx->route = route;
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue