Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at eli/leaky-error-cases 94 lines 2.6 kB view raw
1package spxrpc 2 3import ( 4 "context" 5 "net/http" 6 7 "github.com/labstack/echo/v4" 8 "github.com/slok/go-http-metrics/middleware" 9 echomiddleware "github.com/slok/go-http-metrics/middleware/echo" 10 "github.com/streamplace/oatproxy/pkg/oatproxy" 11 "stream.place/streamplace/pkg/config" 12 "stream.place/streamplace/pkg/log" 13 "stream.place/streamplace/pkg/model" 14) 15 16type Server struct { 17 e *echo.Echo 18 cli *config.CLI 19 model model.Model 20} 21 22func NewServer(ctx context.Context, cli *config.CLI, model model.Model, op *oatproxy.OATProxy, mdlw middleware.Middleware) (*Server, error) { 23 e := echo.New() 24 s := &Server{ 25 e: e, 26 cli: cli, 27 model: model, 28 } 29 e.Use(s.ErrorHandlingMiddleware()) 30 e.Use(s.ContextPreservingMiddleware()) 31 e.Use(echomiddleware.Handler("", mdlw)) 32 e.Use(op.OAuthMiddleware) 33 err := s.RegisterHandlersPlaceStream(e) 34 if err != nil { 35 return nil, err 36 } 37 err = s.RegisterHandlersAppBsky(e) 38 if err != nil { 39 return nil, err 40 } 41 err = s.RegisterHandlersComAtproto(e) 42 if err != nil { 43 return nil, err 44 } 45 e.GET("/xrpc/_health", func(c echo.Context) error { 46 return c.JSON(http.StatusOK, map[string]string{"version": cli.Build.Version}) 47 }) 48 e.GET("/xrpc/com.atproto.sync.subscribeRepos", s.handleComAtprotoSyncSubscribeRepos) 49 e.GET("/xrpc/*", s.HandleWildcard) 50 e.POST("/xrpc/*", s.HandleWildcard) 51 return s, nil 52} 53 54func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 55 s.e.ServeHTTP(w, r) 56} 57 58func (s *Server) ErrorHandlingMiddleware() echo.MiddlewareFunc { 59 return func(next echo.HandlerFunc) echo.HandlerFunc { 60 return func(c echo.Context) error { 61 err := next(c) 62 if err == nil { 63 return nil 64 } 65 httpError, ok := err.(*echo.HTTPError) 66 if ok { 67 log.Error(c.Request().Context(), "http error", "code", httpError.Code, "message", httpError.Message, "internal", httpError.Internal) 68 return err 69 } 70 log.Error(c.Request().Context(), "unhandled error", "error", err) 71 return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) 72 } 73 } 74} 75 76// unique type to prevent assignment. 77type echoContextKeyType struct{} 78 79// singleton value to identify our logging metadata in context 80var echoContextKey = echoContextKeyType{} 81 82func (s *Server) ContextPreservingMiddleware() echo.MiddlewareFunc { 83 return func(next echo.HandlerFunc) echo.HandlerFunc { 84 return func(c echo.Context) error { 85 ctx := c.Request().Context() 86 if ctx == nil { 87 ctx = context.Background() 88 } 89 ctx = context.WithValue(ctx, echoContextKey, c) 90 c.SetRequest(c.Request().WithContext(ctx)) 91 return next(c) 92 } 93 } 94}