Skip to content

Commit

Permalink
feat: pubsub router
Browse files Browse the repository at this point in the history
  • Loading branch information
brokeyourbike committed Apr 10, 2024
1 parent f606168 commit be5eba7
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 0 deletions.
65 changes: 65 additions & 0 deletions q/pubsub-router/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package pubsubrouter

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"

"github.com/gin-gonic/gin"
"github.com/glocurrency/commons/instrumentation"
"github.com/glocurrency/commons/q"
)

type router struct {
*gin.Engine
prefix string
}

func NewRouter(engine *gin.Engine, prefix string) *router {
return &router{Engine: engine, prefix: prefix}
}

func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if strings.Contains(req.URL.Path, r.prefix) {
if err := RewriteForPubSub(req); err != nil {
instrumentation.NoticeError(context.Background(), err, "cannot rewrite",
instrumentation.WithField("prefix", r.prefix))
}
}
r.Engine.ServeHTTP(w, req)
}

func RewriteForPubSub(req *http.Request) error {
data, err := io.ReadAll(req.Body)
if err != nil {
return fmt.Errorf("cannot read body: %w", err)
}

req.Body = io.NopCloser(bytes.NewBuffer(data))

var msg q.PubSubMessage
if err := json.Unmarshal(data, &msg); err != nil {
return fmt.Errorf("cannot unmarshal '%s': %w", string(data), err)
}

name := msg.GetName()
if name == "" {
return nil
}

parsedURI, err := url.ParseRequestURI(req.RequestURI)
if err != nil {
return fmt.Errorf("cannot parse uri '%s': %w", req.RequestURI, err)
}

parsedURI.Path = strings.TrimRight(parsedURI.Path, "/") + "/" + name
req.RequestURI = parsedURI.String()

req.URL.Path = strings.TrimRight(req.URL.Path, "/") + "/" + name
return nil
}
68 changes: 68 additions & 0 deletions q/pubsub-router/router_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package pubsubrouter_test

import (
"bytes"
_ "embed"
"net/http"
"net/http/httptest"
"os"
"testing"

"github.com/gin-gonic/gin"
pubsubrouter "github.com/glocurrency/commons/q/pubsub-router"
"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
gin.SetMode(gin.ReleaseMode)
os.Exit(m.Run())
}

//go:embed testdata/with-name-d.json
var withNameD []byte

//go:embed testdata/with-name-e.json
var withNameE []byte

//go:embed testdata/with-name-def.json
var withNameDEF []byte

func TestRouting(t *testing.T) {
tests := []struct {
name string
url string
body []byte
wantStatus int
}{
{"pubsub not found", "/abc", nil, http.StatusNotFound},
{"pubsub not found, name do not match route", "/abc", withNameE, http.StatusNotFound},
{"pubsub routed", "/abc", withNameD, http.StatusAccepted},
{"pubsub routed", "/abc?a=b", withNameD, http.StatusAccepted},
{"pubsub routed", "/abc/", withNameD, http.StatusAccepted},
{"pubsub routed", "/abc/?a=b", withNameD, http.StatusAccepted},
{"pubsub routed", "/abc", withNameDEF, http.StatusAccepted},
{"not pubpub", "/123/4", withNameD, http.StatusOK},
}

for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()

w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, test.url, bytes.NewReader(test.body))

router := pubsubrouter.NewRouter(gin.New(), "/abc")

group1 := router.Group("/abc")
group1.POST("d", func(ctx *gin.Context) { ctx.Status(http.StatusAccepted) })
group1.POST("d-e-f", func(ctx *gin.Context) { ctx.Status(http.StatusAccepted) })

group2 := router.Group("/123")
group2.POST("4", func(ctx *gin.Context) { ctx.Status(http.StatusOK) })

router.ServeHTTP(w, req)
assert.Equal(t, test.wantStatus, w.Code)
})
}
}
10 changes: 10 additions & 0 deletions q/pubsub-router/testdata/with-name-d.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": {
"messageId": "158b5c5d-ce6b-4020-b822-ceb0e43b754a",
"publishTime": "2023-07-09T17:49:48.087822341Z",
"attributes": {
"nameKey": "d"
}
},
"subscription": "sub-123"
}
10 changes: 10 additions & 0 deletions q/pubsub-router/testdata/with-name-def.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": {
"messageId": "158b5c5d-ce6b-4020-b822-ceb0e43b754a",
"publishTime": "2023-07-09T17:49:48.087822341Z",
"attributes": {
"nameKey": "d-e-f"
}
},
"subscription": "sub-123"
}
10 changes: 10 additions & 0 deletions q/pubsub-router/testdata/with-name-e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": {
"messageId": "158b5c5d-ce6b-4020-b822-ceb0e43b754a",
"publishTime": "2023-07-09T17:49:48.087822341Z",
"attributes": {
"nameKey": "e"
}
},
"subscription": "sub-123"
}

0 comments on commit be5eba7

Please sign in to comment.