Open wangmir opened 1 year ago
Hi @wangmir ,
This library only supports JSON content type. I have no idea if there is another supported graphql client in Go. However, you can use a plain HTTP client to write a simple request with mime/multipart
body.
Hi @hgiasac ,
Yes, but I just wanted to utilize the rich functionalities of this library.
When I check the code, I think we can still reuse some of the code, and maybe similar to the requestModifier
approach, we can make a custom byte buffer on this.
from below code,
// Request the common method that send graphql request
func (c *Client) request(ctx context.Context, query string, variables map[string]interface{}, options ...Option) ([]byte, *http.Response, io.Reader, Errors) {
in := GraphQLRequestPayload{
Query: query,
Variables: variables,
}
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(in)
if err != nil {
return nil, nil, nil, Errors{newError(ErrGraphQLEncode, err)}
}
reqReader := bytes.NewReader(buf.Bytes())
request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.url, reqReader)
if err != nil {
e := newError(ErrRequestError, fmt.Errorf("problem constructing request: %w", err))
if c.debug {
e = e.withRequest(request, reqReader)
}
return nil, nil, nil, Errors{e}
}
request.Header.Add("Content-Type", "application/json")
if c.requestModifier != nil {
c.requestModifier(request)
}
resp, err := c.httpClient.Do(request)
// ... rest of the code
}
We can make the below part as the default byte buffer writer. The input will be GraphQLRequestPayload
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(in)
if err != nil {
return nil, nil, nil, Errors{newError(ErrGraphQLEncode, err)}
}
And, when I want to make multi-part request, then we can just customize this byte buffer to do something like,
var b bytes.Buffer
w := multipart.NewWriter(&b)
// Add the query and variables fields
fw, err := w.CreateFormField("operations")
if err != nil {
fmt.Println("Error creating form field: ", err)
return
}
_, _ = fw.Write([]byte(`{"query":"mutation ($input: PostInput!) { createPost(input: $input) { id, title, fileUrl } }","variables":{"input":{"title":"My Title","file":null}}}`))
fw, err = w.CreateFormField("map")
if err != nil {
fmt.Println("Error creating form field: ", err)
return
}
_, _ = fw.Write([]byte(`{"0":["variables.input.file"]}`))
// Add the file field
file, err := os.Open(tmpFile.Name())
if err != nil {
fmt.Println("Error opening file: ", err)
return
}
defer file.Close()
fw, err = w.CreateFormFile("0", tmpFile.Name())
if err != nil {
fmt.Println("Error creating form file: ", err)
return
}
_, _ = io.Copy(fw, file)
// Don't forget to close the multipart writer.
w.Close()
How about that?
If u agree, then I can make a PR to fix this.
I get your idea. Feel free to make a PR. However, you need to make sure the change doesn't break the current interface and API design.
Same as title.
When I wanna send file with
Upload
scalar, (https://gqlgen.com/reference/file-upload/) How can we send this request?Is there any features to support multi-part request on this library? or should I manually add that.