90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package httpdelivery
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/Kichiyaki/appmode"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/pkg/errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/graphql/querycomplexity"
|
|
|
|
"github.com/99designs/gqlgen/graphql/handler"
|
|
"github.com/99designs/gqlgen/graphql/handler/extension"
|
|
"github.com/99designs/gqlgen/graphql/handler/lru"
|
|
"github.com/99designs/gqlgen/graphql/handler/transport"
|
|
"github.com/99designs/gqlgen/graphql/playground"
|
|
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/graphql/directive"
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/graphql/generated"
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/graphql/resolvers"
|
|
)
|
|
|
|
const (
|
|
playgroundTTL = time.Hour / time.Second
|
|
graphqlEndpoint = "/graphql"
|
|
playgroundEndpoint = "/"
|
|
)
|
|
|
|
type Config struct {
|
|
Resolver *resolvers.Resolver
|
|
Directive *directive.Directive
|
|
}
|
|
|
|
func Attach(r chi.Router, cfg Config) error {
|
|
if cfg.Resolver == nil {
|
|
return errors.New("cfg.Resolver is required")
|
|
}
|
|
gqlHandler := graphqlHandler(prepareConfig(cfg.Resolver, cfg.Directive))
|
|
r.Get(graphqlEndpoint, gqlHandler)
|
|
r.Post(graphqlEndpoint, gqlHandler)
|
|
if appmode.Equals(appmode.DevelopmentMode) {
|
|
r.Get(playgroundEndpoint, playgroundHandler())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func graphqlHandler(cfg generated.Config) http.HandlerFunc {
|
|
srv := handler.New(generated.NewExecutableSchema(cfg))
|
|
|
|
srv.AddTransport(transport.GET{})
|
|
srv.AddTransport(transport.POST{})
|
|
srv.AddTransport(transport.MultipartForm{
|
|
MaxUploadSize: 32 << 18,
|
|
MaxMemory: 32 << 18,
|
|
})
|
|
srv.Use(extension.AutomaticPersistedQuery{
|
|
Cache: lru.New(100),
|
|
})
|
|
srv.SetQueryCache(lru.New(100))
|
|
srv.Use(querycomplexity.GetComplexityLimitExtension())
|
|
if appmode.Equals(appmode.DevelopmentMode) {
|
|
srv.Use(extension.Introspection{})
|
|
}
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
r.Header.Add("Cache-Control", "no-store, must-revalidate")
|
|
srv.ServeHTTP(w, r)
|
|
}
|
|
}
|
|
|
|
func playgroundHandler() http.HandlerFunc {
|
|
h := playground.Handler("Playground", graphqlEndpoint)
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
r.Header.Add("Cache-Control", fmt.Sprintf(`public, max-age=%d`, playgroundTTL))
|
|
h.ServeHTTP(w, r)
|
|
}
|
|
}
|
|
|
|
func prepareConfig(r *resolvers.Resolver, d *directive.Directive) generated.Config {
|
|
cfg := generated.Config{
|
|
Resolvers: r,
|
|
Complexity: querycomplexity.GetComplexityRoot(),
|
|
}
|
|
cfg.Directives.Authenticated = d.Authenticated
|
|
cfg.Directives.HasRole = d.HasRole
|
|
return cfg
|
|
}
|