Skip to content

Commit

Permalink
feat: replace mux with echo
Browse files Browse the repository at this point in the history
  • Loading branch information
im-adithya committed Feb 7, 2024
1 parent 5001afd commit 6135b91
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 62 deletions.
13 changes: 7 additions & 6 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package main

import (
"fmt"
"net/http"

"http-nostr/internal/nostr"
"time"

"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
muxtrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/gorilla/mux"
ddEcho "gopkg.in/DataDog/dd-trace-go.v1/contrib/labstack/echo.v4"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"

"github.com/getsentry/sentry-go"
Expand Down Expand Up @@ -46,16 +46,17 @@ func main() {
defer sentry.Flush(2 * time.Second)
}

r := muxtrace.NewRouter(muxtrace.WithServiceName("http-nostr"))
e := echo.New()
if globalConf.DatadogAgentUrl != "" {
tracer.Start(tracer.WithAgentAddr(globalConf.DatadogAgentUrl))
defer tracer.Stop()
e.Use(ddEcho.Middleware(ddEcho.WithServiceName("http-nostr")))
}

r.HandleFunc("/info", nostr.InfoHandler).Methods(http.MethodGet)
r.HandleFunc("/nip47", nostr.NIP47Handler).Methods(http.MethodPost)
e.GET("/info", nostr.InfoHandler)
e.POST("/nip47", nostr.NIP47Handler)
// r.Use(loggingMiddleware)

logrus.Infof("Server starting on port %d", globalConf.Port)
logrus.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", globalConf.Port), r))
logrus.Fatal(e.Start(fmt.Sprintf(":%d", globalConf.Port)))
}
9 changes: 8 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/getsentry/sentry-go v0.25.0
github.com/joho/godotenv v1.5.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/labstack/echo/v4 v4.11.1
github.com/nbd-wtf/go-nostr v0.25.7
github.com/sirupsen/logrus v1.9.3
gopkg.in/DataDog/dd-trace-go.v1 v1.58.0
Expand Down Expand Up @@ -34,9 +35,11 @@ require (
github.com/golang/glog v1.0.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/outcaste-io/ristretto v0.2.3 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand All @@ -46,11 +49,15 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/atomic v1.11.0 // indirect
go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
Expand Down
23 changes: 21 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBB
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
Expand All @@ -81,8 +79,19 @@ github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4=
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/nbd-wtf/go-nostr v0.25.7 h1:DcGOSgKVr/L6w62tRtKeV2t46sRyFcq9pWcyIFkh0eM=
github.com/nbd-wtf/go-nostr v0.25.7/go.mod h1:bkffJI+x914sPQWum9ZRUn66D7NpDnAoWo1yICvj3/0=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
Expand Down Expand Up @@ -133,6 +142,11 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down Expand Up @@ -185,10 +199,14 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down Expand Up @@ -233,6 +251,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ=
Expand Down
109 changes: 56 additions & 53 deletions internal/nostr/nostr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package nostr

import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"

"github.com/labstack/echo/v4"
"github.com/nbd-wtf/go-nostr"
"github.com/sirupsen/logrus"
)
Expand All @@ -22,6 +23,10 @@ type WalletConnectInfo struct {
Secret string
}

type ErrorResponse struct {
Message string `json:"message"`
}

type InfoRequest struct {
RelayURL string `json:"relayUrl"`
WalletPubkey string `json:"walletPubkey"`
Expand All @@ -38,121 +43,119 @@ func handleError(w http.ResponseWriter, err error, message string, httpStatusCod
http.Error(w, message, httpStatusCode)
}

func InfoHandler(w http.ResponseWriter, r *http.Request) {
req := &InfoRequest{}
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
handleError(w, err, "error decoding client info request", http.StatusBadRequest)
return
func InfoHandler(c echo.Context) error {
var requestData InfoRequest
if err := c.Bind(&requestData); err != nil {
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error decoding info request: %s", err.Error()),
})
}

logrus.Info("Connecting to the relay...")
relay, err := nostr.RelayConnect(r.Context(), req.RelayURL)
relay, err := nostr.RelayConnect(c.Request().Context(), requestData.RelayURL)
if err != nil {
handleError(w, err, "error connecting to relay", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error connecting to relay: %s", err.Error()),
})
}

