gen_coap icon indicating copy to clipboard operation
gen_coap copied to clipboard

Give An Example of Request Routing In The Server

Open drasko opened this issue 7 years ago • 4 comments

Hello, would it be possible to add a small example that explains the request routing in the server and acceding to an appropriate handler for a given URI path.

Currently we have this: https://github.com/gotthardp/gen_coap/blob/master/examples/src/sample_server.erl, and we can figure out if the type of req was GET, POST, PUT, ..., but I see no information how we parse URL string and based on this we call an appropriate handler for this API endpoint.

In general, I would like to understand the CoAP req multiplexer (router) and I would like to see something like this: https://github.com/go-zoo/bone/blob/master/example/001/example.go#L34-L38 as a framework that would enable quick development of the API.

drasko avatar Mar 29 '17 09:03 drasko

Have look at the tests, e.g. https://github.com/gotthardp/gen_coap/blob/master/test/simple_storage_tests.erl. The coap_server_registry:add_handler registers a handler for a given prefix, which is a list of binaries like [<<"A">>, <<"B">>, ...] corresponding to URI path /A/B/.... The multiplexer then takes the longest prefix registered and invokes a specific handler. The handler receives the prefix as the second parameters as well as the rest of the URI as the third parameter. If there is a handler1 for /A and handler2 for /A/B, then a COAP GET call for /A/Z calls handler1:coap_get(_ChId, [<<"A">>], [<<"Z">>], _Query), whereas a call for /A/B calls handler2:coap_get(_ChId, [<<"A">>, <<"B">>], [], _Query). Is it a bit clearer?

gotthardp avatar Mar 29 '17 20:03 gotthardp

If there is a handler1 for /A and handler2 for /A/B... - how do you actually add handler1 and handler2?

I came up with something like:

coap_server_registry:add_handler([<<"test">>], ?MODULE, undefined),
coap_server_registry:add_handler([<<"hello">>], ?MODULE, _Query),
coap_server_registry:add_handler([<<"hello">>, <<"world">>], ?MODULE, undefined).

but they are all calling the same handler called coap_get/4 in the same module.

Also, what does _Query represent here - where does this variable comes from?

One additional question but very important: if I have a URL like:

/A/:B/C

where B is varaible (can change - for example /A/123/C and /A/456/C) and I want to extract this parameter in the handler - what is the best way to do it?

drasko avatar Mar 29 '17 22:03 drasko

The ?MODULE represents the module name. If you call add_handler like this, it will invoke the same module. You should invoke add_handler from different modules, or replace ?MODULE by a module name.

I don't think the last parameter of add_handler is used. It was meant as a parameter for the handler, but no one ever needed that.

To catch /A/:B/C you coap_server_registry:add_handler([<<"A">>], ?MODULE, undefined) and then match handler1:coap_get(_ChId, [<<"A">>], [B, <<"C">>], _Query) which puts content of :B into B. The only thing what is not possible now is to have different modules for /A/:B/C and /A/:B/X, because the prefix (A) is the same for both.

BTW, the _Query in coap_get contains the URI query parameters (?a=x) etc.

gotthardp avatar Mar 30 '17 13:03 gotthardp

image

image

would this help ?

kanishkablack avatar Apr 21 '17 18:04 kanishkablack