GraphQL API Server with MongoDB
Introduction
Learning gqlgen to build full GraphQL servers with MongoDB. The following project is built to manage multiple devices in multiple rooms. This GraphQL API is designed to be secure and requires the user to login to manage devices. A React Frontend is being built to use this API.
The following Golang Project uses:
Instructions
Rename .env-example to .env and setup variables
# MongoDB server config
MONGODB_URL=mongodb://localhost/
MONGODB_DATABASE=gqlmanage
# Server Port
PORT=8000
CORS=http://localhost:8000
# JWT Token Settings
JWT_SECRET=my_jwt_secret
JWT_ISSUER=my_issuer
Need to insert first user to access API (TODO)
Run server
go run ./main.go
# OR
go run github.com/scorpionknifes/gqlmanage
Notes
Resolvers
Custom resolvers for devices and rooms are created to allow recursive and nested GraphQL calls.
Example of a recursive query.
{
rooms{
devices{
room{
devices{
...
}
}
}
}
}
Authentication
Login with username and password to get JWT Token to access other routes. JWT Token has an expire time of 7 days.
mutation login{
login(input:{
username: "username"
password: "password"
}){
authToken{
accessToken
}
}
}
Example result getting JWT token
{
"data": {
"login": {
"authToken": {
"accessToken": "JWT_TOKEN_HERE"
}
}
}
}
Use JWT token to authenticate. Add Authorization Bearer token in Http Header
{
"Authorization": "Bearer JWT_TOKEN_HERE"
}
Dataloader
Read Here for more info about dataloader in gqlgen.
Dataloader solves repeated queries. The dataloader is used in custom resolver for devices.
Example of repeated queries - room needs to be called multiple times for each device that exist
{
devices{
room{
...
}
}
}
Subscriptions (with Redis)
Read Subscription with Redis
Read Passing token using Subscription
Websocket subscription is secured with jwt by passing the token through "graphql-ws" header. A different jwt extract method is used.
Redis pub/sub for running multiple instances.
Example of using a jwt token using Apollo Client in ReactJS
const subscriptionClient = new SubscriptionClient(
"ws://localhost:8000/query",
{
reconnect: true,
},
null,
[ "graphql-ws", 'JWT TOKEN' ])
const wsLink = new WebSocketLink(subscriptionClient);