-
Notifications
You must be signed in to change notification settings - Fork 718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom data for multipart request #129
Changes from 3 commits
162926e
72cb41a
d25c26b
3707524
a7f86e7
e078baa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,19 +300,20 @@ func (c *Client) SetAuthToken(token string) *Client { | |
// R method creates a request instance, its used for Get, Post, Put, Delete, Patch, Head and Options. | ||
func (c *Client) R() *Request { | ||
r := &Request{ | ||
URL: "", | ||
Method: "", | ||
QueryParam: url.Values{}, | ||
FormData: url.Values{}, | ||
Header: http.Header{}, | ||
Body: nil, | ||
Result: nil, | ||
Error: nil, | ||
RawRequest: nil, | ||
client: c, | ||
bodyBuf: nil, | ||
multipartFiles: []*File{}, | ||
pathParams: make(map[string]string), | ||
URL: "", | ||
Method: "", | ||
QueryParam: url.Values{}, | ||
FormData: url.Values{}, | ||
Header: http.Header{}, | ||
Body: nil, | ||
Result: nil, | ||
Error: nil, | ||
RawRequest: nil, | ||
client: c, | ||
bodyBuf: nil, | ||
multipartFiles: []*File{}, | ||
multipartCustomData: []*MultipartCustomData{}, | ||
pathParams: make(map[string]string), | ||
} | ||
|
||
return r | ||
|
@@ -865,3 +866,10 @@ type File struct { | |
func (f *File) String() string { | ||
return fmt.Sprintf("ParamName: %v; FileName: %v", f.ParamName, f.Name) | ||
} | ||
|
||
// MultipartCustomData represent custom data part for multipart request | ||
type MultipartCustomData struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Change |
||
Params map[string]string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Remove map and add two fields- Param string
FileName string |
||
ContentType string | ||
io.Reader | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,6 +300,16 @@ func handleMultipart(c *Client, r *Request) (err error) { | |
} | ||
} | ||
|
||
// adding custom data support | ||
if len(r.multipartCustomData) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Based review comments/recommendation. This section will change to // GitHub #130 adding multipart field support with content type
if len(r.multipartFields) > 0 {
for _, mf := range r.multipartFields {
if err = addMultipartFormField(w, mf); err != nil {
return
}
}
} |
||
for _, cd := range r.multipartCustomData { | ||
err = addCustomDataReader(w, cd) | ||
if err != nil { | ||
return | ||
} | ||
} | ||
} | ||
|
||
r.Header.Set(hdrContentTypeKey, w.FormDataContentType()) | ||
err = w.Close() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -279,6 +279,19 @@ func (r *Request) SetFileReader(param, fileName string, reader io.Reader) *Reque | |
return r | ||
} | ||
|
||
// SetMultipartData method is to set custom data using io.Reader for multipart upload. | ||
func (r *Request) SetMultipartData(params map[string]string, contentType string, reader io.Reader) *Request { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Change method name to Also update your method signature to func (r *Request) SetMultipartField(param, fileName, contentType string, reader io.Reader) *Request { |
||
r.isMultiPart = true | ||
|
||
r.multipartCustomData = append(r.multipartCustomData, &MultipartCustomData{ | ||
Params: params, | ||
ContentType: contentType, | ||
Reader: reader, | ||
}) | ||
|
||
return r | ||
} | ||
|
||
// SetContentLength method sets the HTTP header `Content-Length` value for current request. | ||
// By default go-resty won't set `Content-Length`. Also you have an option to enable for every | ||
// request. See `resty.SetContentLength` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ type Request struct { | |
isSaveResponse bool | ||
outputFile string | ||
multipartFiles []*File | ||
multipartCustomData []*MultipartCustomData | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Change attribute name to |
||
notParseResponse bool | ||
fallbackContentType string | ||
pathParams map[string]string | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ type Request struct { | |
isSaveResponse bool | ||
outputFile string | ||
multipartFiles []*File | ||
multipartCustomData []*MultipartCustomData | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Change attribute name to |
||
notParseResponse bool | ||
ctx context.Context | ||
fallbackContentType string | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,6 +107,24 @@ func escapeQuotes(s string) string { | |
return quoteEscaper.Replace(s) | ||
} | ||
|
||
func writeMultipartFormCustomData(w *multipart.Writer, params map[string]string, contentType string, r io.Reader) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 We are gonna improve it further.
func createMultipartHeader(param, fileName, contentType string) textproto.MIMEHeader {
hdr := make(textproto.MIMEHeader)
hdr.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(param), escapeQuotes(fileName)))
hdr.Set("Content-Type", contentType)
return hdr
}
func addMultipartFormField(w *multipart.Writer, mf *multipartField) error {
End result may look like- func addMultipartFormField(w *multipart.Writer, mf *multipartField) error {
partWriter, err := w.CreatePart(createMultipartHeader(mf.Param, mf.FileName, mf.ContentType))
if err != nil {
return err
}
_, err = io.Copy(partWriter, r)
return err
} Optional: Call |
||
h := make(textproto.MIMEHeader) | ||
var bufContDisp bytes.Buffer | ||
bufContDisp.WriteString("form-data;") | ||
for k, v := range params { | ||
bufContDisp.WriteString(fmt.Sprintf(` %s="%s";`, k, escapeQuotes(v))) | ||
} | ||
h.Set("Content-Disposition", bufContDisp.String()) | ||
h.Set("Content-Type", contentType) | ||
partWriter, err := w.CreatePart(h) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = io.Copy(partWriter, r) | ||
return err | ||
} | ||
|
||
func writeMultipartFormFile(w *multipart.Writer, fieldName, fileName string, r io.Reader) error { | ||
// Auto detect actual multipart content type | ||
cbuf := make([]byte, 512) | ||
|
@@ -148,6 +166,10 @@ func addFileReader(w *multipart.Writer, f *File) error { | |
return writeMultipartFormFile(w, f.ParamName, f.Name, f.Reader) | ||
} | ||
|
||
func addCustomDataReader(w *multipart.Writer, cd *MultipartCustomData) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Asker80 Please remove it, this method not needed after you take care of comments. |
||
return writeMultipartFormCustomData(w, cd.Params, cd.ContentType, cd.Reader) | ||
} | ||
|
||
func getPointer(v interface{}) interface{} { | ||
vv := valueOf(v) | ||
if vv.Kind() == reflect.Ptr { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Asker80 Based on review comments/recommendation, please make appropriate updates.