From aee44d2f7d15d6ed28d70fe9e456960f4ba9aff8 Mon Sep 17 00:00:00 2001 From: Jozef Kralik <jojo.lwin@gmail.com> Date: Wed, 1 Nov 2023 12:48:39 +0000 Subject: [PATCH] mux: Root path handling improvement This modification ensures that the mux treats both "/" and an empty path ("") as requests to the root path. The reason behind this is the absence of the Uri-path option in CoAP requests in such instances. --- mux/router.go | 2 +- udp/server_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/mux/router.go b/mux/router.go index 2bcafe07..0596f845 100644 --- a/mux/router.go +++ b/mux/router.go @@ -215,7 +215,7 @@ func (r *Router) ServeCOAP(w ResponseWriter, req *Message) { r.m.RLock() defaultHandler := r.defaultHandler r.m.RUnlock() - if err != nil { + if err != nil && !errors.Is(err, message.ErrOptionNotFound) { defaultHandler.ServeCOAP(w, req) return } diff --git a/udp/server_test.go b/udp/server_test.go index 0ec3e22a..4af06146 100644 --- a/udp/server_test.go +++ b/udp/server_test.go @@ -13,6 +13,7 @@ import ( "github.com/plgd-dev/go-coap/v3/message" "github.com/plgd-dev/go-coap/v3/message/codes" "github.com/plgd-dev/go-coap/v3/message/pool" + "github.com/plgd-dev/go-coap/v3/mux" coapNet "github.com/plgd-dev/go-coap/v3/net" "github.com/plgd-dev/go-coap/v3/net/responsewriter" "github.com/plgd-dev/go-coap/v3/options" @@ -603,3 +604,77 @@ func TestServerReconnectNewClient(t *testing.T) { require.False(t, checkMessageID[cc.GetMessageID()]) } } + +func TestMuxPath(t *testing.T) { + r := mux.NewRouter() + err := r.Handle("/", mux.HandlerFunc(handleA)) + require.NoError(t, err) + err = r.Handle("/a", mux.HandlerFunc(handleA)) + require.NoError(t, err) + + l, err := coapNet.NewListenUDP("udp", ":5688") + require.NoError(t, err) + defer func() { + errC := l.Close() + require.NoError(t, errC) + }() + s := udp.NewServer(options.WithMux(r)) + go func() { + errL := s.Serve(l) + require.NoError(t, errL) + }() + + type args struct { + path string + } + tests := []struct { + name string + args args + wantCode codes.Code + }{ + { + name: "empty path", + args: args{path: ""}, + wantCode: codes.Content, + }, + { + name: "root path", + args: args{path: "/"}, + wantCode: codes.Content, + }, + { + name: "a path", + args: args{path: "/a"}, + wantCode: codes.Content, + }, + { + name: "not found path", + args: args{path: "/b"}, + wantCode: codes.NotFound, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testPath(t, tt.args.path, tt.wantCode) + }) + } +} + +func testPath(t *testing.T, path string, expCode codes.Code) { + co, err := udp.Dial("localhost:5688") + require.NoError(t, err) + defer func() { + errC := co.Close() + require.NoError(t, errC) + }() + resp, err := co.Get(context.Background(), path) + require.NoError(t, err) + require.Equal(t, expCode, resp.Code()) +} + +func handleA(w mux.ResponseWriter, _ *mux.Message) { + err := w.SetResponse(codes.Content, message.TextPlain, bytes.NewReader([]byte("hello world"))) + if err != nil { + log.Printf("cannot set response: %v", err) + } +}