Skip to content
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

Merged
merged 6 commits into from
Feb 24, 2018

Conversation

Asker80
Copy link
Contributor

@Asker80 Asker80 commented Feb 20, 2018

Proposal for MultipartCustomData type, in case there's a need to inject custom data into multipart request. Since SetFile() and SetFileReader() functions are specifically file-oriented, I created a separate type to hold Content-Disposition header fields, Content-Type and the actual data.

@codecov
Copy link

codecov bot commented Feb 20, 2018

Codecov Report

Merging #129 into master will decrease coverage by 0.3%.
The diff coverage is 90%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #129      +/-   ##
==========================================
- Coverage   96.32%   96.02%   -0.31%     
==========================================
  Files          10       10              
  Lines        1034     1056      +22     
==========================================
+ Hits          996     1014      +18     
- Misses         21       23       +2     
- Partials       17       19       +2
Impacted Files Coverage Δ
request17.go 100% <ø> (ø) ⬆️
request16.go 100% <ø> (ø) ⬆️
client.go 97.71% <100%> (ø) ⬆️
request.go 100% <100%> (ø) ⬆️
middleware.go 91.32% <50%> (-0.77%) ⬇️
util.go 88.88% <84.61%> (-0.95%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cf9fbbb...e078baa. Read the comment docs.

@jeevatkm
Copy link
Member

@Asker80 Thanks for the PR, I will have a look and get back.

Copy link
Member

@jeevatkm jeevatkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Thank you for your PR and idea to improve resty.

  • Please have a look on comments and make updates.
  • Also please add test cases into request_test.go for this implementation.
  • Bring PR into Green tick status

client.go Outdated
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Change struct name to multipartField. Basically making as unexported struct.

client.go Outdated

// MultipartCustomData represent custom data part for multipart request
type MultipartCustomData struct {
Params map[string]string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Remove map and add two fields-

Param string
FileName string

request.go Outdated
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Change method name to SetMultipartField. Your idea, it supports multiple fields.

Also update your method signature to

func (r *Request) SetMultipartField(param, fileName, contentType string, reader io.Reader) *Request {

request16.go Outdated
@@ -43,6 +43,7 @@ type Request struct {
isSaveResponse bool
outputFile string
multipartFiles []*File
multipartCustomData []*MultipartCustomData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Change attribute name to multipartFields

request17.go Outdated
@@ -44,6 +44,7 @@ type Request struct {
isSaveResponse bool
outputFile string
multipartFiles []*File
multipartCustomData []*MultipartCustomData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 Change attribute name to multipartFields

util.go Outdated
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Asker80 We are gonna improve it further.

  1. Create a new unexported method called createMultipartHeader
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
}
  1. Change method signature to
func addMultipartFormField(w *multipart.Writer, mf *multipartField) error {
  1. Call method createMultipartHeader from method addMultipartFormField to get part header

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 createMultipartHeader from method writeMultipartFormFile. Otherwise I will take care after your PR merge.

util.go Outdated
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The 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.

middleware.go Outdated
@@ -300,6 +300,16 @@ func handleMultipart(c *Client, r *Request) (err error) {
}
}

// adding custom data support
if len(r.multipartCustomData) > 0 {
Copy link
Member

Choose a reason for hiding this comment

The 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
			}
		}
	}

client.go Outdated
client: c,
bodyBuf: nil,
multipartFiles: []*File{},
multipartCustomData: []*MultipartCustomData{},
Copy link
Member

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.

@jeevatkm
Copy link
Member

@Asker80 Thanks for the updates. I'm merging it.

@jeevatkm jeevatkm merged commit e008fe0 into go-resty:master Feb 24, 2018
@Asker80 Asker80 deleted the custom-data-for-multipart-request branch February 24, 2018 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants