Пример #1
0
int
http_router_bind(struct http_router *router,
                 const char *path_string, enum http_method method,
                 http_route_cb cb, void *cb_arg) {
    struct http_route *route;
    struct http_path *path;

    path = http_path_parse(path_string);
    if (!path) {
        c_set_error("invalid path: %s", c_get_error());
        return -1;
    }

    route = http_route_new();

    route->path_string = c_strdup(path_string);
    route->path = path;
    route->method = method;

    route->cb = cb;
    route->cb_arg = cb_arg;

    c_ptr_vector_append(router->routes, route);

    http_router_sort_routes(router);

    return 0;
}
Пример #2
0
int
http_route_base_find_route(struct http_route_base *base,
                           enum http_method method, const char *path,
                           const struct http_route **proute,
                           enum http_route_match_result *p_match_result,
                           struct http_named_parameter **p_named_parameters,
                           size_t *p_nb_named_parameters) {
    struct http_route *route;
    struct http_named_parameter *named_parameters;
    size_t nb_named_parameters;
    enum http_route_match_result match_result;
    char **path_components;
    size_t nb_path_components, idx;

    if (!base->sorted)
        http_route_base_sort_routes(base);

    if (*path != '/') {
        *proute = NULL;
        *p_match_result = HTTP_ROUTE_MATCH_WRONG_PATH;
        return 0;
    }

    if (http_path_parse(path, &path_components, &nb_path_components) == -1)
        return -1;

    route = NULL;
    match_result = HTTP_ROUTE_MATCH_PATH_NOT_FOUND;

    for (size_t i = 0; i < base->nb_routes; i++) {
        enum http_route_match_result result;

        if (http_route_matches_request(base->routes[i], method,
                                       path_components, nb_path_components,
                                       &result)) {
            route = base->routes[i];
            match_result = HTTP_ROUTE_MATCH_OK;
            break;
        }

        if (result == HTTP_ROUTE_MATCH_METHOD_NOT_FOUND) {
            match_result = HTTP_ROUTE_MATCH_METHOD_NOT_FOUND;
        } else if (result == HTTP_ROUTE_MATCH_PATH_NOT_FOUND
                && match_result != HTTP_ROUTE_MATCH_METHOD_NOT_FOUND) {
            match_result = HTTP_ROUTE_MATCH_PATH_NOT_FOUND;
        }
    }

    if (!route) {
        *proute = NULL;
        *p_match_result = match_result;

        http_path_free(path_components, nb_path_components);
        return 0;
    }

    if (route->nb_components != nb_path_components) {
        /* We made a mistake somewhere, it should not happen */
        http_set_error("route/path size mismatch");
        return -1;
    }

    /* Copy named parameters */
    nb_named_parameters = 0;
    for (size_t i = 0; i < route->nb_components; i++) {
        if (route->components[i].type == HTTP_ROUTE_COMPONENT_NAMED)
            nb_named_parameters++;
    }

    if (p_named_parameters && nb_named_parameters > 0) {
        named_parameters = http_calloc(nb_named_parameters,
                                       sizeof(struct http_named_parameter));

        idx = 0;
        for (size_t i = 0; i < route->nb_components; i++) {
            struct http_route_component *component;

            component = route->components + i;

            if (component->type != HTTP_ROUTE_COMPONENT_NAMED)
                continue;

            named_parameters[idx].name = http_strdup(component->value);
            named_parameters[idx].value = http_strdup(path_components[i]);
            idx++;
        }
    } else {
        named_parameters = NULL;
    }

    http_path_free(path_components, nb_path_components);

    *proute = route;
    *p_match_result = match_result;

    if (p_named_parameters)
        *p_named_parameters = named_parameters;
    if (p_nb_named_parameters)
        *p_nb_named_parameters = nb_named_parameters;
    return 0;
}