|
|
|
@ -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,6 +276,7 @@ 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; |
|
|
|
|
} |
|
|
|
@ -237,6 +287,12 @@ void grpc_uri_destroy(grpc_uri *uri) { |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|