2020-06-02 15:45:21 +00:00
|
|
|
package httpdelivery
|
|
|
|
|
|
|
|
import (
|
2021-03-20 17:13:45 +00:00
|
|
|
"context"
|
2020-06-02 15:45:21 +00:00
|
|
|
"fmt"
|
2021-03-20 17:13:45 +00:00
|
|
|
"github.com/99designs/gqlgen/graphql"
|
2021-04-22 17:34:47 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-05-05 17:58:45 +00:00
|
|
|
"time"
|
|
|
|
|
2021-03-22 15:38:00 +00:00
|
|
|
"github.com/tribalwarshelp/api/graphql/querycomplexity"
|
2021-03-20 17:13:45 +00:00
|
|
|
"github.com/tribalwarshelp/api/middleware"
|
2020-06-02 15:45:21 +00:00
|
|
|
|
|
|
|
"github.com/99designs/gqlgen/graphql/handler"
|
2020-06-03 15:21:28 +00:00
|
|
|
"github.com/99designs/gqlgen/graphql/handler/extension"
|
|
|
|
"github.com/99designs/gqlgen/graphql/handler/lru"
|
|
|
|
"github.com/99designs/gqlgen/graphql/handler/transport"
|
2020-06-02 15:45:21 +00:00
|
|
|
"github.com/99designs/gqlgen/graphql/playground"
|
|
|
|
"github.com/gin-gonic/gin"
|
2021-05-05 17:58:45 +00:00
|
|
|
|
2020-06-02 15:45:21 +00:00
|
|
|
"github.com/tribalwarshelp/api/graphql/generated"
|
|
|
|
"github.com/tribalwarshelp/api/graphql/resolvers"
|
|
|
|
)
|
|
|
|
|
2020-06-12 16:26:48 +00:00
|
|
|
const (
|
2021-04-22 17:34:47 +00:00
|
|
|
endpointGraphQL = "/graphql"
|
2021-03-20 17:13:45 +00:00
|
|
|
endpointPlayground = "/"
|
|
|
|
playgroundTTL = time.Hour / time.Second
|
2020-06-12 16:26:48 +00:00
|
|
|
)
|
|
|
|
|
2020-06-03 15:21:28 +00:00
|
|
|
type Config struct {
|
|
|
|
RouterGroup *gin.RouterGroup
|
|
|
|
Resolver *resolvers.Resolver
|
|
|
|
}
|
|
|
|
|
|
|
|
func Attach(cfg Config) error {
|
|
|
|
if cfg.Resolver == nil {
|
2021-04-22 17:34:47 +00:00
|
|
|
return errors.New("Graphql resolver cannot be nil")
|
2020-06-02 15:45:21 +00:00
|
|
|
}
|
2021-03-20 17:13:45 +00:00
|
|
|
gqlHandler := graphqlHandler(prepareConfig(cfg.Resolver))
|
2021-04-22 17:34:47 +00:00
|
|
|
cfg.RouterGroup.GET(endpointGraphQL, gqlHandler)
|
|
|
|
cfg.RouterGroup.POST(endpointGraphQL, gqlHandler)
|
2021-03-20 17:13:45 +00:00
|
|
|
cfg.RouterGroup.GET(endpointPlayground, playgroundHandler())
|
2020-06-02 15:45:21 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-06-18 15:15:31 +00:00
|
|
|
// Defining the GraphQL handler
|
2021-03-20 17:13:45 +00:00
|
|
|
func graphqlHandler(cfg generated.Config) gin.HandlerFunc {
|
2020-06-03 15:21:28 +00:00
|
|
|
srv := handler.New(generated.NewExecutableSchema(cfg))
|
|
|
|
|
|
|
|
srv.AddTransport(transport.GET{})
|
|
|
|
srv.AddTransport(transport.POST{})
|
|
|
|
srv.Use(extension.Introspection{})
|
|
|
|
srv.Use(extension.AutomaticPersistedQuery{
|
|
|
|
Cache: lru.New(100),
|
|
|
|
})
|
2021-03-24 04:31:53 +00:00
|
|
|
srv.SetQueryCache(lru.New(100))
|
2021-03-20 17:13:45 +00:00
|
|
|
srv.Use(&extension.ComplexityLimit{
|
|
|
|
Func: func(ctx context.Context, rc *graphql.OperationContext) int {
|
|
|
|
if middleware.CanExceedLimit(ctx) {
|
2021-03-21 12:46:05 +00:00
|
|
|
return 500000000
|
2021-03-20 17:13:45 +00:00
|
|
|
}
|
2021-04-22 17:49:50 +00:00
|
|
|
return 15000
|
2021-03-20 17:13:45 +00:00
|
|
|
},
|
|
|
|
})
|
2020-06-02 15:45:21 +00:00
|
|
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
c.Header("Cache-Control", "no-store, must-revalidate")
|
2020-06-03 15:21:28 +00:00
|
|
|
srv.ServeHTTP(c.Writer, c.Request)
|
2020-06-02 15:45:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Defining the Playground handler
|
|
|
|
func playgroundHandler() gin.HandlerFunc {
|
2021-04-22 17:34:47 +00:00
|
|
|
h := playground.Handler("Playground", endpointGraphQL)
|
2020-06-02 15:45:21 +00:00
|
|
|
|
|
|
|
return func(c *gin.Context) {
|
2021-01-08 22:14:13 +00:00
|
|
|
c.Header("Cache-Control", fmt.Sprintf(`public, max-age=%d`, playgroundTTL))
|
2020-06-02 15:45:21 +00:00
|
|
|
h.ServeHTTP(c.Writer, c.Request)
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 17:13:45 +00:00
|
|
|
|
|
|
|
func prepareConfig(r *resolvers.Resolver) generated.Config {
|
|
|
|
return generated.Config{
|
|
|
|
Resolvers: r,
|
2021-03-22 15:38:00 +00:00
|
|
|
Complexity: querycomplexity.GetComplexityRoot(),
|
2021-03-20 17:13:45 +00:00
|
|
|
}
|
|
|
|
}
|