obgm / libcoap

A CoAP (RFC 7252) implementation in C
Other
778 stars 421 forks source link

Resource path issue with '/' character #1340

Open rjmrohit94 opened 4 months ago

rjmrohit94 commented 4 months ago

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.

mrdeep1 commented 4 months ago

@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.

rjmrohit94 commented 4 months ago

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?

mrdeep1 commented 4 months ago

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.

mrdeep1 commented 4 months ago

See https://github.com/obgm/libcoap-minimal/pull/14 for a clean fix where you now just have to define a single CoAP URI to connect to.

mrdeep1 commented 2 months ago

@rjmrohit94 Can this be closed now?

rjmrohit94 commented 2 months ago

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,

mrdeep1 commented 2 months ago

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 '/'.

mrdeep1 commented 2 months ago

Are you able to get this to work correctly now?

mrdeep1 commented 1 month ago

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

rjmrohit94 commented 1 month ago

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.

mrdeep1 commented 1 month ago

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.