obgm/libcoap

Resource path issue with '/' character

Closed this issue · 12 comments

Try using libcoap-minimal ( for simplicity)
Just change the resource from hello to something like "hello/hi" in server and client. Basically, any API with a '/'. It will always return a resource not found error.
Looks like an issue with processing the ASCII characters.

@rjmrohit94 I think your underlying issue is that with the client, it is connecting to coap.me (L#28), a site that has a limited set of resources to interrogate, rather than you are connecting to your local server. If you do a GET for coap://coap.me/.well-known/core , you will get a list of the available resources at coap.me.

Oh sorry I forgot to mention that I had changed it from coap.me to local host ie 127.0.0.1 in both client and server.

Let us say the api I am trying to reach is hello/hi from the client.

I will have to do like this in the server
coap_make_str_const("hello%2Fhi")
to make it work

I was expecting we can do like coap_make_str_const("hello/hi") this.

Is this the expected behavior?

OK - can see what the issue is. It involves some code changes (should be using coap_split_uri()). I will get a fix and upload it.

See obgm/libcoap-minimal#14 for a clean fix where you now just have to define a single CoAP URI to connect to.

@rjmrohit94 Can this be closed now?

Sorry for the late reply.

I could not get it resolved, instead as a temporary fix, I changed my server code to use %2F instead of '/'

I have many custom URIs which needs to supported, not just the well known ones.
I looked into the logic of the library I could not find where the issue is. Somewhere while reading and registering resource handlers, it seems like it is not able to identify '/' as ASCII,

Hmm. Not sure what is happening here. With this change (libcoap-minimal)

diff --git a/server.cc b/server.cc
index 16bcf90..73e01a9 100644
--- a/server.cc
+++ b/server.cc
@@ -27,7 +27,7 @@ main(void) {
   coap_context_t  *ctx = nullptr;
   coap_resource_t *resource = nullptr;
   int result = EXIT_FAILURE;;
-  coap_str_const_t *ruri = coap_make_str_const("hello");
+  coap_str_const_t *ruri = coap_make_str_const("hello/me");
   uint32_t scheme_hint_bits;
   coap_addr_info_t *info = nullptr;
   coap_addr_info_t *info_list = nullptr;

With the server running, using the client, I get

$ ./client coap://127.0.0.1/hello/me
v:1 t:CON c:GET i:cf62 {} [ Uri-Path:hello, Uri-Path:me ]
v:1 t:ACK c:2.05 i:cf62 {} [ ] :: 'world'
world

$ ./client coap://127.0.0.1/hello
v:1 t:CON c:GET i:9ef1 {} [ Uri-Path:hello ]
v:1 t:ACK c:4.04 i:9ef1 {} [ ] :: 'Not Found'
Not Found

as expected. Note that the requested path is broken down into individual Uri-Path options where the implicit separator is '/'.

Are you able to get this to work correctly now?

@rjmrohit94 Are you still having issues here, or can this Issue be closed?

The issue is with custom APIs not included in the well known, it is not limited to libcoap minimal.

Lets say,
I want to have a server with my own APIs( as I understand, the protocol supports any APIs and not just the well known cores).
If I create a resource handler and register the resource, I see problem with the '/' not being parsed correctly.

Please try making the following change to the latest version of libcoap-minimal main branch

diff --git a/server.cc b/server.cc
index f8659b9..b0c6caf 100644
--- a/server.cc
+++ b/server.cc
@@ -93,6 +93,32 @@ main(void) {
                            coap_show_pdu(COAP_LOG_WARN, response);
                          });
   coap_add_resource(ctx, resource);
+  /* Create a resource that the server can respond to with information */
+  resource = coap_resource_init(coap_make_str_const("hello/my"), 0);
+  coap_register_handler(resource, COAP_REQUEST_GET,
+                        [](auto, auto,
+                           const coap_pdu_t *request,
+                           auto, coap_pdu_t *response) {
+                           coap_show_pdu(COAP_LOG_WARN, request);
+                           coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
+                           coap_add_data(response, 8,
+                                         (const uint8_t *)"my world");
+                           coap_show_pdu(COAP_LOG_WARN, response);
+                         });
+  coap_add_resource(ctx, resource);
+  /* Create a resource that the server can respond to with information */
+  resource = coap_resource_init(coap_make_str_const("1/2/3/4/5/6/7/8/hello"), 0);
+  coap_register_handler(resource, COAP_REQUEST_GET,
+                        [](auto, auto,
+                           const coap_pdu_t *request,
+                           auto, coap_pdu_t *response) {
+                           coap_show_pdu(COAP_LOG_WARN, request);
+                           coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
+                           coap_add_data(response, 21,
+                                         (const uint8_t *)"1-2-3-4-5-6-7-8-hello");
+                           coap_show_pdu(COAP_LOG_WARN, response);
+                         });
+  coap_add_resource(ctx, resource);

   /* Handle any libcoap I/O requirements */
   while (true) {

Compile the code, then
Window 1

$ ./server

and in Window 2, run the following 3 commands (resultant output shown as well)

$ ./client coap://127.0.0.1/hello
v:1 t:CON c:GET i:0e73 {} [ Uri-Path:hello ]
v:1 t:ACK c:2.05 i:0e73 {} [ ] :: 'world'
world
main [jon@ubuntu22 ~/libcoap-minimal]
$ ./client coap://127.0.0.1/hello/my
v:1 t:CON c:GET i:c801 {} [ Uri-Path:hello, Uri-Path:my ]
v:1 t:ACK c:2.05 i:c801 {} [ ] :: 'my world'
my world
main [jon@ubuntu22 ~/libcoap-minimal]
$ ./client coap://127.0.0.1/1/2/3/4/5/6/7/8/hello
v:1 t:CON c:GET i:256a {} [ Uri-Path:1, Uri-Path:2, Uri-Path:3, Uri-Path:4, Uri-Path:5, Uri-Path:6, Uri-Path:7, Uri-Path:8, Uri-Path:hello ]
v:1 t:ACK c:2.05 i:256a {} [ ] :: '1-2-3-4-5-6-7-8-hello'
1-2-3-4-5-6-7-8-hello

Here, '/' is being handled as expected.

Issue number 1485 resolves this