mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 16:34:02 +01:00
* Bump golang.org/x/text from 0.3.7 to 0.3.8 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * Update go dependencies * Update x/net --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
186 lines
4.7 KiB
Go
186 lines
4.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/99designs/gqlgen/graphql"
|
|
"github.com/99designs/gqlgen/graphql/executor"
|
|
"github.com/99designs/gqlgen/graphql/handler/extension"
|
|
"github.com/99designs/gqlgen/graphql/handler/lru"
|
|
"github.com/99designs/gqlgen/graphql/handler/transport"
|
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
|
)
|
|
|
|
type (
|
|
Server struct {
|
|
transports []graphql.Transport
|
|
exec *executor.Executor
|
|
}
|
|
)
|
|
|
|
func New(es graphql.ExecutableSchema) *Server {
|
|
return &Server{
|
|
exec: executor.New(es),
|
|
}
|
|
}
|
|
|
|
func NewDefaultServer(es graphql.ExecutableSchema) *Server {
|
|
srv := New(es)
|
|
|
|
srv.AddTransport(transport.Websocket{
|
|
KeepAlivePingInterval: 10 * time.Second,
|
|
})
|
|
srv.AddTransport(transport.Options{})
|
|
srv.AddTransport(transport.GET{})
|
|
srv.AddTransport(transport.POST{})
|
|
srv.AddTransport(transport.MultipartForm{})
|
|
|
|
srv.SetQueryCache(lru.New(1000))
|
|
|
|
srv.Use(extension.Introspection{})
|
|
srv.Use(extension.AutomaticPersistedQuery{
|
|
Cache: lru.New(100),
|
|
})
|
|
|
|
return srv
|
|
}
|
|
|
|
func (s *Server) AddTransport(transport graphql.Transport) {
|
|
s.transports = append(s.transports, transport)
|
|
}
|
|
|
|
func (s *Server) SetErrorPresenter(f graphql.ErrorPresenterFunc) {
|
|
s.exec.SetErrorPresenter(f)
|
|
}
|
|
|
|
func (s *Server) SetRecoverFunc(f graphql.RecoverFunc) {
|
|
s.exec.SetRecoverFunc(f)
|
|
}
|
|
|
|
func (s *Server) SetQueryCache(cache graphql.Cache) {
|
|
s.exec.SetQueryCache(cache)
|
|
}
|
|
|
|
func (s *Server) Use(extension graphql.HandlerExtension) {
|
|
s.exec.Use(extension)
|
|
}
|
|
|
|
// AroundFields is a convenience method for creating an extension that only implements field middleware
|
|
func (s *Server) AroundFields(f graphql.FieldMiddleware) {
|
|
s.exec.AroundFields(f)
|
|
}
|
|
|
|
// AroundRootFields is a convenience method for creating an extension that only implements field middleware
|
|
func (s *Server) AroundRootFields(f graphql.RootFieldMiddleware) {
|
|
s.exec.AroundRootFields(f)
|
|
}
|
|
|
|
// AroundOperations is a convenience method for creating an extension that only implements operation middleware
|
|
func (s *Server) AroundOperations(f graphql.OperationMiddleware) {
|
|
s.exec.AroundOperations(f)
|
|
}
|
|
|
|
// AroundResponses is a convenience method for creating an extension that only implements response middleware
|
|
func (s *Server) AroundResponses(f graphql.ResponseMiddleware) {
|
|
s.exec.AroundResponses(f)
|
|
}
|
|
|
|
func (s *Server) getTransport(r *http.Request) graphql.Transport {
|
|
for _, t := range s.transports {
|
|
if t.Supports(r) {
|
|
return t
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
err := s.exec.PresentRecoveredError(r.Context(), err)
|
|
gqlErr, _ := err.(*gqlerror.Error)
|
|
resp := &graphql.Response{Errors: []*gqlerror.Error{gqlErr}}
|
|
b, _ := json.Marshal(resp)
|
|
w.WriteHeader(http.StatusUnprocessableEntity)
|
|
w.Write(b)
|
|
}
|
|
}()
|
|
|
|
r = r.WithContext(graphql.StartOperationTrace(r.Context()))
|
|
|
|
transport := s.getTransport(r)
|
|
if transport == nil {
|
|
sendErrorf(w, http.StatusBadRequest, "transport not supported")
|
|
return
|
|
}
|
|
|
|
transport.Do(w, r, s.exec)
|
|
}
|
|
|
|
func sendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) {
|
|
w.WriteHeader(code)
|
|
b, err := json.Marshal(&graphql.Response{Errors: errors})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Write(b)
|
|
}
|
|
|
|
func sendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) {
|
|
sendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)})
|
|
}
|
|
|
|
type OperationFunc func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler
|
|
|
|
func (r OperationFunc) ExtensionName() string {
|
|
return "InlineOperationFunc"
|
|
}
|
|
|
|
func (r OperationFunc) Validate(schema graphql.ExecutableSchema) error {
|
|
if r == nil {
|
|
return fmt.Errorf("OperationFunc can not be nil")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r OperationFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
|
|
return r(ctx, next)
|
|
}
|
|
|
|
type ResponseFunc func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response
|
|
|
|
func (r ResponseFunc) ExtensionName() string {
|
|
return "InlineResponseFunc"
|
|
}
|
|
|
|
func (r ResponseFunc) Validate(schema graphql.ExecutableSchema) error {
|
|
if r == nil {
|
|
return fmt.Errorf("ResponseFunc can not be nil")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r ResponseFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
|
|
return r(ctx, next)
|
|
}
|
|
|
|
type FieldFunc func(ctx context.Context, next graphql.Resolver) (res interface{}, err error)
|
|
|
|
func (f FieldFunc) ExtensionName() string {
|
|
return "InlineFieldFunc"
|
|
}
|
|
|
|
func (f FieldFunc) Validate(schema graphql.ExecutableSchema) error {
|
|
if f == nil {
|
|
return fmt.Errorf("FieldFunc can not be nil")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f FieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
|
|
return f(ctx, next)
|
|
}
|