Skip to content

Commit

Permalink
set up server http to graphql
Browse files Browse the repository at this point in the history
  • Loading branch information
JamsMendez committed May 8, 2024
1 parent 596012e commit 7c3fe36
Show file tree
Hide file tree
Showing 5 changed files with 455 additions and 0 deletions.
26 changes: 26 additions & 0 deletions go-pagination/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package api

import (
"database/sql"
"log"
"net/http"

"go-pagination/repository"
"go-pagination/service"
)

func Start(testDB *sql.DB) error {
bookRepo := repository.NewBookRepository(testDB)
bookService := service.NewBookService(bookRepo)

handlerGQL, err := NewHandlerGQL(bookService)
if err != nil {
log.Fatalf("expected handler gql error nil, got %v", err)
}

mux := http.NewServeMux()
mux.HandleFunc("GET /api/graphql/", handlerGQL.HandlerQueries)
mux.HandleFunc("POST /api/graphql/", handlerGQL.HandlerMutations)

return http.ListenAndServe(":3000", mux)
}
50 changes: 50 additions & 0 deletions go-pagination/api/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package api

import (
"io"
"net/http"
"net/url"
"time"
)

type Client struct {
baseURL string
apiKey string
clientHTTP *http.Client
}

func NewClient(baseURL, apiKey string) *Client {
return &Client{
baseURL: baseURL,
apiKey: apiKey,
clientHTTP: &http.Client{
Timeout: 3 * time.Second,
},
}
}

func (c *Client) makeRequest(method, endpoint string, queries map[string]string, body io.Reader) (*http.Response, error) {
u, err := c.getURL(endpoint)
if err != nil {
return nil, err
}

req, err := http.NewRequest(method, u, body)
if err != nil {
return nil, err
}

q := req.URL.Query()

for key, value := range queries {
q.Add(key, value)
}

req.URL.RawQuery = q.Encode()

return c.clientHTTP.Do(req)
}

func (c *Client) getURL(p string) (string, error) {
return url.JoinPath(c.baseURL, p)
}
123 changes: 123 additions & 0 deletions go-pagination/api/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package api

import (
"bytes"
"encoding/json"
"io"
"log"
"net/http"

"go-pagination/domain"
"go-pagination/gql"

"github.com/graphql-go/graphql"
)

const (
KeyQuery = "query"
)

type BodyGQL struct {
Query string `json:"query"`
Variables map[string]any `json:"variables"`
Operation string `json:"operation"`
}

type HandlerGQL struct {
schema graphql.Schema
}

func NewHandlerGQL(bookService domain.BookService) (*HandlerGQL, error) {
schema, err := gql.NewSchema(bookService)
if err != nil {
return nil, err
}

h := &HandlerGQL{
schema: schema,
}

return h, nil
}

func (h *HandlerGQL) HandlerQueries(w http.ResponseWriter, r *http.Request) {
var variables map[string]any
var operation string
var rootObject map[string]any

q := r.URL.Query()
query := q.Get(KeyQuery)

params := graphql.Params{
Schema: h.schema,
RequestString: query,
// mutations
VariableValues: variables,
OperationName: operation,
Context: r.Context(),
RootObject: rootObject,
}

result := graphql.Do(params)

var buffer bytes.Buffer

err := json.NewEncoder(&buffer).Encode(result)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
_, err = w.Write(buffer.Bytes())
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}

func (h *HandlerGQL) HandlerMutations(w http.ResponseWriter, r *http.Request) {
var bGQL BodyGQL

err := json.NewDecoder(r.Body).Decode(&bGQL)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

defer func() {
err = r.Body.Close()
if err != nil {
log.Println("request body close error: ", err)
}
}()

var rootObject map[string]any

params := graphql.Params{
Schema: h.schema,
RequestString: bGQL.Query,
// mutations
VariableValues: bGQL.Variables,
OperationName: bGQL.Operation,
Context: r.Context(),
RootObject: rootObject,
}

result := graphql.Do(params)

var buffer bytes.Buffer

err = json.NewEncoder(&buffer).Encode(result)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
_, err = io.Copy(w, &buffer)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
150 changes: 150 additions & 0 deletions go-pagination/api/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package api

import (
"bytes"
"encoding/json"
"io"
"log"
"net/http"
"net/http/httptest"
"testing"

"go-pagination/repository"
"go-pagination/service"
)

func TestHandlerGQL(t *testing.T) {
bookRepo := repository.NewBookRepository(testDB)
bookService := service.NewBookService(bookRepo)

handlerGQL, err := NewHandlerGQL(bookService)
if err != nil {
t.Fatalf("expected handler gql error nil, got %v", err)
}

mux := http.NewServeMux()
mux.HandleFunc("GET /api/graphql/", handlerGQL.HandlerQueries)
mux.HandleFunc("POST /api/graphql/", handlerGQL.HandlerMutations)

server := httptest.NewServer(mux)

const endpoint = "/api/graphql/"

client := NewClient(server.URL, "")

t.Run("test query book pagination", func(t *testing.T) {
query := `
query {
books(page: 1, perPage: 5) {
nextPage
page
pages
items {
id
title
}
}
}
`

queries := map[string]string{
KeyQuery: query,
}

var resp *http.Response
resp, err = client.makeRequest(
http.MethodGet,
endpoint,
queries,
nil,
)
if err != nil {
t.Fatalf("expected http request error nil, got %v", err)
}

var buffer bytes.Buffer
_, err = io.Copy(&buffer, resp.Body)
if err != nil {
t.Fatalf("expected response read error nil, got %v", err)
}

defer func() {
err = resp.Body.Close()
if err != nil {
log.Println("response body close error: ", err)
}
}()

s := buffer.String()
if s != "" {
log.Fatalf("response body: %s", s)
}
})

t.Run("test mutation create book", func(t *testing.T) {
query := `
mutation CreateBook($book: InputBook!) {
createBook(input: $book) {
id
title
author
createdAt
updatedAt
}
}
`

book := map[string]any{
"title": "Go development",
"author": "JamsMendez",
}

variables := map[string]any{
"book": book,
}

bodyGQL := BodyGQL{
Query: query,
Variables: variables,
Operation: "CreateBook",
}

var body bytes.Buffer

err = json.NewEncoder(&body).Encode(bodyGQL)
if err != nil {
t.Fatalf("expected json encode error nil, got %v", err)
}

var queries map[string]string

var resp *http.Response
resp, err = client.makeRequest(
http.MethodPost,
endpoint,
queries,
&body,
)
if err != nil {
t.Fatalf("expected http request error nil, got %v", err)
}

var buffer bytes.Buffer
_, err = io.Copy(&buffer, resp.Body)
if err != nil {
t.Fatalf("expected response read error nil, got %v", err)
}

defer func() {
err = resp.Body.Close()
if err != nil {
log.Println("response body close error: ", err)
}
}()

s := buffer.String()
if s != "" {
log.Fatalf("response bodyGQL: %s", s)
}
})
}
Loading

0 comments on commit 7c3fe36

Please sign in to comment.