Skip to content

Commit

Permalink
Merge pull request 99designs#1074 from yudppp/feature/add_contenttype…
Browse files Browse the repository at this point in the history
…_for_upload

Add ContentType to graphql.Upload
  • Loading branch information
vektah authored Mar 4, 2020
2 parents 3154479 + 64560ec commit 74ffe75
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 108 deletions.
7 changes: 4 additions & 3 deletions docs/content/reference/scalars.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ Maps a `Upload` GraphQL scalar to a `graphql.Upload` struct, defined as follows:

```go
type Upload struct {
File io.Reader
Filename string
Size int64
File io.Reader
Filename string
Size int64
ContentType string
}
```

Expand Down
117 changes: 67 additions & 50 deletions example/fileupload/fileupload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"mime/multipart"
"net/http"
"net/http/httptest"
"net/textproto"
"testing"

"github.com/99designs/gqlgen/example/fileupload/model"
Expand All @@ -32,21 +33,23 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, string(content), "test")

return &model.File{
ID: 1,
Name: file.Filename,
Content: string(content),
ID: 1,
Name: file.Filename,
Content: string(content),
ContentType: file.ContentType,
}, nil
}
srv := httptest.NewServer(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})))
defer srv.Close()

operations := `{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id, name, content } }", "variables": { "file": null } }`
operations := `{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id, name, content, contentType } }", "variables": { "file": null } }`
mapData := `{ "0": ["variables.file"] }`
files := []file{
{
mapKey: "0",
name: "a.txt",
content: "test",
mapKey: "0",
name: "a.txt",
content: "test",
contentType: "text/plain",
},
}
req := createUploadRequest(t, srv.URL, operations, mapData, files)
Expand All @@ -57,7 +60,7 @@ func TestFileUpload(t *testing.T) {
responseBody, err := ioutil.ReadAll(resp.Body)
require.Nil(t, err)
responseString := string(responseBody)
require.Equal(t, `{"data":{"singleUpload":{"id":1,"name":"a.txt","content":"test"}}}`, responseString)
require.Equal(t, `{"data":{"singleUpload":{"id":1,"name":"a.txt","content":"test","contentType":"text/plain"}}}`, responseString)
err = resp.Body.Close()
require.Nil(t, err)
})
Expand All @@ -73,21 +76,23 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, string(content), "test")

return &model.File{
ID: 1,
Name: req.File.Filename,
Content: string(content),
ID: 1,
Name: req.File.Filename,
Content: string(content),
ContentType: req.File.ContentType,
}, nil
}
srv := httptest.NewServer(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})))
defer srv.Close()

operations := `{ "query": "mutation ($req: UploadFile!) { singleUploadWithPayload(req: $req) { id, name, content } }", "variables": { "req": {"file": null, "id": 1 } } }`
operations := `{ "query": "mutation ($req: UploadFile!) { singleUploadWithPayload(req: $req) { id, name, content, contentType } }", "variables": { "req": {"file": null, "id": 1 } } }`
mapData := `{ "0": ["variables.req.file"] }`
files := []file{
{
mapKey: "0",
name: "a.txt",
content: "test",
mapKey: "0",
name: "a.txt",
content: "test",
contentType: "text/plain",
},
}
req := createUploadRequest(t, srv.URL, operations, mapData, files)
Expand All @@ -97,7 +102,7 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode)
responseBody, err := ioutil.ReadAll(resp.Body)
require.Nil(t, err)
require.Equal(t, `{"data":{"singleUploadWithPayload":{"id":1,"name":"a.txt","content":"test"}}}`, string(responseBody))
require.Equal(t, `{"data":{"singleUploadWithPayload":{"id":1,"name":"a.txt","content":"test","contentType":"text/plain"}}}`, string(responseBody))
err = resp.Body.Close()
require.Nil(t, err)
})
Expand All @@ -114,9 +119,10 @@ func TestFileUpload(t *testing.T) {
require.Nil(t, err)
contents = append(contents, string(content))
resp = append(resp, &model.File{
ID: i + 1,
Name: files[i].Filename,
Content: string(content),
ID: i + 1,
Name: files[i].Filename,
Content: string(content),
ContentType: files[i].ContentType,
})
}
require.ElementsMatch(t, []string{"test1", "test2"}, contents)
Expand All @@ -125,18 +131,20 @@ func TestFileUpload(t *testing.T) {
srv := httptest.NewServer(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})))
defer srv.Close()

