Host *Host_create(bstring name, bstring matching) { if(!MAX_URL_PATH || !MAX_HOST_NAME) { MAX_URL_PATH = Setting_get_int("limits.url_path", 256); MAX_HOST_NAME = Setting_get_int("limits.host_name", 256); log_info("MAX limits.url_path=%d, limits.host_name=%d", MAX_URL_PATH, MAX_HOST_NAME); } Host *host = h_calloc(sizeof(Host), 1); check_mem(host); host->name = bstrcpy(name); check(blength(host->name) < MAX_HOST_NAME, "Host name too long (max %d): '%s'\n", MAX_HOST_NAME, bdata(name)); host->matching = bstrcpy(matching); check(blength(host->matching) < MAX_HOST_NAME, "Host matching pattern too long (max %d): '%s'\n", MAX_HOST_NAME, bdata(name)); host->routes = RouteMap_create(backend_destroy_cb); check(host->routes, "Failed to create host route map for %s.", bdata(name)); return host; error: return NULL; }
Server *Server_create(bstring uuid, bstring default_host, bstring bind_addr, int port, bstring chroot, bstring access_log, bstring error_log, bstring pid_file, bstring control_port, int use_ssl) { Server *srv = NULL; int rc = 0; srv = h_calloc(sizeof(Server), 1); check_mem(srv); srv->hosts = RouteMap_create(host_destroy_cb); check(srv->hosts != NULL, "Failed to create host RouteMap."); srv->handlers = darray_create(sizeof(Handler), 20); check_mem(srv->handlers); check(port > 0, "Invalid port given, must be > 0: %d", port); srv->port = port; srv->listen_fd = 0; srv->bind_addr = bstrcpy(bind_addr); check_mem(srv->bind_addr); srv->uuid = bstrcpy(uuid); check_mem(srv->uuid); // TODO: once mbedtls supports opening urandom early and keeping it open, // put the rng initialization back here (before chroot) //if(use_ssl) { // rc = Server_init_rng(srv); // check(rc == 0, "Failed to initialize rng for server %s", bdata(uuid)); //} if(blength(chroot) > 0) { srv->chroot = bstrcpy(chroot); check_mem(srv->chroot); } else { srv->chroot = NULL; } srv->access_log = bstrcpy(access_log); check_mem(srv->access_log); srv->error_log = bstrcpy(error_log); check_mem(srv->error_log); srv->pid_file = bstrcpy(pid_file); check_mem(srv->pid_file); if(blength(control_port) > 0) { srv->control_port = bstrcpy(control_port); check_mem(srv->control_port); } else { srv->control_port = NULL; } srv->default_hostname = bstrcpy(default_host); srv->use_ssl = use_ssl; srv->created_on = time(NULL); if(srv->use_ssl) { rc = Server_init_ssl(srv); check(rc == 0, "Failed to initialize ssl for server %s", bdata(uuid)); } return srv; error: Server_destroy(srv); return NULL; }
int Command_route(Command *cmd) { int rc = 0; RouteMap *map = RouteMap_create(null_destroy); check(map != NULL, "Error, can't create the RouteMap."); bstring match = option(cmd, "match", NULL); bstring pattern = option(cmd, "pattern", NULL); bstring reversed = option(cmd, "reversed", NULL); bstring sfxmatch = option(cmd, "suffix", NULL); check(match != NULL, "You have to give something to match against with --match."); check(pattern != NULL, "You have to give a pattern to use with --pattern."); if(reversed == NULL) { rc = RouteMap_insert(map, bstrcpy(pattern), NULL); check(rc == 0, "Failed to insert pattern into routing table."); } else { rc = RouteMap_insert_reversed(map, bstrcpy(pattern), NULL); check(rc == 0, "Failed to insert REVERSED pattern into routing table."); } Route *route = NULL; if(sfxmatch != NULL) { route = RouteMap_match_suffix(map, match); } else { route = RouteMap_simple_prefix_match(map, match); } if(route != NULL) { printf("Match passed on '%s' against '%s'.\n", bdata(match), bdata(pattern)); printf("ROUTE: pattern='%s', prefix='%s'\n", bdata(route->pattern), bdata(route->prefix)); } else { printf("Match FAILED on '%s' against '%s'.\n", bdata(match), bdata(pattern)); } RouteMap_destroy(map); return 0; error: RouteMap_destroy(map); return -1; }
char *test_routing_match_reversed() { RouteMap *routes = RouteMap_create(NULL); mu_assert(routes != NULL, "Failed to make the route map."); char *route_data1 = "route1"; char *route_data2 = "route2"; char *route_data3 = "route3"; bstring route1 = bfromcstr("foo"); bstring route2 = bfromcstr("moo"); bstring route3 = bfromcstr("fio"); Route *route = NULL; RouteMap_insert_reversed(routes, route1, route_data1); RouteMap_insert_reversed(routes, route2, route_data2); RouteMap_insert_reversed(routes, route3, route_data3); bstring path1 = bfromcstr("foo"); bstring path2 = bfromcstr("moo"); bstring path3 = bfromcstr("fio"); route = RouteMap_match_suffix(routes, path1); mu_assert(route != NULL, "Pattern match failed."); mu_assert(route->data == route_data1, "Pattern matched wrong route."); route = RouteMap_match_suffix(routes, path2); mu_assert(route != NULL, "Pattern match failed."); mu_assert(route->data == route_data2, "Pattern matched wrong route."); route = RouteMap_match_suffix(routes, path3); mu_assert(route != NULL, "Pattern match failed."); mu_assert(route->data == route_data3, "Pattern matched wrong route."); bdestroy(path1); bdestroy(path2); bdestroy(path3); RouteMap_destroy(routes); return NULL; }
char *test_simple_prefix_matching() { RouteMap *routes = RouteMap_create(NULL); mu_assert(routes != NULL, "Failed to make the route map."); char *route_data0 = "route0"; char *route_data1 = "route1"; char *route_data2 = "route2"; char *route_data3 = "route3"; char *route_data4 = "route4"; bstring route0 = bfromcstr("/"); bstring route1 = bfromcstr("/users/([0-9]+)"); bstring route2 = bfromcstr("/users"); bstring route3 = bfromcstr("/users/people/([0-9]+)$"); bstring route4 = bfromcstr("/cars-fast/([a-z]-)$"); RouteMap_insert(routes, route0, route_data0); RouteMap_insert(routes, route1, route_data1); RouteMap_insert(routes, route2, route_data2); RouteMap_insert(routes, route3, route_data3); RouteMap_insert(routes, route4, route_data4); mu_assert(check_simple_prefix(routes, "/users/1234/testing", route_data1), "Failed."); mu_assert(check_simple_prefix(routes, "/users", route_data2), "Failed."); mu_assert(check_simple_prefix(routes, "/users/people/1234", route_data3), "Failed."); mu_assert(check_simple_prefix(routes, "/cars-fast/cadillac", route_data4), "Failed."); mu_assert(check_simple_prefix(routes, "/users/1234", route_data1), "Failed."); mu_assert(check_simple_prefix(routes, "/", route_data0), "Failed."); // this is expected, because /users isn't explicitly patterned to be exact, it // only prefix matches. mu_assert(check_simple_prefix(routes, "/usersBLAAHAHAH", route_data2), "Failed."); mu_assert(check_simple_prefix(routes, "/us", route_data2), "Failed."); RouteMap_destroy(routes); return NULL; }
char *test_routing_match() { RouteMap *routes = RouteMap_create(NULL); mu_assert(routes != NULL, "Failed to make the route map."); char *route_data0 = "route0"; char *route_data1 = "route1"; char *route_data2 = "route2"; char *route_data3 = "route3"; char *route_data4 = "route4"; bstring route0 = bfromcstr("/"); bstring route1 = bfromcstr("/users/([0-9]+)"); bstring route2 = bfromcstr("/users"); bstring route3 = bfromcstr("/users/people/([0-9]+)$"); bstring route4 = bfromcstr("/cars-fast/([a-z]-)$"); Route *route = NULL; RouteMap_insert(routes, route0, route_data0); RouteMap_insert(routes, route1, route_data1); RouteMap_insert(routes, route2, route_data2); RouteMap_insert(routes, route3, route_data3); RouteMap_insert(routes, route4, route_data4); bstring path1 = bfromcstr("/users/1234/testing"); bstring path2 = bfromcstr("/users"); bstring path3 = bfromcstr("/users/people/1234"); bstring path4 = bfromcstr("/cars-fast/cadillac"); bstring path5 = bfromcstr("/users/1234"); bstring path6 = bfromcstr("/"); bstring path7 = bfromcstr("/users/people/1234/notgonnawork"); list_t *found = RouteMap_match(routes, path5); mu_assert(check_routing(found, route, 1, route_data1), "Pattern match route wrong."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path1); mu_assert(check_routing(found, route, 1, route_data1), "Past end route wrong."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path2); mu_assert(check_routing(found, route, 1, route_data2), "No pattern route wrong."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path3); mu_assert(check_routing(found, route, 1, route_data3), "Wrong $ terminated route."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path4); mu_assert(check_routing(found, route, 1, route_data4), "Wrong longer route match."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path5); mu_assert(check_routing(found, route, 1, route_data1), "Wrong route for /users/1234"); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path6); mu_assert(check_routing(found, route, 2, route_data0), "Should get root / route."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path7); mu_assert(check_routing(found, route, 0, NULL), "Should not match past end"); list_destroy_nodes(found); list_destroy(found); bdestroy(path1); bdestroy(path2); bdestroy(path3); bdestroy(path4); bdestroy(path5); RouteMap_destroy(routes); return NULL; }
char *test_routing_match() { RouteMap *routes = RouteMap_create(NULL); mu_assert(routes != NULL, "Failed to make the route map."); char *route_data1 = "route1"; char *route_data2 = "route2"; char *route_data3 = "route3"; char *route_data4 = "route4"; bstring route1 = bfromcstr("/users/([0-9]+)"); bstring route2 = bfromcstr("/users"); bstring route3 = bfromcstr("/users/people/([0-9]+))$"); bstring route4 = bfromcstr("/cars/([a-z]-)$"); Route *route = NULL; RouteMap_insert(routes, route1, route_data1); RouteMap_insert(routes, route2, route_data2); RouteMap_insert(routes, route3, route_data4); RouteMap_insert(routes, route4, route_data3); bstring path1 = bfromcstr("/users/1234/testing"); bstring path2 = bfromcstr("/users"); bstring path3 = bfromcstr("/cars/cadillac"); bstring path4 = bfromcstr("/users/people/1234"); bstring path5 = bfromcstr("/users/1234"); list_t *found = RouteMap_match(routes, path5); mu_assert(check_routing(found, route, 1, route_data1), "Pattern match route wrong."); list_destroy_nodes(found); list_destroy(found); // must make sure that match is partial unless $ explicitly found = RouteMap_match(routes, path1); mu_assert(check_routing(found, route, 1, route_data1), "Past end route wrong."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path2); mu_assert(check_routing(found, route, 1, route_data2), "No pattern route wrong."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path3); mu_assert(check_routing(found, route, 1, route_data3), "Wrong $ terminated route."); list_destroy_nodes(found); list_destroy(found); found = RouteMap_match(routes, path4); mu_assert(check_routing(found, route, 1, route_data4), "Wrong longer route match."); list_destroy_nodes(found); list_destroy(found); bdestroy(path1); bdestroy(path2); bdestroy(path3); bdestroy(path4); bdestroy(path5); RouteMap_destroy(routes); return NULL; }