logrus.Info("Subscribing to info event...")
filter := nostr.Filter{
Authors: []string{req.WalletPubkey},
Authors: []string{requestData.WalletPubkey},
Kinds: []int{NIP_47_INFO_EVENT_KIND},
Limit: 1,
}
ctx, cancel := context.WithTimeout(r.Context(), 60*time.Second)
ctx, cancel := context.WithTimeout(c.Request().Context(), 60*time.Second)
defer cancel()
sub, err := relay.Subscribe(ctx, []nostr.Filter{filter})
if err != nil {
handleError(w, err, "error connecting to relay", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error subscribing to relay: %s", err.Error()),
})
}

select {
case <-ctx.Done():
logrus.Info("Exiting subscription.")
http.Error(w, "request canceled or timed out", http.StatusRequestTimeout)
return
return c.JSON(http.StatusRequestTimeout, ErrorResponse{
Message: "request canceled or timed out",
})
case event := <-sub.Events:
w.Header().Add("Content-type", "application/json")
err = json.NewEncoder(w).Encode(event)
if err != nil {
handleError(w, err, "error encoding response", http.StatusInternalServerError)
}
return
return c.JSON(http.StatusOK, event)
}
}

func NIP47Handler(w http.ResponseWriter, r *http.Request) {
func NIP47Handler(c echo.Context) error {
var requestData NIP47Request
if err := c.Bind(&requestData); err != nil {
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error decoding nip47 request: %s", err.Error()),
})
}
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()

req := &NIP47Request{}
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
handleError(w, err, "error decoding nip47 request", http.StatusBadRequest)
return
}

relay, err := nostr.RelayConnect(ctx, req.RelayURL)
relay, err := nostr.RelayConnect(ctx, requestData.RelayURL)
if err != nil {
handleError(w, err, "error connecting to relay", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error connecting to relay: %s", err.Error()),
})
}

// Start subscribing to the event for response
logrus.WithFields(logrus.Fields{"e": req.SignedEvent.ID, "author": req.WalletPubkey}).Info("Subscribing to events for response...")
logrus.WithFields(logrus.Fields{"e": requestData.SignedEvent.ID, "author": requestData.WalletPubkey}).Info("Subscribing to events for response...")
filter := nostr.Filter{
Authors: []string{req.WalletPubkey},
Authors: []string{requestData.WalletPubkey},
Kinds: []int{NIP_47_RESPONSE_KIND},
Tags: nostr.TagMap{"e": []string{req.SignedEvent.ID}},
Tags: nostr.TagMap{"e": []string{requestData.SignedEvent.ID}},
}
sub, err := relay.Subscribe(ctx, []nostr.Filter{filter})
if err != nil {
handleError(w, err, "error subscribing to events", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error subscribing to relay: %s", err.Error()),
})
}

// Publish the request event
logrus.Info("Publishing request event...")
status, err := relay.Publish(ctx, req.SignedEvent)
status, err := relay.Publish(ctx, requestData.SignedEvent)
if err != nil {
handleError(w, err, "error publishing request event", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error publishing request event: %s", err.Error()),
})
}

if status == nostr.PublishStatusSucceeded {
logrus.WithFields(logrus.Fields{
"status": status,
"eventId": req.SignedEvent.ID,
"eventId": requestData.SignedEvent.ID,
}).Info("Published request")
} else if status == nostr.PublishStatusFailed {
logrus.WithFields(logrus.Fields{
"status": status,
"eventId": req.SignedEvent.ID,
"eventId": requestData.SignedEvent.ID,
}).Info("Failed to publish request")
handleError(w, err, "error publishing request event", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, ErrorResponse{
Message: fmt.Sprintf("error publishing request event: %s", err.Error()),
})
} else {
logrus.WithFields(logrus.Fields{
"status": status,
"eventId": req.SignedEvent.ID,
"eventId": requestData.SignedEvent.ID,
}).Info("Request sent but no response from relay (timeout)")
}

select {
case <-ctx.Done():
logrus.Info("Exiting subscription.")
http.Error(w, "request canceled or timed out", http.StatusRequestTimeout)
return
return c.JSON(http.StatusRequestTimeout, ErrorResponse{
Message: "request canceled or timed out",
})
case event := <-sub.Events:
// TODO: Store the req.SignedEvent.IDs which didn't get
// a response in a DB and use a global subscription to
// respond to them
w.Header().Add("Content-type", "application/json")
err = json.NewEncoder(w).Encode(event)
if err != nil {
handleError(w, err, "error encoding response", http.StatusInternalServerError)
}
logrus.Infof("Successfully received event: %s", event.ID)
return c.JSON(http.StatusOK, event)
}
}

0 comments on commit 6135b91

Please sign in to comment.