refactor(routing): moved some stuff, added some comments
							parent
							
								
									cf4451740f
								
							
						
					
					
						commit
						115baecde8
					
				|  | @ -89,4 +89,12 @@ uint64_t lnm_atoi(const char *s, size_t len); | |||
|  */ | ||||
| uint64_t lnm_digits(uint64_t num); | ||||
| 
 | ||||
| /**
 | ||||
|  * Check whether the given nul-terminated string solely consists of ASCII | ||||
|  * characters. | ||||
|  * | ||||
|  * @param s nul-terminated string to check | ||||
|  */ | ||||
| bool lnm_is_ascii(const char *s); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -45,6 +45,10 @@ lnm_err lnm_http_router_init(lnm_http_router **out); | |||
| 
 | ||||
| void lnm_http_router_free(lnm_http_router *router); | ||||
| 
 | ||||
| /**
 | ||||
|  * Insert a new path & method in the given router, returning a handle to the | ||||
|  * newly created route struct. | ||||
|  */ | ||||
| lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router, | ||||
|                             lnm_http_method method, const char *path); | ||||
| 
 | ||||
|  | @ -67,14 +71,26 @@ lnm_err lnm_http_router_merge(lnm_http_router *r1, lnm_http_router *r2); | |||
| lnm_err lnm_http_router_nest(lnm_http_router *parent, lnm_http_router *child, | ||||
|                              const char *prefix); | ||||
| 
 | ||||
| /**
 | ||||
|  * Route the given path & method. | ||||
|  */ | ||||
| lnm_http_route_err lnm_http_router_route(lnm_http_route_match *out, | ||||
|                                          const lnm_http_router *router, | ||||
|                                          lnm_http_method method, | ||||
|                                          const char *path); | ||||
| 
 | ||||
| /**
 | ||||
|  * Retrieve a path segment using its name. | ||||
|  * | ||||
|  * @return NULL if not found, otherwise pointer to the match segment struct | ||||
|  * representing the key | ||||
|  */ | ||||
| const lnm_http_route_match_segment * | ||||
| lnm_http_route_match_get(lnm_http_route_match *match, const char *key); | ||||
| 
 | ||||
| /**
 | ||||
|  * Append the given step function to the route's step list. | ||||
|  */ | ||||
| lnm_err lnm_http_route_step_append(lnm_http_route *route, lnm_http_step_fn fn, | ||||
|                                    bool blocking); | ||||
| 
 | ||||
|  |  | |||
|  | @ -75,6 +75,31 @@ lnm_err lnm_http_route_key_segment_insert(lnm_http_route *route, | |||
|   return lnm_err_ok; | ||||
| } | ||||
| 
 | ||||
