Hi everyone , i’m new to Dgraph and Go and i’m trying to write a Go API that can handle HTTP requests containing dgraph queries and mutations.
So far, I managed to send a curl request containing a query and handle it to return the json result from my database but now i’m trying to pass to my API a mutation in a http request and pass it back to my dgraph database.
I tried to find examples but i couldn’t find anything like what i’m trying to do…
I’d really apreciate if someone could take a look and help me find out what i’m doing wrong
Here is my code :
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/dgraph-io/dgo/v2"
"github.com/dgraph-io/dgo/v2/protos/api"
"github.com/golang/gddo/httputil/header"
"google.golang.org/grpc"
)
// query example : curl -H "Content-Type: application/json" localhost:2000/api/query -XPOST -d '{"query": "{\n testQuery(func: has(name)) {\n uid\n name\n firstname \n }\n }"}'
//mutation example : curl -H "Content-Type: application/json" localhost:2000/api/mutate -XPOST -d '{ "set":[{"name":"Test2"}]}'
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the homepage")
fmt.Println("Endpoint touched: homePage")
}
func apiPage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Endpoint api ...")
fmt.Println("Endpoint touched : /api ")
}
//dgraph client creation
func getDgraphClient() *dgo.Dgraph {
conn, err := grpc.Dial("127.0.0.1:9080", grpc.WithInsecure())
if err != nil {
log.Fatal("While trying to dial gRPC")
}
dc := api.NewDgraphClient(conn)
dg := dgo.NewDgraphClient(dc)
return dg
}
type queryStruct struct {
Query string
}
type mutateStruct struct {
Mutation []byte
}
func returnMutationJSONInR(w http.ResponseWriter, r *http.Request) []byte {
if r.Header.Get("Content-Type") != "" {
value, _ := header.ParseValueAndParams(r.Header, "Content-Type")
if value != "application/json" {
msg := "Content-Type header is not application/json"
http.Error(w, msg, http.StatusUnsupportedMediaType)
}
}
var m mutateStruct
err := json.NewDecoder(r.Body).Decode(&m)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
fmt.Println("Mutation received ... Treating following Mutation : \n")
fmt.Println(m.Mutation)
return m.Mutation
}
//returnJSONInR Returns query in a string
func returnJSONInR(w http.ResponseWriter, r *http.Request) string {
if r.Header.Get("Content-Type") != "" {
value, _ := header.ParseValueAndParams(r.Header, "Content-Type")
if value != "application/json" {
msg := "Content-Type header is not application/json"
http.Error(w, msg, http.StatusUnsupportedMediaType)
}
}
var q queryStruct
err := json.NewDecoder(r.Body).Decode(&q)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
fmt.Println("Query received ... Treating following Query : \n")
fmt.Println(q.Query)
return q.Query
}
//returnQueryResult returns database result
func returnQueryResult(w http.ResponseWriter, r *http.Request) {
fmt.Println("Enpoint touché: returnQueryResult \n")
query := returnJSONInR(w, r)
ctx := context.Background()
dg := getDgraphClient()
txn := dg.NewTxn()
defer txn.Discard(ctx)
res, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
fmt.Printf("\n*Query result %s \n", res.Json)
fmt.Fprintf(w, "dgraph response : %s \n", res)
}
func mutateDatabase(w http.ResponseWriter, r *http.Request) {
fmt.Println("Enpoint touched: mutateDatabase \n")
mutation := returnMutationJSONInR(w, r)
println(mutation)
dg := getDgraphClient()
//op := &api.Operation{}
ctx := context.Background()
if err := dg.Alter(ctx, op); err != nil {
log.Fatal(err)
}
pb, err := json.Marshal(mutation)
if err != nil {
log.Fatal(err)
}
println(pb)
mu := &api.Mutation{
//CommitNow: true,
}
mu.SetJson = pb
println(mu)
txn := dg.NewTxn()
defer txn.Discard(ctx)
req := &api.Request{CommitNow: true, Mutations: []*api.Mutation{mu}}
res, err := txn.Do(ctx, req)
if err != nil {
log.Fatal(err)
}
/*res,err := txn.Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}*/
fmt.Println(res)
}
//Http Handler
func handleRequests() {
mux := http.NewServeMux()
mux.HandleFunc("/", homePage)
//ajout des routes
mux.HandleFunc("/api", apiPage)
mux.HandleFunc("/api/mutate", mutateDatabase)
mux.HandleFunc("/api/query", returnQueryResult)
log.Fatal(http.ListenAndServe(":2000", mux))
}
func main() {
fmt.Println("Testing API on :2000 ... \n")
handleRequests()
}
I realize I may have done a lot of things wrong but i’ts my first time developing an api , if anybody got any examples or tutorial to help me i’d be very thankful!
Peace !