plgd-dev / go-coap

Implementation of CoAP Server & Client in Go

Home Page:https://coap.technology

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implement Support for Separate Messages in Server

bukacdan opened this issue · comments

Hello,

I'm currently working on a CoAP proxy to an HTTP server. Given the potential latency and variance in HTTP responses, it's essential for the proxy to immediately send an ACKNOWLEDGEMENT message and then deliver the HTTP response as a Separate message when it's ready. This ensures that the CoAP client doesn't repeatedly retransmit the request message, especially when waiting for potentially slow HTTP responses.

I've referred to RFC 7252 (The Constrained Application Protocol) and noticed the detailed description of the Separate messages feature in Section 5.2.2. This would be a perfect fit for the feature I need.

Currently, I couldn't find an easy way to support this feature using the server provided by the library.

Request:
Could the library be extended to provide native support for sending separate response messages? It would be beneficial to have:

A mechanism to immediately send an ACKNOWLEDGEMENT once a request is received.
Then, once the actual resource representation (in my case, HTTP response) is available, send it as a separate response.

Previous Issue Reference:
I noticed that there is a prior issue opened regarding this feature. Unfortunately, it appears that it hasn't been resolved. Given the importance and potential utility of this feature for various applications, I wanted to bring it to your attention again.

Thank you for considering this request, and I appreciate the work you've done on this library. I hope this feature, if implemented, will enhance its usability for many other developers facing similar challenges.

Hi @bukacdan
From my perspective, the provided code snippet is backed by the current version. You might want to experiment with a similar handler within your server:

package main
import (
	"bytes"
	"log"

	coap "github.com/plgd-dev/go-coap/v3"
	"github.com/plgd-dev/go-coap/v3/message"
	"github.com/plgd-dev/go-coap/v3/message/codes"
	"github.com/plgd-dev/go-coap/v3/mux"
	"github.com/plgd-dev/go-coap/v3/udp/client"
)

func handleB(w mux.ResponseWriter, r *mux.Message) {
  // empty handle sends just empty acknoweldge response
  go func() {
	// Perform necessary actions...
	// ...
	// Construct an actual response for the request with confirmation as is described in RFC 7252 5.2.2
	customResp := w.Conn().AcquireMessage(r.Context())
	defer w.Conn().ReleaseMessage(customResp)
        customResp.SetType(message.Confirmable) // set Confirmable message
	customResp.SetMessageID(w.Conn().(*client.Conn).GetMessageID()) // generate new message id for Confirmable message
	// Custom the response and options
        customResp.SetCode(codes.Content)
	customResp.SetToken(r.Token())
	customResp.SetContentFormat(message.TextPlain)
	customResp.SetBody(bytes.NewReader([]byte("B hello world")))
	err := w.Conn().WriteMessage(customResp)
	if err != nil {
		log.Printf("cannot set response: %v", err)
	}
  }
}

func main() {
	r := mux.NewRouter()
	r.Use(loggingMiddleware)
	r.Handle("/example", mux.HandlerFunc(handleB))

	log.Fatal(coap.ListenAndServe("udp", ":5688", r))
}