operations := `{ "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id, name, content } }", "variables": { "files": [null, null] } }`
operations := `{ "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id, name, content, contentType } }", "variables": { "files": [null, null] } }`
mapData := `{ "0": ["variables.files.0"], "1": ["variables.files.1"] }`
files := []file{
{
mapKey: "0",
name: "a.txt",
content: "test1",
mapKey: "0",
name: "a.txt",
content: "test1",
contentType: "text/plain",
},
{
mapKey: "1",
name: "b.txt",
content: "test2",
mapKey: "1",
name: "b.txt",
content: "test2",
contentType: "text/plain",
},
}
req := createUploadRequest(t, srv.URL, operations, mapData, files)
Expand All @@ -146,7 +154,7 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode)
responseBody, err := ioutil.ReadAll(resp.Body)
require.Nil(t, err)
require.Equal(t, `{"data":{"multipleUpload":[{"id":1,"name":"a.txt","content":"test1"},{"id":2,"name":"b.txt","content":"test2"}]}}`, string(responseBody))
require.Equal(t, `{"data":{"multipleUpload":[{"id":1,"name":"a.txt","content":"test1","contentType":"text/plain"},{"id":2,"name":"b.txt","content":"test2","contentType":"text/plain"}]}}`, string(responseBody))
err = resp.Body.Close()
require.Nil(t, err)
})
Expand All @@ -166,9 +174,10 @@ func TestFileUpload(t *testing.T) {
ids = append(ids, req[i].ID)
contents = append(contents, string(content))
resp = append(resp, &model.File{
ID: i + 1,
Name: req[i].File.Filename,
Content: string(content),
ID: i + 1,
Name: req[i].File.Filename,
Content: string(content),
ContentType: req[i].File.ContentType,
})
}
require.ElementsMatch(t, []int{1, 2}, ids)
Expand All @@ -178,18 +187,20 @@ func TestFileUpload(t *testing.T) {
srv := httptest.NewServer(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})))
defer srv.Close()

operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id, name, content } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }`
operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id, name, content, contentType } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }`
mapData := `{ "0": ["variables.req.0.file"], "1": ["variables.req.1.file"] }`
files := []file{
{
mapKey: "0",
name: "a.txt",
content: "test1",
mapKey: "0",
name: "a.txt",
content: "test1",
contentType: "text/plain",
},
{
mapKey: "1",
name: "b.txt",
content: "test2",
mapKey: "1",
name: "b.txt",
content: "test2",
contentType: "text/plain",
},
}
req := createUploadRequest(t, srv.URL, operations, mapData, files)
Expand All @@ -199,7 +210,7 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode)
responseBody, err := ioutil.ReadAll(resp.Body)
require.Nil(t, err)
require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1"},{"id":2,"name":"b.txt","content":"test2"}]}}`, string(responseBody))
require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1","contentType":"text/plain"},{"id":2,"name":"b.txt","content":"test2","contentType":"text/plain"}]}}`, string(responseBody))
err = resp.Body.Close()
require.Nil(t, err)
})
Expand Down Expand Up @@ -230,23 +241,25 @@ func TestFileUpload(t *testing.T) {
}
contents = append(contents, string(got))
resp = append(resp, &model.File{
ID: i + 1,
Name: req[i].File.Filename,
Content: string(got),
ID: i + 1,
Name: req[i].File.Filename,
Content: string(got),
ContentType: req[i].File.ContentType,
})
}
require.ElementsMatch(t, []int{1, 2}, ids)
require.ElementsMatch(t, []string{"test1", "test1"}, contents)
return resp, nil
}

operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id, name, content } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }`
operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id, name, content, contentType } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }`
mapData := `{ "0": ["variables.req.0.file", "variables.req.1.file"] }`
files := []file{
{
mapKey: "0",
name: "a.txt",
content: "test1",
mapKey: "0",
name: "a.txt",
content: "test1",
contentType: "text/plain",
},
}

Expand All @@ -262,7 +275,7 @@ func TestFileUpload(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode)
responseBody, err := ioutil.ReadAll(resp.Body)
require.Nil(t, err)
require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1"},{"id":2,"name":"a.txt","content":"test1"}]}}`, string(responseBody))
require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1","contentType":"text/plain"},{"id":2,"name":"a.txt","content":"test1","contentType":"text/plain"}]}}`, string(responseBody))
err = resp.Body.Close()
require.Nil(t, err)
}
Expand All @@ -278,9 +291,10 @@ func TestFileUpload(t *testing.T) {
}

type file struct {
mapKey string
name string
content string
mapKey string
name string
content string
contentType string
}

func createUploadRequest(t *testing.T, url, operations, mapData string, files []file) *http.Request {
Expand All @@ -294,7 +308,10 @@ func createUploadRequest(t *testing.T, url, operations, mapData string, files []
require.NoError(t, err)

for i := range files {
ff, err := bodyWriter.CreateFormFile(files[i].mapKey, files[i].name)
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, files[i].mapKey, files[i].name))
h.Set("Content-Type", files[i].contentType)
ff, err := bodyWriter.CreatePart(h)
require.NoError(t, err)
_, err = ff.Write([]byte(files[i].content))
require.NoError(t, err)
Expand Down
54 changes: 51 additions & 3 deletions example/fileupload/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions example/fileupload/model/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions example/fileupload/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type File {
id: Int!
name: String!
content: String!
contentType: String!
}

"The `UploadFile` type, represents the request for uploading a file with certain payload."
Expand Down
Loading

0 comments on commit 74ffe75

Please sign in to comment.