http: Add a more expressive but still nowhere near regex URL pattern matcher.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 14m57s
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 14m57s
This commit is contained in:
37
src/http.c
37
src/http.c
@ -67,7 +67,6 @@ typedef struct _tf_http_connection_t
|
||||
typedef struct _tf_http_handler_t
|
||||
{
|
||||
const char* pattern;
|
||||
bool is_wildcard;
|
||||
tf_http_callback_t* callback;
|
||||
tf_http_cleanup_t* cleanup;
|
||||
void* user_data;
|
||||
@ -129,9 +128,15 @@ static void _http_allocate_buffer(uv_handle_t* handle, size_t suggested_size, uv
|
||||
*buf = uv_buf_init(connection->incoming, sizeof(connection->incoming));
|
||||
}
|
||||
|
||||
static bool _http_pattern_matches(const char* pattern, const char* path, bool is_wildcard)
|
||||
bool tf_http_pattern_matches(const char* pattern, const char* path)
|
||||
{
|
||||
if (!pattern || !*pattern || (!is_wildcard && strcmp(path, pattern) == 0))
|
||||
if (!pattern || !*pattern)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const char* k_word = "{word}";
|
||||
bool is_wildcard = strchr(pattern, '*') || strstr(pattern, k_word);
|
||||
if (!is_wildcard && strcmp(path, pattern) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -140,17 +145,34 @@ static bool _http_pattern_matches(const char* pattern, const char* path, bool is
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (pattern[i] && path[j] && pattern[i] != '*' && pattern[i] == path[j])
|
||||
while (pattern[i] && path[j] && pattern[i] == path[j])
|
||||
{
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (pattern[i] == '*')
|
||||
size_t k_word_len = strlen(k_word);
|
||||
if (strncmp(pattern + i, k_word, k_word_len) == 0 && ((path[j] >= 'a' && path[j] <= 'z') || (path[j] >= 'A' && path[j] <= 'Z')))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_http_pattern_matches(pattern + i + 1, path + j, strchr(pattern + i + 1, '*') != NULL))
|
||||
if (((path[j] >= 'a' && path[j] <= 'z') || (path[j] >= 'A' && path[j] <= 'Z') || (path[j] >= '0' && path[j] <= '9')) &&
|
||||
tf_http_pattern_matches(pattern + i + k_word_len, path + j + 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!path[j])
|
||||
{
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
else if (pattern[i] == '*')
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (tf_http_pattern_matches(pattern + i + 1, path + j))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -170,7 +192,7 @@ static bool _http_find_handler(tf_http_t* http, const char* path, tf_http_callba
|
||||
{
|
||||
for (int i = 0; i < http->handlers_count; i++)
|
||||
{
|
||||
if (_http_pattern_matches(http->handlers[i].pattern, path, http->handlers[i].is_wildcard))
|
||||
if (tf_http_pattern_matches(http->handlers[i].pattern, path))
|
||||
{
|
||||
*out_callback = http->handlers[i].callback;
|
||||
*out_trace_name = http->handlers[i].pattern;
|
||||
@ -741,7 +763,6 @@ void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_
|
||||
http->handlers = tf_resize_vec(http->handlers, sizeof(tf_http_handler_t) * (http->handlers_count + 1));
|
||||
http->handlers[http->handlers_count++] = (tf_http_handler_t) {
|
||||
.pattern = tf_strdup(pattern),
|
||||
.is_wildcard = pattern && strchr(pattern, '*') != NULL,
|
||||
.callback = callback,
|
||||
.cleanup = cleanup,
|
||||
.user_data = user_data,
|
||||
|
Reference in New Issue
Block a user