Merge branch 'uri_query_parts' into sockaddr_resolver_lb_2

pull/6037/head
David Garcia Quintas 9 years ago
commit fec8ece176
  1. 56
      src/core/lib/client_config/uri_parser.c
  2. 8
      src/core/lib/client_config/uri_parser.h
  3. 46
      test/core/client_config/uri_parser_test.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,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);
}

@ -34,11 +34,19 @@
#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;

@ -56,6 +56,51 @@ static void test_fails(const char *uri_text) {
GPR_ASSERT(NULL == grpc_uri_parse(uri_text, 0));
}
static void test_query_parts() {
{
const char *uri_text = "http://foo/path?a&b=B&c=&#frag";
grpc_uri *uri = grpc_uri_parse(uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme));
GPR_ASSERT(0 == strcmp("foo", uri->authority));
GPR_ASSERT(0 == strcmp("/path", uri->path));
GPR_ASSERT(0 == strcmp("a&b=B&c=&", uri->query));
GPR_ASSERT(4 == uri->num_query_parts);
GPR_ASSERT(0 == strcmp("a", uri->query_parts[0]));
GPR_ASSERT(NULL == uri->query_parts_values[0]);
GPR_ASSERT(0 == strcmp("b", uri->query_parts[1]));
GPR_ASSERT(0 == strcmp("B", uri->query_parts_values[1]));
GPR_ASSERT(0 == strcmp("c", uri->query_parts[2]));
GPR_ASSERT(0 == strcmp("", uri->query_parts_values[2]));
GPR_ASSERT(0 == strcmp("", uri->query_parts[3]));
GPR_ASSERT(NULL == uri->query_parts_values[3]);
GPR_ASSERT(0 == strcmp("frag", uri->fragment));
grpc_uri_destroy(uri);
}
{
/* empty query */
const char *uri_text = "http://foo/path";
grpc_uri *uri = grpc_uri_parse(uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme));
GPR_ASSERT(0 == strcmp("foo", uri->authority));
GPR_ASSERT(0 == strcmp("/path", uri->path));
GPR_ASSERT(0 == strcmp("", uri->query));
GPR_ASSERT(0 == uri->num_query_parts);
GPR_ASSERT(NULL == uri->query_parts);
GPR_ASSERT(NULL == uri->query_parts_values);
GPR_ASSERT(0 == strcmp("", uri->fragment));
grpc_uri_destroy(uri);
}
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_succeeds("http://www.google.com", "http", "www.google.com", "", "", "");
@ -82,5 +127,6 @@ int main(int argc, char **argv) {
test_fails("http://foo?x[bar]");
test_fails("http://foo?bar#lol#");
test_query_parts();
return 0;
}

Loading…
Cancel
Save