[前言]
GraphQL系列文章
本篇內容將提供快速的指引,使用Golang Gin Framework來建置GraphQL的API Server。
[使用Golang Gin Framework來建置GraphQL的API Server]
GraphQL API Server主體上來說是參考下列文章的方式來建置:
第 1 天 - API 服務器(Go,GraphQL) - 第 1 部分
第 2 天 - API 服務器(Go,GraphQL) - 第 2 部分
Golang Gin Server網路上已經有很多資源,我們假設已經有的前提下,如何來建置GraphQL的API Server。首先,先安裝所需的模組:
#在個人自己的Gin Server 的 project 內
$ go get github.com/99designs/gqlgen
$ go get github.com/99designs/gqlgen
$ go get github.com/gin-gonic/gin
我們需要準備下列檔案:
$ tree -L 1
.
├── gqlgen.yml
├── internal
├── scripts
......
gqlgen.yml 的內容如下:
# go-gql-server gqlgen.yml file
# Refer to https://gqlgen.com/config/
# for detailed .gqlgen.yml documentation.
schema:
- internal/gql/schemas/schema.graphql
# Let gqlgen know where to put the generated server
exec:
filename: internal/gql/generated/generated.go
package: gql
# Let gqlgen know where to put the generated models (if any)
model:
filename: internal/gql/models/generated/generated.go
package: models
# Let gqlgen know where to put the generated resolvers
resolver:
filename: internal/gql/resolvers/generated/generated.go
type: Resolver
package: resolvers
autobind: []
scripts/gqlgen.sh 的內容如下:
#!/bin/bash
printf "\nRegenerating gqlgen files\n"
rm -f internal/gql/generated/generated.go \
internal/gql/models/generated/generated.go \
internal/gql/resolvers/generated/generated.go
time gqlgen $1
cp internal/gql/generated/generated.go internal/gql
mv internal/gql/generated.go internal/gql/main.go
cp internal/gql/models/generated/generated.go internal/gql/models
mv internal/gql/models/generated.go internal/gql/models/users.go
cp internal/gql/resolvers/generated/generated.go internal/gql/resolvers
mv internal/gql/resolvers/generated.go internal/gql/resolvers/main.go
printf "\nDone.\n\n"
透過執行 scripts/gqlgen.sh, 會generate codes (包含 generated、models、resolvers、schemas),並放在internal資料夾內,其檔案樹狀結構如下:
$ tree -L 3
.
├── gql
│ ├── generated
│ │ └── generated.go
│ ├── main.go
│ ├── models
│ │ ├── generated
│ │ └── users.go
│ ├── resolvers
│ │ ├── generated
│ │ └── main.go
│ └── schemas
│ └── schema.graphql
└── handlers
└── gql.go
備註:
在GraphQL api server using golang Gin framework 有提到可以用下列方式產生初步的GraphQL骨架,所以不一定要用上述的方式
$ go run github.com/99designs/gqlgen init
我們需要實作相關檔案:
internal/handlers/gql.go
package handlers
import (
"microsegmentation/internal/gql"
"microsegmentation/internal/gql/resolvers"
"github.com/99designs/gqlgen/handler"
"github.com/gin-gonic/gin"
)
// GraphqlHandler defines the GQLGen GraphQL server handler
func GraphqlHandler() gin.HandlerFunc {
// NewExecutableSchema and Config are in the generated.go file
c := gql.Config{
Resolvers: &resolvers.Resolver{},
}
h := handler.GraphQL(gql.NewExecutableSchema(c))
return func(c *gin.Context) {
h.ServeHTTP(c.Writer, c.Request)
}
}
// PlaygroundHandler Defines the Playground handler to expose our playground
func PlaygroundHandler(path string) gin.HandlerFunc {
h := handler.Playground("Go GraphQL Server", path)
return func(c *gin.Context) {
h.ServeHTTP(c.Writer, c.Request)
}
}
internal/resolvers/main.go
package resolvers
import (
"context"
// remeber to change the import path
gql "microsegmentation/internal/gql"
models "microsegmentation/internal/gql/models"
)
// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.
type Resolver struct{}
func (r *Resolver) Mutation() gql.MutationResolver {
return &mutationResolver{r}
}
func (r *Resolver) Query() gql.QueryResolver {
return &queryResolver{r}
}
type mutationResolver struct{ *Resolver }
func (r *mutationResolver) CreateUser(ctx context.Context, input models.UserInput) (*models.User, error) {
panic("not implemented")
}
func (r *mutationResolver) UpdateUser(ctx context.Context, input models.UserInput) (*models.User, error) {
panic("not implemented")
}
func (r *mutationResolver) DeleteUser(ctx context.Context, userID string) (bool, error) {
panic("not implemented")
}
type queryResolver struct{ *Resolver }
func (r *queryResolver) Users(ctx context.Context, userID *string) ([]*models.User, error) {
// this is for test purpose
var tempID = "ec17af15-e354-440c-a09f-69715fc8b595"
var tempEmail = "your@email.com"
var tempUserID = "UserID-1"
records := []*models.User{
&models.User{
ID: &tempID,
Email: &tempEmail,
UserID: &tempUserID,
},
}
return records, nil
}
完成後,就可以在自己的Gin Server上加入GraphQL相關的API Routes
//GraphQL
// Playground handler
r.GET("/heartbeat", handlers.Heartbeat())
r.GET("/gql", handlers.PlaygroundHandler("/gql"))
r.POST("/gql", handlers.GraphqlHandler())
Schema
- Schema is the way to provide structure of the object or resource. Based on the schema we can query or mutate the data/resource on the GraphqL server.
Queries
- Queries are used to retrieve the data from the GraphQL server.
Mutations
- Mutations are used to update/modify the resource on the server.
Resolvers
- Resolvers are used to create the data structure that matches with the provided resource schema.
在這篇文章: 使用 GraphQL 滿足現代業務需求
- GraphQL 架構
- GraphQL 的特徵:
- 可描述性的:使用GraphQL,你獲取的都是你想要的數據,很少也不會少;
- 請求的對象,請求的對象的一個簡單的對象:GraphQL自然遵循間的關係,我們可以通過簡單的對象請求,我們獲取到一個我們相關的對象,通過簡單的對象,可以獲取一個和她創建的所有文章,然後可以獲取文章的所有評論;
- 強類型的:使用GraphQL的類型系統,我們可以描述被服務器查詢的可能的數據,確保從服務器獲取到的數據和我們查詢的一致;
- 不做限制:現在並沒有綁定到某種語言的某種語言,實際上已經有了某種語言;
- 後台代碼:QL不存在特定的數據庫,甚至可以使用連接關聯的API。
- 好反省的:GraphQL服務器查詢架構的細節。
No comments:
Post a Comment