diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index 92b221fdec151f6238550ef682ffe0f7203e0568..991909c4a9fb2a5aa2c94f860451b2c1ffea2844 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -484,20 +484,14 @@ void gcoap_register_listener(gcoap_listener_t *listener); /** * @brief Initializes a CoAP request PDU on a buffer. - - * @warning After you use this function, you may not add Options with option - * number less than COAP_OPT_URI_PATH. Otherwise, use the struct-based API - * described with @link net_nanocoap nanocoap @endlink to initialize the - * message. See the implementation of gcoap_req_init() itself as an example. * * @param[out] pdu Request metadata * @param[out] buf Buffer containing the PDU * @param[in] len Length of the buffer - * @param[in] code Request code: GCOAP_[GET|POST|PUT|DELETE] - * @param[in] path Resource path, *must* start with '/' + * @param[in] code Request code, one of COAP_METHOD_XXX + * @param[in] path Resource path, may be NULL * - * @pre @p path not `NULL` - * @pre @p path must start with `/` + * @pre @p path must start with `/` if not NULL * * @return 0 on success * @return < 0 on error diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index 79c26dc87b485aeaee9e4299282090f25824611e..119a7aaa66b93fabfb94be50cbf751636f622da4 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -645,7 +645,7 @@ void gcoap_register_listener(gcoap_listener_t *listener) int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code, const char *path) { - assert((path != NULL) && (path[0] == '/')); + assert((path == NULL) || (path[0] == '/')); pdu->hdr = (coap_hdr_t *)buf; @@ -669,7 +669,9 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, if (hdrlen > 0) { coap_pkt_init(pdu, buf, len - GCOAP_REQ_OPTIONS_BUF, hdrlen); - coap_opt_add_string(pdu, COAP_OPT_URI_PATH, path, '/'); + if (path != NULL) { + coap_opt_add_string(pdu, COAP_OPT_URI_PATH, path, '/'); + } return 0; } else { diff --git a/tests/unittests/tests-gcoap/tests-gcoap.c b/tests/unittests/tests-gcoap/tests-gcoap.c index d24517d8aadba716a63907985355e6c1978d72a6..a7f82e0a7b5f1a137a948925161444c4e13c3691 100644 --- a/tests/unittests/tests-gcoap/tests-gcoap.c +++ b/tests/unittests/tests-gcoap/tests-gcoap.c @@ -182,6 +182,32 @@ static void test_gcoap__client_get_query(void) TEST_ASSERT_EQUAL_STRING(&expected[0], &query[1]); } +/* + * Builds on get_req test, to test use of NULL path with gcoap_req_init(). + * Then separately add Uri-Path option later. + */ +static void test_gcoap__client_get_path_defer(void) +{ + uint8_t buf[GCOAP_PDU_BUF_SIZE]; + coap_pkt_t pdu; + size_t len, optlen; + char path[] = "/time"; + + gcoap_req_init(&pdu, buf, GCOAP_PDU_BUF_SIZE, COAP_METHOD_GET, NULL); + coap_opt_add_uint(&pdu, COAP_OPT_OBSERVE, 0); + coap_opt_add_string(&pdu, COAP_OPT_URI_PATH, path, '/'); + optlen = 6; + + len = gcoap_finish(&pdu, 0, COAP_FORMAT_NONE); + TEST_ASSERT_EQUAL_INT(len, sizeof(coap_hdr_t) + GCOAP_TOKENLEN + optlen); + + coap_parse(&pdu, buf, len); + + char uri[NANOCOAP_URI_MAX] = {0}; + coap_get_uri_path(&pdu, (uint8_t *)&uri[0]); + TEST_ASSERT_EQUAL_STRING(&path[0], &uri[0]); +} + /* * Helper for server_get tests below. * Request from libcoap example for gcoap_cli /cli/stats resource @@ -346,6 +372,7 @@ Test *tests_gcoap_tests(void) new_TestFixture(test_gcoap__client_get_resp), new_TestFixture(test_gcoap__client_put_req), new_TestFixture(test_gcoap__client_get_query), + new_TestFixture(test_gcoap__client_get_path_defer), new_TestFixture(test_gcoap__server_get_req), new_TestFixture(test_gcoap__server_get_resp), new_TestFixture(test_gcoap__server_con_req),