| const lnm_http_route_match_segment * | ||||
| lnm_http_route_match_get(lnm_http_route_match *match, const char *key) { | ||||
|   if (match->route->key_segments == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   lnm_http_route_segment_trie *trie = match->route->key_segments; | ||||
| 
 | ||||
|   while (*key != '\0') { | ||||
|     trie = trie->children[(unsigned char)*key]; | ||||
| 
 | ||||
|     if (trie == NULL) { | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     key++; | ||||
|   } | ||||
| 
 | ||||
|   if (!trie->represents_segment) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   return &match->key_segments[trie->index]; | ||||
| } | ||||
| 
 | ||||
| lnm_err lnm_http_step_init(lnm_http_step **out) { | ||||
|   lnm_http_step *step = calloc(1, sizeof(lnm_http_step)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,21 +34,9 @@ void lnm_http_router_free(lnm_http_router *router) { | |||
|   free(router); | ||||
| } | ||||
| 
 | ||||
| static bool is_ascii(const char *s) { | ||||
|   while (*s != '\0') { | ||||
|     if (*s < 0) { | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     s++; | ||||
|   } | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router, | ||||
|                             lnm_http_method method, const char *path) { | ||||
|   if (path[0] != '/' || !is_ascii(path)) { | ||||
|   if (path[0] != '/' || !lnm_is_ascii(path)) { | ||||
|     return lnm_err_invalid_route; | ||||
|   } | ||||
| 
 | ||||
|  | @ -63,7 +51,10 @@ lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router, | |||
| 
 | ||||
|     switch (c) { | ||||
|     case ':': { | ||||
|       // Match the segment content as the variable name
 | ||||
|       const char *next_slash_ptr = strchr(path + 1, '/'); | ||||
| 
 | ||||
|       // Account for segment being the final part of the route
 | ||||
|       const char *new_path = | ||||
|           next_slash_ptr == NULL ? strchr(path + 1, '\0') : next_slash_ptr; | ||||
|       size_t key_len = new_path - (path + 1); | ||||
|  | @ -128,7 +119,6 @@ lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router, | |||
| 
 | ||||
|       http_router->multi_segment_routes[method] = route; | ||||
|       goto end; | ||||
| 
 | ||||
|     } break; | ||||
|     default: | ||||
|       if (http_router->exact_children[c] == NULL) { | ||||
|  | @ -218,6 +208,8 @@ static lnm_http_route_err __lnm_http_router_route(lnm_http_route_match *out, | |||
|           matched_key_segments + 1); | ||||
| 
 | ||||
|       if (sub_res == lnm_http_route_err_match) { | ||||
|         // If match succeeds down the recursion, we can correctly set the
 | ||||
|         // matched segments when going back up the stack
 | ||||
|         if (out != NULL) { | ||||
|           out->key_segments[matched_key_segments].start = path_index; | ||||
|           out->key_segments[matched_key_segments].len = segment_len; | ||||
|  | @ -257,38 +249,13 @@ lnm_http_route_err lnm_http_router_route(lnm_http_route_match *out, | |||
|                                          const lnm_http_router *router, | ||||
|                                          lnm_http_method method, | ||||
|                                          const char *path) { | ||||
|   if (!is_ascii(path)) { | ||||
|   if (!lnm_is_ascii(path)) { | ||||
|     return lnm_http_route_err_unknown_route; | ||||
|   } | ||||
| 
 | ||||
|   return __lnm_http_router_route(out, router, method, path, 0, 0); | ||||
| } | ||||
| 
 | ||||
| const lnm_http_route_match_segment * | ||||
| lnm_http_route_match_get(lnm_http_route_match *match, const char *key) { | ||||
|   if (match->route->key_segments == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   lnm_http_route_segment_trie *trie = match->route->key_segments; | ||||
| 
 | ||||
|   while (*key != '\0') { | ||||
|     trie = trie->children[(unsigned char)*key]; | ||||
| 
 | ||||
|     if (trie == NULL) { | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     key++; | ||||
|   } | ||||
| 
 | ||||
|   if (!trie->represents_segment) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   return &match->key_segments[trie->index]; | ||||
| } | ||||
| 
 | ||||
| bool lnm_http_router_conflicts(const lnm_http_router *r1, | ||||
|                                const lnm_http_router *r2) { | ||||
|   // First check the literal routes for the routers
 | ||||
|  | @ -359,14 +326,12 @@ lnm_err lnm_http_router_merge(lnm_http_router *r1, lnm_http_router *r2) { | |||
| 
 | ||||
| lnm_err lnm_http_router_nest(lnm_http_router *parent, lnm_http_router *child, | ||||
|                              const char *prefix) { | ||||
|   if (!is_ascii(prefix) || prefix[0] != '/') { | ||||
|   if (!lnm_is_ascii(prefix) || prefix[0] != '/') { | ||||
|     return lnm_err_invalid_route; | ||||
|   } | ||||
| 
 | ||||
|   lnm_http_router *router = parent; | ||||
| 
 | ||||
|   // The child router's routes are also mounted on '/', so we stop one earlier
 | ||||
|   // as we need to merge it with the router representing the '/'
 | ||||
|   while (*prefix != '\0') { | ||||
|     unsigned char c = *prefix; | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,3 +55,15 @@ uint64_t lnm_digits(uint64_t num) { | |||
| 
 | ||||
|   return digits; | ||||
| } | ||||
| 
 | ||||
| bool lnm_is_ascii(const char *s) { | ||||
|   bool valid = true; | ||||
| 
 | ||||
|   while (valid && *s != '\0') { | ||||
|     valid = *s < 0; | ||||
| 
 | ||||
|     s++; | ||||
|   } | ||||
| 
 | ||||
|   return valid; | ||||
| } | ||||
|  |  | |||
|  | @ -77,6 +77,8 @@ void test_routing_merge() { | |||
| 
 | ||||
|   TEST_CHECK(lnm_http_router_route(&match, rtr1, lnm_http_method_get, "/test2") == lnm_http_route_err_match); | ||||
|   TEST_CHECK(match.route == rt2); | ||||
| 
 | ||||
|   lnm_http_router_free(rtr1); | ||||
| } | ||||
| 
 | ||||
| void test_routing_nest() { | ||||
|  | @ -97,6 +99,7 @@ void test_routing_nest() { | |||
| 
 | ||||
|   TEST_CHECK(lnm_http_router_route(&match, r2, lnm_http_method_get, "/test/test2") == lnm_http_route_err_match); | ||||
| 
 | ||||
|   lnm_http_router_free(r2); | ||||
| } | ||||
| 
 | ||||
| TEST_LIST = { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue