From c1fcf80166f50941b5329797f10009878bba1fb8 Mon Sep 17 00:00:00 2001 From: Dengke Tang Date: Fri, 22 Dec 2023 14:05:40 -0800 Subject: [PATCH 1/4] add a query string helper from byte cursor directly --- include/aws/common/uri.h | 22 ++++++++++++++++++++++ source/uri.c | 21 +++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/aws/common/uri.h b/include/aws/common/uri.h index 0ac1fd9b3..1999ae793 100644 --- a/include/aws/common/uri.h +++ b/include/aws/common/uri.h @@ -136,6 +136,28 @@ AWS_COMMON_API bool aws_uri_query_string_next_param(const struct aws_uri *uri, s */ AWS_COMMON_API int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params); +/** + * For iterating over the params in the query string. + * `param` is an in/out argument used to track progress, it MUST be zeroed out to start. + * If true is returned, `param` contains the value of the next param. + * If false is returned, there are no further params. + * + * Edge cases: + * 1) Entries without '=' sign are treated as having a key and no value. + * Example: First param in query string "a&b=c" has key="a" value="" + * + * 2) Blank entries are skipped. + * Example: The only param in query string "&&a=b" is key="a" value="b" + */ +AWS_COMMON_API bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param); + +/** + * Parses query string and stores the parameters in 'out_params'. Returns AWS_OP_SUCCESS on success and + * AWS_OP_ERR on failure. The user is responsible for initializing out_params with item size of struct aws_query_param. + * The user is also responsible for cleaning up out_params when finished. + */ +AWS_COMMON_API int aws_query_string_params(struct aws_byte_cursor query_string, struct aws_array_list *out_params); + /** * Writes the uri path encoding of a cursor to a buffer. This is the modified version of rfc3986 used by * sigv4 signing. diff --git a/source/uri.c b/source/uri.c index cefe57e87..37dee320d 100644 --- a/source/uri.c +++ b/source/uri.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -212,7 +213,7 @@ uint16_t aws_uri_port(const struct aws_uri *uri) { return uri->port; } -bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { +bool aws_query_string_next_param(struct aws_byte_cursor query_string_cursor, struct aws_uri_param *param) { /* If param is zeroed, then this is the first run. */ bool first_run = param->value.ptr == NULL; @@ -230,7 +231,7 @@ bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_p /* The do-while is to skip over any empty substrings */ do { - if (!aws_byte_cursor_next_split(&uri->query_string, '&', &substr)) { + if (!aws_byte_cursor_next_split(&query_string_cursor, '&', &substr)) { /* no more splits, done iterating */ return false; } @@ -252,6 +253,22 @@ bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_p return true; } +int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct aws_array_list *out_params) { + struct aws_uri_param param; + AWS_ZERO_STRUCT(param); + while (aws_query_string_next_param(query_string_cursor, ¶m)) { + if (aws_array_list_push_back(out_params, ¶m)) { + return AWS_OP_ERR; + } + } + + return AWS_OP_SUCCESS; +} + +bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { + return aws_query_string_next_param(uri->query_string, param); +} + int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params) { struct aws_uri_param param; AWS_ZERO_STRUCT(param); From ccf16c722de69b5ef445642a7984984ad0191ee9 Mon Sep 17 00:00:00 2001 From: Dengke Tang Date: Fri, 22 Dec 2023 14:06:39 -0800 Subject: [PATCH 2/4] don't need string now --- source/uri.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/uri.c b/source/uri.c index 37dee320d..16a29fc13 100644 --- a/source/uri.c +++ b/source/uri.c @@ -5,7 +5,6 @@ #include #include -#include #include #include From eb70a19296b294a3b067a9aa31b7d5a25296d1a7 Mon Sep 17 00:00:00 2001 From: Dengke Tang Date: Wed, 27 Dec 2023 12:12:58 -0800 Subject: [PATCH 3/4] fix --- include/aws/common/uri.h | 14 ++++++++------ source/uri.c | 18 +++++------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/include/aws/common/uri.h b/include/aws/common/uri.h index 1999ae793..63b7051da 100644 --- a/include/aws/common/uri.h +++ b/include/aws/common/uri.h @@ -115,7 +115,7 @@ AWS_COMMON_API uint16_t aws_uri_port(const struct aws_uri *uri); AWS_COMMON_API const struct aws_byte_cursor *aws_uri_path_and_query(const struct aws_uri *uri); /** - * For iterating over the params in the uri query string. + * For iterating over the params in the query string. * `param` is an in/out argument used to track progress, it MUST be zeroed out to start. * If true is returned, `param` contains the value of the next param. * If false is returned, there are no further params. @@ -127,17 +127,19 @@ AWS_COMMON_API const struct aws_byte_cursor *aws_uri_path_and_query(const struct * 2) Blank entries are skipped. * Example: The only param in query string "&&a=b" is key="a" value="b" */ -AWS_COMMON_API bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param); +AWS_COMMON_API bool aws_query_string_next_param( + const struct aws_byte_cursor *query_string, + struct aws_uri_param *param); /** * Parses query string and stores the parameters in 'out_params'. Returns AWS_OP_SUCCESS on success and * AWS_OP_ERR on failure. The user is responsible for initializing out_params with item size of struct aws_query_param. * The user is also responsible for cleaning up out_params when finished. */ -AWS_COMMON_API int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params); +AWS_COMMON_API int aws_query_string_params(struct aws_byte_cursor query_string, struct aws_array_list *out_params); /** - * For iterating over the params in the query string. + * For iterating over the params in the uri query string. * `param` is an in/out argument used to track progress, it MUST be zeroed out to start. * If true is returned, `param` contains the value of the next param. * If false is returned, there are no further params. @@ -149,14 +151,14 @@ AWS_COMMON_API int aws_uri_query_string_params(const struct aws_uri *uri, struct * 2) Blank entries are skipped. * Example: The only param in query string "&&a=b" is key="a" value="b" */ -AWS_COMMON_API bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param); +AWS_COMMON_API bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param); /** * Parses query string and stores the parameters in 'out_params'. Returns AWS_OP_SUCCESS on success and * AWS_OP_ERR on failure. The user is responsible for initializing out_params with item size of struct aws_query_param. * The user is also responsible for cleaning up out_params when finished. */ -AWS_COMMON_API int aws_query_string_params(struct aws_byte_cursor query_string, struct aws_array_list *out_params); +AWS_COMMON_API int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params); /** * Writes the uri path encoding of a cursor to a buffer. This is the modified version of rfc3986 used by diff --git a/source/uri.c b/source/uri.c index 16a29fc13..e30e4729b 100644 --- a/source/uri.c +++ b/source/uri.c @@ -212,7 +212,7 @@ uint16_t aws_uri_port(const struct aws_uri *uri) { return uri->port; } -bool aws_query_string_next_param(struct aws_byte_cursor query_string_cursor, struct aws_uri_param *param) { +bool aws_query_string_next_param(const struct aws_byte_cursor *query_string_cursor, struct aws_uri_param *param) { /* If param is zeroed, then this is the first run. */ bool first_run = param->value.ptr == NULL; @@ -230,7 +230,7 @@ bool aws_query_string_next_param(struct aws_byte_cursor query_string_cursor, str /* The do-while is to skip over any empty substrings */ do { - if (!aws_byte_cursor_next_split(&query_string_cursor, '&', &substr)) { + if (!aws_byte_cursor_next_split(query_string_cursor, '&', &substr)) { /* no more splits, done iterating */ return false; } @@ -255,7 +255,7 @@ bool aws_query_string_next_param(struct aws_byte_cursor query_string_cursor, str int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct aws_array_list *out_params) { struct aws_uri_param param; AWS_ZERO_STRUCT(param); - while (aws_query_string_next_param(query_string_cursor, ¶m)) { + while (aws_query_string_next_param(&query_string_cursor, ¶m)) { if (aws_array_list_push_back(out_params, ¶m)) { return AWS_OP_ERR; } @@ -265,19 +265,11 @@ int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct a } bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { - return aws_query_string_next_param(uri->query_string, param); + return aws_query_string_next_param(&uri->query_string, param); } int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params) { - struct aws_uri_param param; - AWS_ZERO_STRUCT(param); - while (aws_uri_query_string_next_param(uri, ¶m)) { - if (aws_array_list_push_back(out_params, ¶m)) { - return AWS_OP_ERR; - } - } - - return AWS_OP_SUCCESS; + return aws_query_string_params(uri->query_string, out_params); } static void s_parse_scheme(struct uri_parser *parser, struct aws_byte_cursor *str) { From 7bde526c044be725da2c7b906565c5ae00160ebb Mon Sep 17 00:00:00 2001 From: Dengke Tang Date: Wed, 27 Dec 2023 16:16:52 -0800 Subject: [PATCH 4/4] comments addressed --- include/aws/common/uri.h | 4 +--- source/uri.c | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/aws/common/uri.h b/include/aws/common/uri.h index 63b7051da..edc3fb2bd 100644 --- a/include/aws/common/uri.h +++ b/include/aws/common/uri.h @@ -127,9 +127,7 @@ AWS_COMMON_API const struct aws_byte_cursor *aws_uri_path_and_query(const struct * 2) Blank entries are skipped. * Example: The only param in query string "&&a=b" is key="a" value="b" */ -AWS_COMMON_API bool aws_query_string_next_param( - const struct aws_byte_cursor *query_string, - struct aws_uri_param *param); +AWS_COMMON_API bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param); /** * Parses query string and stores the parameters in 'out_params'. Returns AWS_OP_SUCCESS on success and diff --git a/source/uri.c b/source/uri.c index e30e4729b..9e6920488 100644 --- a/source/uri.c +++ b/source/uri.c @@ -212,7 +212,7 @@ uint16_t aws_uri_port(const struct aws_uri *uri) { return uri->port; } -bool aws_query_string_next_param(const struct aws_byte_cursor *query_string_cursor, struct aws_uri_param *param) { +bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param) { /* If param is zeroed, then this is the first run. */ bool first_run = param->value.ptr == NULL; @@ -230,7 +230,7 @@ bool aws_query_string_next_param(const struct aws_byte_cursor *query_string_curs /* The do-while is to skip over any empty substrings */ do { - if (!aws_byte_cursor_next_split(query_string_cursor, '&', &substr)) { + if (!aws_byte_cursor_next_split(&query_string, '&', &substr)) { /* no more splits, done iterating */ return false; } @@ -255,7 +255,7 @@ bool aws_query_string_next_param(const struct aws_byte_cursor *query_string_curs int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct aws_array_list *out_params) { struct aws_uri_param param; AWS_ZERO_STRUCT(param); - while (aws_query_string_next_param(&query_string_cursor, ¶m)) { + while (aws_query_string_next_param(query_string_cursor, ¶m)) { if (aws_array_list_push_back(out_params, ¶m)) { return AWS_OP_ERR; } @@ -265,7 +265,7 @@ int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct a } bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { - return aws_query_string_next_param(&uri->query_string, param); + return aws_query_string_next_param(uri->query_string, param); } int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params) {