diff options
author | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-03-31 17:08:17 -0700 |
---|---|---|
committer | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-03-31 17:08:17 -0700 |
commit | 38d812077be28f9837a5bf3ffd42a86396cb9d98 (patch) | |
tree | 50a648b662e55d1c6b4e67cf9c21fa8227403fa2 /src/core | |
parent | 6a362747571b6a47c3a84c8e2df25814230a53a7 (diff) | |
parent | f341374f6f903fff231df71298c30a4a973ea792 (diff) |
Merge pull request #6034 from dgquintas/uri_query_parts
Added & and = to URI queries
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/lib/client_config/uri_parser.c | 68 | ||||
-rw-r--r-- | src/core/lib/client_config/uri_parser.h | 12 |
2 files changed, 80 insertions, 0 deletions
diff --git a/src/core/lib/client_config/uri_parser.c b/src/core/lib/client_config/uri_parser.c index b4ee763735..6bec70da2d 100644 --- a/src/core/lib/client_config/uri_parser.c +++ b/src/core/lib/client_config/uri_parser.c @@ -38,8 +38,12 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/port_platform.h> +#include <grpc/support/slice.h> +#include <grpc/support/slice_buffer.h> #include <grpc/support/string_util.h> +#include "src/core/lib/support/string.h" + /** a size_t default value... maps to all 1's */ #define NOT_SET (~(size_t)0) @@ -133,6 +137,51 @@ static int parse_fragment_or_query(const char *uri_text, size_t *i) { return 1; } +static void do_nothing(void *ignored) {} +static void parse_query_parts(grpc_uri *uri) { + static const char *QUERY_PARTS_SEPARATOR = "&"; + static const char *QUERY_PARTS_VALUE_SEPARATOR = "="; + GPR_ASSERT(uri->query != NULL); + if (uri->query[0] == '\0') { + uri->query_parts = NULL; + uri->query_parts_values = NULL; + uri->num_query_parts = 0; + return; + } + gpr_slice query_slice = + gpr_slice_new(uri->query, strlen(uri->query), do_nothing); + gpr_slice_buffer query_parts; /* the &-separated elements of the query */ + gpr_slice_buffer query_param_parts; /* the =-separated subelements */ + + gpr_slice_buffer_init(&query_parts); + gpr_slice_buffer_init(&query_param_parts); + + gpr_slice_split(query_slice, QUERY_PARTS_SEPARATOR, &query_parts); + uri->query_parts = gpr_malloc(query_parts.count * sizeof(char *)); + uri->query_parts_values = gpr_malloc(query_parts.count * sizeof(char *)); + uri->num_query_parts = query_parts.count; + for (size_t i = 0; i < query_parts.count; i++) { + gpr_slice_split(query_parts.slices[i], QUERY_PARTS_VALUE_SEPARATOR, + &query_param_parts); + GPR_ASSERT(query_param_parts.count > 0); + uri->query_parts[i] = + gpr_dump_slice(query_param_parts.slices[0], GPR_DUMP_ASCII); + if (query_param_parts.count > 1) { + /* TODO(dgq): only the first value after the separator is considered. + * Perhaps all chars after the first separator for the query part should + * be included, even if they include the separator. */ + uri->query_parts_values[i] = + gpr_dump_slice(query_param_parts.slices[1], GPR_DUMP_ASCII); + } else { + uri->query_parts_values[i] = NULL; + } + gpr_slice_buffer_reset_and_unref(&query_param_parts); + } + gpr_slice_buffer_destroy(&query_parts); + gpr_slice_buffer_destroy(&query_param_parts); + gpr_slice_unref(query_slice); +} + grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) { grpc_uri *uri; size_t scheme_begin = 0; @@ -227,16 +276,35 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) { uri->path = copy_component(uri_text, path_begin, path_end); uri->query = copy_component(uri_text, query_begin, query_end); uri->fragment = copy_component(uri_text, fragment_begin, fragment_end); + parse_query_parts(uri); return uri; } +const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key) { + GPR_ASSERT(key != NULL); + if (key[0] == '\0') return NULL; + + for (size_t i = 0; i < uri->num_query_parts; ++i) { + if (0 == strcmp(key, uri->query_parts[i])) { + return uri->query_parts_values[i]; + } + } + return NULL; +} + void grpc_uri_destroy(grpc_uri *uri) { if (!uri) return; gpr_free(uri->scheme); gpr_free(uri->authority); gpr_free(uri->path); gpr_free(uri->query); + for (size_t i = 0; i < uri->num_query_parts; ++i) { + gpr_free(uri->query_parts[i]); + gpr_free(uri->query_parts_values[i]); + } + gpr_free(uri->query_parts); + gpr_free(uri->query_parts_values); gpr_free(uri->fragment); gpr_free(uri); } diff --git a/src/core/lib/client_config/uri_parser.h b/src/core/lib/client_config/uri_parser.h index 4f8e809b2e..5d6785d293 100644 --- a/src/core/lib/client_config/uri_parser.h +++ b/src/core/lib/client_config/uri_parser.h @@ -34,17 +34,29 @@ #ifndef GRPC_CORE_LIB_CLIENT_CONFIG_URI_PARSER_H #define GRPC_CORE_LIB_CLIENT_CONFIG_URI_PARSER_H +#include <stddef.h> + typedef struct { char *scheme; char *authority; char *path; char *query; + /** Query substrings separated by '&' */ + char **query_parts; + /** Number of elements in \a query_parts and \a query_parts_values */ + size_t num_query_parts; + /** Split each query part by '='. NULL if not present. */ + char **query_parts_values; char *fragment; } grpc_uri; /** parse a uri, return NULL on failure */ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors); +/** return the part of a query string after the '=' in "?key=xxx&...", or NULL + * if key is not present */ +const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key); + /** destroy a uri */ void grpc_uri_destroy(grpc_uri *uri); |