1. Добавить в go проект Graphiql клиент
Graphiql — интерактивный работающий в браузере GraphQL клиент.
Для использования в go проекте нужно добавить html страничку с несколькими зависимостями.
Если нужно иметь последние версии, то поможет установить node и пакеты. Проект сильно разрастется. Есть вариант собрать HTML в один go файл и подтянуть при старте зависимости с cdn.
Мой вариант go-graphiql.
Для работы нужно добавить только:
http.HandleFunc("/cli", graphiql.ServeGraphiQL)
Результате имеем:
2. Посмотрим как работает API с точки зрения браузера
В браузере откроем консоль разработчика и добавим js код:
let q=`{getMessage}`
let v={}
let options = (query, variables={}) =>{
return {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
}
};
let o = options(q, v)
console.log(o)
fetch("http://localhost:9000/graphql",o)
.then(response=>response.json())
.then(console.log)
Результат выполнения:
В API есть ошибка. Нужно поменять текст сообщения.
q=`mutation {
setMessage(msg: "Hello Habr")
}
`
v={}
o = options(q, v)
console.log(o)
fetch("http://localhost:9000/graphql",o)
.then(response=>response.json())
.then(console.log)
Результат выполнения:
3. Посмотрим как это работает с точки зрения сервера.
Схему работ описывает объект:
schema, err := graphql.NewSchema(graphql.SchemaConfig{
Query: types.RootQuery,
Mutation: types.RootMutation,
})
Query
Получение данных
var RootQuery = graphql.NewObject(graphql.ObjectConfig{
Name: "RootQuery",
Fields: graphql.Fields{
"getMessage": &graphql.Field{
Type: graphql.String,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
msg := logic.GetMessage()
return msg, nil
},
},
},
})
Функция Resolve достает для нас данные. Данные могут быть из любого источника от Базы данных до микро контроллера
Mutation
Мутация данных
var RootMutation = graphql.NewObject(graphql.ObjectConfig{
Name: "RootMutation",
Fields: graphql.Fields{
"setMessage": &graphql.Field{
Type: graphql.String,
Args: graphql.FieldConfigArgument{
"msg": &graphql.ArgumentConfig{Type: graphql.NewNonNull(graphql.String)},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
msg := p.Args["msg"].(string)
logic.SetMessage(msg)
return msg, nil
},
},
},
})
Правка данных происходит тоже при помощи функции Resolve.
Resolve может так же создавать события включения света или регулировать температуру.
Интересный момент, что тип возвращаемых данных тоже может иметь graphql.Fields которые тоже будут иметь свои функции Resolve
4. Типизированные языки?
Есть некоторые ограничения(особенности) обмена данными.
В go у переменных есть значения по умолчанию
Int равен 0, String = ""
В graphql может быть ситуация когда переменная не установлена.
Поэтому для таких параметров используем ссылку на переменную
В продолжении,
Напишу как сделать graphql api к Реестру открытых данных.
Поскольку программисты это самы ленивые люди на планете. Будем делать API так чтобы делать что то поменьше.
TODO:
Api Starter Kit
schema
есть интересный проект который создает схему по тексту.
func main() {
s := `
schema {
query: Query
}
type Query {
hello: String!
}
`
schema := graphql.MustParseSchema(s, &query{})
http.Handle("/query", &relay.Handler{Schema: schema})
log.Fatal(http.ListenAndServe(":8080", nil))
}
github.com/graph-gophers/graphql-go
resolv
сделаю генератор для полей по структурам
query
не придумал как построить запросы генератором