Skip to content

Commit f14b587

Browse files
committed
chore: disable introspection options
1 parent 2259e40 commit f14b587

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

serve/graph/setup.go

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import (
44
"context"
55
embed "embed"
66
"io/fs"
7+
"time"
78

89
"github.com/99designs/gqlgen/graphql"
910
"github.com/99designs/gqlgen/graphql/handler"
11+
"github.com/99designs/gqlgen/graphql/handler/extension"
12+
"github.com/99designs/gqlgen/graphql/handler/lru"
1013
"github.com/99designs/gqlgen/graphql/handler/transport"
1114
"github.com/go-chi/chi/v5"
15+
"github.com/vektah/gqlparser/v2/ast"
16+
"github.com/vektah/gqlparser/v2/gqlerror"
1217

1318
"github.com/gnolang/tx-indexer/events"
1419
"github.com/gnolang/tx-indexer/serve/graph/model"
@@ -19,7 +24,7 @@ import (
1924
var examples embed.FS
2025

2126
func Setup(s storage.Storage, manager *events.Manager, m *chi.Mux) *chi.Mux {
22-
srv := handler.NewDefaultServer(NewExecutableSchema(
27+
srv := newGraphQueryServer(NewExecutableSchema(
2328
Config{
2429
Resolvers: NewResolver(s, manager),
2530
Directives: DirectiveRoot{
@@ -37,6 +42,25 @@ func Setup(s storage.Storage, manager *events.Manager, m *chi.Mux) *chi.Mux {
3742

3843
srv.AddTransport(&transport.Websocket{})
3944

45+
srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
46+
oc := graphql.GetOperationContext(ctx)
47+
if oc.Operation != nil && oc.Operation.Operation == ast.Query {
48+
if includesIntrospection(oc.Operation.SelectionSet) {
49+
return func(ctx context.Context) *graphql.Response {
50+
return &graphql.Response{
51+
Errors: gqlerror.List{
52+
&gqlerror.Error{
53+
Message: "GraphQL introspection is disabled",
54+
},
55+
},
56+
}
57+
}
58+
}
59+
}
60+
61+
return next(ctx)
62+
})
63+
4064
es, err := examplesToSlice()
4165
if err != nil {
4266
panic(err)
@@ -68,3 +92,48 @@ func examplesToSlice() ([]string, error) {
6892

6993
return out, err
7094
}
95+
96+
func newGraphQueryServer(es graphql.ExecutableSchema) *handler.Server {
97+
srv := handler.New(es)
98+
99+
srv.AddTransport(transport.Websocket{
100+
KeepAlivePingInterval: 10 * time.Second,
101+
})
102+
srv.AddTransport(transport.Options{})
103+
srv.AddTransport(transport.GET{})
104+
srv.AddTransport(transport.POST{})
105+
srv.AddTransport(transport.MultipartForm{})
106+
107+
srv.SetQueryCache(lru.New[*ast.QueryDocument](1000))
108+
109+
srv.Use(extension.AutomaticPersistedQuery{
110+
Cache: lru.New[string](100),
111+
})
112+
113+
return srv
114+
}
115+
116+
func includesIntrospection(selectionSet ast.SelectionSet) bool {
117+
for _, selection := range selectionSet {
118+
switch sel := selection.(type) {
119+
case *ast.Field:
120+
if sel.Name == "__schema" || sel.Name == "__typename" {
121+
return true
122+
}
123+
124+
if includesIntrospection(sel.SelectionSet) {
125+
return true
126+
}
127+
case *ast.FragmentSpread:
128+
if sel.Definition != nil && includesIntrospection(sel.Definition.SelectionSet) {
129+
return true
130+
}
131+
case *ast.InlineFragment:
132+
if includesIntrospection(sel.SelectionSet) {
133+
return true
134+
}
135+
}
136+
}
137+
138+
return false
139+
}

0 commit comments

Comments
 (0)