diff --git a/go.mod b/go.mod index f0dc553..abc52d8 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/getsentry/sentry-go v0.7.0 github.com/go-chi/chi v4.1.2+incompatible + github.com/go-chi/cors v1.1.1 github.com/golang/protobuf v1.4.2 // indirect github.com/google/go-cmp v0.5.2 // indirect github.com/joho/godotenv v1.3.0 diff --git a/go.sum b/go.sum index fb93c0a..280f7a3 100644 --- a/go.sum +++ b/go.sum @@ -87,6 +87,8 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw= +github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= diff --git a/httpserver/handlers.go b/httpserver/handlers.go new file mode 100644 index 0000000..0814135 --- /dev/null +++ b/httpserver/handlers.go @@ -0,0 +1,15 @@ +package httpserver + +import ( + "net/http" + "time" +) + +func (s *server) handleNow() http.HandlerFunc { + type response struct { + Now time.Time `json:"now"` + } + return func(w http.ResponseWriter, r *http.Request) { + s.respondJSON(w, r, &response{Now: time.Now()}, 200) + } +} diff --git a/httpserver/main.go b/httpserver/main.go index a3df137..b26de23 100644 --- a/httpserver/main.go +++ b/httpserver/main.go @@ -50,7 +50,6 @@ func NewServer(options ...func(s *server)) *server { for _, opt := range options { opt(n) } - return n } diff --git a/httpserver/middlewares.go b/httpserver/middlewares.go index 70267a6..cf6024a 100644 --- a/httpserver/middlewares.go +++ b/httpserver/middlewares.go @@ -7,9 +7,9 @@ import ( basicauth "github.com/99designs/basicauth-go" "github.com/go-chi/chi/middleware" + "github.com/go-chi/cors" metrics "github.com/slok/go-http-metrics/metrics/prometheus" ghmm "github.com/slok/go-http-metrics/middleware" - "github.com/slok/go-http-metrics/middleware/std" "github.com/spf13/viper" ) @@ -75,10 +75,25 @@ func (s *server) LoggingMiddleware() func(http.Handler) http.Handler { } } +func (s *server) CORSMiddleware() func(http.Handler) http.Handler { + return cors.Handler(cors.Options{ + // CHANGEME! these are defaults, change them to suit your needs or + // read from environment/viper. + // AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts + AllowedOrigins: []string{"*"}, + // AllowOriginFunc: func(r *http.Request, origin string) bool { return true }, + AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, + ExposedHeaders: []string{"Link"}, + AllowCredentials: false, + MaxAge: 300, // Maximum value not ignored by any of major browsers + }) +} + func (s *server) AuthMiddleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // FIXME you'll want to change this to do stuff. + // CHANGEME you'll want to change this to do stuff. s.log.Info().Msg("AUTH: before request") next.ServeHTTP(w, r) }) diff --git a/httpserver/routes.go b/httpserver/routes.go index 7ab9ba6..19f2682 100644 --- a/httpserver/routes.go +++ b/httpserver/routes.go @@ -30,6 +30,10 @@ func (s *server) routes() { s.router.Use(s.MetricsMiddleware()) } + // set up CORS headers. you'll probably want to configure that + // in middlewares.go. + s.router.Use(s.CORSMiddleware()) + // CHANGEME to suit your needs, or pull from config. // timeout for request context; your handlers must finish within // this window: @@ -55,6 +59,12 @@ func (s *server) routes() { s.router.Get("/", s.handleIndex()) + s.router.Get("/", s.handleIndex()) + + s.router.Route("/api/v1", func(r chi.Router) { + r.Get("/now", s.handleNow()) + }) + // if you want to use a general purpose middleware (http.Handler // wrapper) on a specific HandleFunc route, you need to take the // .ServeHTTP of the http.Handler to get its HandleFunc, viz: