Skip to content

Commit

Permalink
Update GQLgen test client to work with multipart form data
Browse files Browse the repository at this point in the history
Update the GQLgen to support multipart form data, like those present
within the fileupload examples.

- Add missing space between "unsupported encoding " and failing
  content-type header error
  • Loading branch information
Sonna committed Dec 12, 2020
1 parent 862762c commit 101842f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
10 changes: 7 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"regexp"

"github.com/mitchellh/mapstructure"
)
Expand Down Expand Up @@ -119,15 +120,18 @@ func (p *Client) newRequest(query string, options ...Option) (*http.Request, err
option(bd)
}

switch bd.HTTP.Header.Get("Content-Type") {
case "application/json":
contentType := bd.HTTP.Header.Get("Content-Type")
switch {
case regexp.MustCompile(`multipart/form-data; ?boundary=.*`).MatchString(contentType):
break
case "application/json" == contentType:
requestBody, err := json.Marshal(bd)
if err != nil {
return nil, fmt.Errorf("encode: %s", err.Error())
}
bd.HTTP.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
default:
panic("unsupported encoding" + bd.HTTP.Header.Get("Content-Type"))
panic("unsupported encoding " + bd.HTTP.Header.Get("Content-Type"))
}

return bd.HTTP, nil
Expand Down
41 changes: 41 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package client_test

import (
"bytes"
"encoding/json"
"io/ioutil"
"mime/multipart"
"net/http"
"net/textproto"
"testing"

"github.com/99designs/gqlgen/client"
Expand Down Expand Up @@ -39,6 +42,44 @@ func TestClient(t *testing.T) {
require.Equal(t, "bob", resp.Name)
}

func TestClientMultipartFormData(t *testing.T) {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
bodyBytes, err := ioutil.ReadAll(r.Body)
require.NoError(t, err)
require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="operations"`)
require.Contains(t, string(bodyBytes), `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`)
require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="map"`)
require.Contains(t, string(bodyBytes), `{"0":["variables.file"]}`)
require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="0"; filename="example.txt"`)
require.Contains(t, string(bodyBytes), `Content-Type: text/plain`)
require.Contains(t, string(bodyBytes), `Hello World`)

w.Write([]byte(`{}`))
})

c := client.New(h)

var resp struct{}
c.MustPost("{ id }", &resp,
func(bd *client.Request) {
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
bodyWriter.WriteField("operations", `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`)
bodyWriter.WriteField("map", `{"0":["variables.file"]}`)

h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", `form-data; name="0"; filename="example.txt"`)
h.Set("Content-Type", "text/plain")
ff, _ := bodyWriter.CreatePart(h)
ff.Write([]byte("Hello World"))
bodyWriter.Close()

bd.HTTP.Body = ioutil.NopCloser(bodyBuf)
bd.HTTP.Header.Set("Content-Type", bodyWriter.FormDataContentType())
},
)
}

func TestAddHeader(t *testing.T) {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "ASDF", r.Header.Get("Test-Key"))
Expand Down

0 comments on commit 101842f

Please sign in to comment.