Closed csterritt closed 5 years ago
We don't use gqlgen with Lamda internally, so not sure what's required to get it working sorry. I would recommending asking in our gitter channel to see if anyone has tried this before.
@mathewbyrne Thanks, I may give that a try.
We're doing this with heavily trafficked services - we've implemented just like any other http handler, we use the proxy adapters from the aws labs to use golang http handlers.
code is something akin to:
package main
import (
"context"
"github.com/aws/aws-lambda-go/lambdacontext"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-xray-sdk-go/xray"
"github.com/awslabs/aws-lambda-go-api-proxy/gorillamux"
"github.com/gorilla/mux"
)
func init() {
// start the mux router
r := mux.NewRouter()
api.Routes(r) // routes just accepts a mux router to bind routes to and that's where our gqlgen handlers live
// initialize the mux adapter so that we can use mux with lambda
muxAdapter = gorillamux.New(r)
}
// Handler is a wrapper around lambda and mux so that we can continue to use mux via lambda
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
res, err := muxAdapter.Proxy(req)
if err != nil {
log.Println(err)
}
return res, err
}
func main() {
lambda.Start(Handler)
}
Thanks @sdalezman . I'm going to mark this issue closed, we might consider including this in a documentation recipe in the future.
Thanks @sdalezman -- that works fine! Much appreciated.
Hey there, is there a repo for this showing a fully working example? @sdalezman
@rayhaanq unfortunately i don't have one that I can publicly share and am pretty strapped for time these days. You can use the mux router generated above to bind to a gqlgen handler like you would if you were using mux and you can do the same thing with the playground handler. Hope that helps!
Hey there, is there a repo for this showing a fully working example? @sdalezman
A year on but this hopefully is a more complete version for ref. It combines the generated server.go
file with @sdalezman solution
package main
import (
"context"
"log"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/gorillamux"
"github.com/gorilla/mux"
"<yourRepo>/graph"
"<yourRepo>/graph/generated"
)
var muxAdapter *gorillamux.GorillaMuxAdapter
func init() {
r := mux.NewRouter()
// From server.go
schema := generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})
server := handler.NewDefaultServer(schema)
r.Handle("/query", server)
r.Handle("/", playground.Handler("GraphQL playground", "/query"))
muxAdapter = gorillamux.New(r)
}
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
rsp, err := muxAdapter.Proxy(req)
if err != nil {
log.Println(err)
}
return rsp, err
}
func main() {
lambda.Start(Handler)
}
@ptimson I failed to make the code like the above working (I use serverless framework). The response from the server is always 404 page not found
.
What worked for me (no Playground though):
import (
"context"
"github.com/99designs/gqlgen/handler"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/handlerfunc"
"<repo>/server" // includes everything that corresponds to "generated" and "graph" in ptimson's comment
"log"
)
var apiGatewayAdapter *handlerfunc.HandlerFuncAdapter
func init() {
schema := server.NewExecutableSchema(server.Config{Resolvers: &server.Resolver{}})
gqlHandler := handler.GraphQL(schema)
apiGatewayAdapter = handlerfunc.New(gqlHandler)
}
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
rsp, err := apiGatewayAdapter.ProxyWithContext(ctx, req)
if err != nil {
log.Println(err)
}
return rsp, err
}
@leventov I was also getting a 404 with @ptimson solution but I managed to get it working by changing my serverless config -
from: events:
to: events:
Just in case someone else runs into same issue...
Hi all, Anyone use the gqlgen to generate ( types/model ) schema of AWS Appsync? I try to use it but got an error with Aws directive "failed to load schema: graph/schema.graphql:747: Undefined directive aws_subscribe.exit status 1"
Should I use the gqlgen for Aws or not? Thanks
For any other beginning at golang struggling to get this working, here's a more complete version of @ptimson's solution:
server.go
:
package main
import (
"context"
"log"
"net/http"
"os"
"strings"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/gorillamux"
"<yourRepo>/graph"
"<yourRepo>/graph/generated"
"github.com/gorilla/mux"
)
var muxRouter *mux.Router
func init() {
muxRouter = mux.NewRouter()
schema := generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})
server := handler.NewDefaultServer(schema)
muxRouter.Handle("/query", server)
muxRouter.Handle("/", playground.Handler("GraphQL playground", "/query"))
}
func lambdaHandler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
muxAdapter := gorillamux.New(muxRouter)
rsp, err := muxAdapter.Proxy(req)
if err != nil {
log.Println(err)
}
return rsp, err
}
func main() {
isRunningAtLambda := strings.Contains(os.Getenv("AWS_EXECUTION_ENV"), "AWS_Lambda_")
if isRunningAtLambda {
lambda.Start(lambdaHandler)
} else {
defaultPort := "7010"
port := os.Getenv("PORT")
if port == "" {
port = defaultPort
}
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, muxRouter))
}
}
serverless.yml
:
provider:
name: aws
runtime: go1.x
lambdaHashingVersion: 20201221
package:
patterns:
- "!./**"
- ./bin/**
functions:
graphql:
handler: bin/server
events:
- http: ANY /{proxy+}
- http: ANY /
Makefile
:
build:
env GOOS=linux go build -ldflags="-s -w" -o bin/server
clean:
rm -rf ./bin
deploy: clean build
sls deploy --verbose
For any other beginning at golang struggling to get this working, here's a more complete version of @ptimson's solution:
server.go
:package main import ( "context" "log" "net/http" "os" "strings" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" "github.com/awslabs/aws-lambda-go-api-proxy/gorillamux" "<yourRepo>/graph" "<yourRepo>/graph/generated" "github.com/gorilla/mux" ) var muxRouter *mux.Router func init() { muxRouter = mux.NewRouter() schema := generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}) server := handler.NewDefaultServer(schema) muxRouter.Handle("/query", server) muxRouter.Handle("/", playground.Handler("GraphQL playground", "/query")) } func lambdaHandler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { muxAdapter := gorillamux.New(muxRouter) rsp, err := muxAdapter.Proxy(req) if err != nil { log.Println(err) } return rsp, err } func main() { isRunningAtLambda := strings.Contains(os.Getenv("AWS_EXECUTION_ENV"), "AWS_Lambda_") if isRunningAtLambda { lambda.Start(lambdaHandler) } else { defaultPort := "7010" port := os.Getenv("PORT") if port == "" { port = defaultPort } log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":"+port, muxRouter)) } }
serverless.yml
:provider: name: aws runtime: go1.x lambdaHashingVersion: 20201221 package: patterns: - "!./**" - ./bin/** functions: graphql: handler: bin/server events: - http: ANY /{proxy+} - http: ANY /
Makefile
:build: env GOOS=linux go build -ldflags="-s -w" -o bin/server clean: rm -rf ./bin deploy: clean build sls deploy --verbose
Thanks for that!
i 'm going to implement also subscription for aws apigateway socket in this repo if someone need join let's give me a hand.
I am following this code snippet , but getting "Transport not supported" error
Any help would be appreciated
@mihir-mehta it is depend on graphql subscription client. If you are using graphql-ws
you need add this to header of AWS Apigateway websocket
return events.APIGatewayProxyResponse{Headers: map[string]string{
"Sec-WebSocket-Protocol": "graphql-transport-ws",
}, StatusCode: http.StatusOK, Body: body}, nil
see what i implemented here. https://github.com/thebaycity/aws-graphql/blob/master/lambda/subscription/main.go
Content-Type: application/json was missing from request headers.
Thank you
Hey -- trying a straight server approach with gqlgen works really well, thanks!
But I'd like to set it up as an AWS Lambda service, to replace a REST service I have set up already.
However, I can't figure out how to take a query/mutation and run it. This article shows how to do it using
graphql-go
, but that's a different API.Thanks!