Compare commits
No commits in common. "4a0df8db6bb78e6eb4885524c352184cc4ddf8c6" and "854e8c3809bf97a3c395525d15b8a3fe00e89005" have entirely different histories.
4a0df8db6b
...
854e8c3809
|
@ -86,17 +86,4 @@ uint64_t lnm_atoi(const char *s, size_t len);
|
|||
*/
|
||||
uint64_t lnm_digits(uint64_t num);
|
||||
|
||||
/**
|
||||
* Find the first case-insensitive occurence of s2 in s1.
|
||||
*
|
||||
* @param out pointer to store start of match in
|
||||
* @param s1 pointer to string to look in
|
||||
* @param s1_len length of s1
|
||||
* @param s2 string to search for in s1
|
||||
* @param s2_len length of s2
|
||||
* @return true if found, false otherwise
|
||||
*/
|
||||
bool lnm_stristr(const char **out, const char *s1, size_t s1_len,
|
||||
const char *s2, size_t s2_len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,11 +13,7 @@
|
|||
#define LNM_HTTP_MAX_REQ_HEADERS 32
|
||||
#define LNM_HTTP_MAX_REGEX_GROUPS 4
|
||||
|
||||
/**
|
||||
* Internal representation of a header in a request, defined using offsets
|
||||
* relative to the full buffer.
|
||||
*/
|
||||
typedef struct lnm_http_req_ihdr {
|
||||
typedef struct lnm_http_req_header {
|
||||
struct {
|
||||
size_t o;
|
||||
size_t len;
|
||||
|
@ -26,7 +22,7 @@ typedef struct lnm_http_req_ihdr {
|
|||
size_t o;
|
||||
size_t len;
|
||||
} value;
|
||||
} lnm_http_req_ihhr;
|
||||
} lnm_http_req_header;
|
||||
|
||||
/**
|
||||
* Represents the parsed HTTP request
|
||||
|
@ -49,7 +45,7 @@ typedef struct lnm_http_req {
|
|||
size_t len;
|
||||
} query;
|
||||
struct {
|
||||
lnm_http_req_ihhr arr[LNM_HTTP_MAX_REQ_HEADERS];
|
||||
lnm_http_req_header arr[LNM_HTTP_MAX_REQ_HEADERS];
|
||||
size_t len;
|
||||
} headers;
|
||||
struct {
|
||||
|
@ -85,71 +81,31 @@ lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf, size_t len);
|
|||
void lnm_http_req_reset(lnm_http_req *req);
|
||||
|
||||
/**
|
||||
* Represents an actual header value, with offsets already resolved.
|
||||
*/
|
||||
typedef struct lnm_http_req_hdr {
|
||||
struct {
|
||||
const char *s;
|
||||
size_t len;
|
||||
} name;
|
||||
struct {
|
||||
const char *s;
|
||||
size_t len;
|
||||
} value;
|
||||
} lnm_http_req_hdr;
|
||||
|
||||
/**
|
||||
* Retrieve a known type header from the request.
|
||||
* Retrieve a specific header from the request.
|
||||
*
|
||||
* Pointers retrieved from this function should never be used between step
|
||||
* functions; simply request the header again if you need to.
|
||||
*
|
||||
* @param out where to store pointer to struct representing header
|
||||
* @param out where to write pointer to header value
|
||||
* @param out_len where to store length of out value
|
||||
* @param req request to look for header in
|
||||
* @param type type of header to look for
|
||||
*/
|
||||
lnm_err lnm_http_req_header_get(lnm_http_req_hdr *out, lnm_http_req *req,
|
||||
lnm_http_header type);
|
||||
lnm_err lnm_http_req_header_get(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, lnm_http_header type);
|
||||
|
||||
/**
|
||||
* Retrieve a header from the request using a case-insensitive name.
|
||||
* Retrieve a specific header from the request by specifying its name.
|
||||
*
|
||||
* Pointers retrieved from this function should never be used between step
|
||||
* functions; simply request the header again if you need to.
|
||||
*
|
||||
* @param out where to store pointer to struct representing header
|
||||
* @param out where to write pointer to header value
|
||||
* @param out_len where to store length of out value
|
||||
* @param req request to look for header in
|
||||
* @param name name of the header; matches case-insensitive
|
||||
*/
|
||||
lnm_err lnm_http_req_header_get_s(lnm_http_req_hdr *out, lnm_http_req *req,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Represents a parameter in an HTTP header.
|
||||
*/
|
||||
typedef struct lnm_http_req_hdr_param {
|
||||
struct {
|
||||
const char *s;
|
||||
size_t len;
|
||||
} key;
|
||||
struct {
|
||||
const char *s;
|
||||
size_t len;
|
||||
} value;
|
||||
} lnm_http_req_hdr_param;
|
||||
|
||||
/**
|
||||
* Retrieve a specific key-value parameter from a header.
|
||||
*
|
||||
* Pointers retrieved from this function should never be used between step
|
||||
* functions; simply request the header again if you need to.
|
||||
*
|
||||
* @param out output struct
|
||||
* @param header header to look in
|
||||
* @param key name of the parameter to return from the header
|
||||
*/
|
||||
lnm_err lnm_http_req_header_param(lnm_http_req_hdr_param *param,
|
||||
const lnm_http_req_hdr *header,
|
||||
const char *key);
|
||||
lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, const char *name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -113,10 +113,11 @@ void lnm_http_loop_process_parse_headers(lnm_http_conn *conn) {
|
|||
lnm_http_loop_ctx *ctx = conn->ctx;
|
||||
lnm_http_req *req = &ctx->req;
|
||||
|
||||
lnm_http_req_hdr header;
|
||||
if (lnm_http_req_header_get(&header, req, lnm_http_header_content_length) ==
|
||||
lnm_err_ok) {
|
||||
req->body.expected_len = lnm_atoi(header.value.s, header.value.len);
|
||||
const char *value;
|
||||
size_t value_len;
|
||||
if (lnm_http_req_header_get(&value, &value_len, req,
|
||||
lnm_http_header_content_length) == lnm_err_ok) {
|
||||
req->body.expected_len = lnm_atoi(value, value_len);
|
||||
}
|
||||
|
||||
ctx->state = lnm_http_loop_state_steps;
|
||||
|
|
|
@ -30,13 +30,13 @@ lnm_http_step_err lnm_http_loop_step_auth(lnm_http_conn *conn) {
|
|||
// If there's no API key, requests are always authorized
|
||||
bool authorized = ctx->g->api_key == NULL;
|
||||
|
||||
lnm_http_req_hdr header;
|
||||
const char *value;
|
||||
size_t value_len;
|
||||
|
||||
if (!authorized && lnm_http_req_header_get_s(&header, &ctx->req,
|
||||
if (!authorized && lnm_http_req_header_get_s(&value, &value_len, &ctx->req,
|
||||
"X-Api-Key") == lnm_err_ok) {
|
||||
authorized =
|
||||
(header.value.len == strlen(ctx->g->api_key)) &&
|
||||
(memcmp(header.value.s, ctx->g->api_key, header.value.len) == 0);
|
||||
authorized = (value_len == strlen(ctx->g->api_key)) &&
|
||||
(memcmp(value, ctx->g->api_key, value_len) == 0);
|
||||
}
|
||||
|
||||
ctx->res.status = authorized ? ctx->res.status : lnm_http_status_unauthorized;
|
||||
|
|
|
@ -88,24 +88,23 @@ void lnm_http_req_reset(lnm_http_req *req) {
|
|||
memset(req, 0, sizeof(lnm_http_req));
|
||||
}
|
||||
|
||||
lnm_err lnm_http_req_header_get(lnm_http_req_hdr *out, lnm_http_req *req,
|
||||
lnm_http_header type) {
|
||||
return lnm_http_req_header_get_s(out, req, lnm_http_header_names[type]);
|
||||
lnm_err lnm_http_req_header_get(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, lnm_http_header type) {
|
||||
return lnm_http_req_header_get_s(out, out_len, req,
|
||||
lnm_http_header_names[type]);
|
||||
}
|
||||
|
||||
lnm_err lnm_http_req_header_get_s(lnm_http_req_hdr *out, lnm_http_req *req,
|
||||
const char *name) {
|
||||
lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, const char *name) {
|
||||
size_t name_len = strlen(name);
|
||||
|
||||
for (size_t i = 0; i < req->headers.len; i++) {
|
||||
const lnm_http_req_ihhr *header = &req->headers.arr[i];
|
||||
const lnm_http_req_header *header = &req->headers.arr[i];
|
||||
|
||||
if (lnm_strnieq(req->buf.s + header->name.o, header->name.len, name,
|
||||
name_len)) {
|
||||
out->name.s = req->buf.s + header->name.o;
|
||||
out->name.len = header->name.len;
|
||||
out->value.s = req->buf.s + header->value.o;
|
||||
out->value.len = header->value.len;
|
||||
*out = req->buf.s + header->value.o;
|
||||
*out_len = header->value.len;
|
||||
|
||||
return lnm_err_ok;
|
||||
}
|
||||
|
@ -113,15 +112,3 @@ lnm_err lnm_http_req_header_get_s(lnm_http_req_hdr *out, lnm_http_req *req,
|
|||
|
||||
return lnm_err_not_found;
|
||||
}
|
||||
|
||||
lnm_err lnm_http_req_header_param(lnm_http_req_hdr_param *param,
|
||||
const lnm_http_req_hdr *header,
|
||||
const char *key) {
|
||||
size_t key_len = strlen(key);
|
||||
|
||||
const char *s;
|
||||
if (lnm_stristr(&s, header->name.s, header->name.len - 1, key, key_len) && (header->name.s[key_len] == '=')) {
|
||||
// Value runs till end of header or next semi-colon
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,19 +55,3 @@ uint64_t lnm_digits(uint64_t num) {
|
|||
|
||||
return digits;
|
||||
}
|
||||
|
||||
bool lnm_stristr(const char **out, const char *s1, size_t s1_len,
|
||||
const char *s2, size_t s2_len) {
|
||||
while (s1_len >= s2_len) {
|
||||
if (lnm_strnieq(s1, s1_len, s2, s2_len)) {
|
||||
*out = s1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
s1_len--;
|
||||
s1++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue