diff options
| author | Shulhan <ms@kilabit.info> | 2024-02-15 02:28:30 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2024-02-15 02:28:30 +0700 |
| commit | 6ef5bdfc203a5d5e3648c59edd158db51ee289c0 (patch) | |
| tree | 3352b1740abe5a5c6c6177e5c2b6fc758564bd7b | |
| parent | 48e6dced72d470d78c8f58f4dc703528eb092c3c (diff) | |
| download | pakakeh.go-6ef5bdfc203a5d5e3648c59edd158db51ee289c0.tar.xz | |
lib/http: export function to generate "multipart/form-data"
The GenerateFormData generate the request body with boundary for
HTTP content-type "multipart/form-data" from map[string][]byte.
| -rw-r--r-- | lib/http/client.go | 24 | ||||
| -rw-r--r-- | lib/http/client_example_test.go | 47 | ||||
| -rw-r--r-- | lib/http/client_request.go | 2 |
3 files changed, 65 insertions, 8 deletions
diff --git a/lib/http/client.go b/lib/http/client.go index 05368092..cdfb1979 100644 --- a/lib/http/client.go +++ b/lib/http/client.go @@ -21,6 +21,7 @@ import ( "net/http" "net/url" "path" + "sort" "strings" "time" @@ -243,7 +244,7 @@ func (client *Client) GenerateHttpRequest( case RequestTypeMultipartForm: paramsAsMultipart, ok := params.(map[string][]byte) if ok { - contentType, strBody, err = generateFormData(paramsAsMultipart) + contentType, strBody, err = GenerateFormData(paramsAsMultipart) if err != nil { return nil, fmt.Errorf("%s: %w", logp, err) } @@ -336,7 +337,7 @@ func (client *Client) PostFormData( ) ( res *http.Response, resBody []byte, err error, ) { - contentType, strBody, err := generateFormData(params) + contentType, strBody, err := GenerateFormData(params) if err != nil { return nil, nil, fmt.Errorf("http: PostFormData: %w", err) } @@ -393,7 +394,7 @@ func (client *Client) PutFormData(rpath string, hdr http.Header, params map[stri body *strings.Reader ) - contentType, strBody, err = generateFormData(params) + contentType, strBody, err = GenerateFormData(params) if err != nil { return nil, nil, fmt.Errorf(`http: PutFormData: %w`, err) } @@ -540,21 +541,30 @@ func (client *Client) uncompress(res *http.Response, body []byte) ( return out, err } -// generateFormData generate multipart/form-data body from params. -func generateFormData(params map[string][]byte) (contentType, body string, err error) { +// GenerateFormData generate multipart/form-data body from params. +func GenerateFormData(params map[string][]byte) (contentType, body string, err error) { var ( sb = new(strings.Builder) w = multipart.NewWriter(sb) + k string + listKey []string + ) + for k = range params { + listKey = append(listKey, k) + } + sort.Strings(listKey) + + var ( part io.Writer - k string v []byte ) - for k, v = range params { + for _, k = range listKey { part, err = w.CreateFormField(k) if err != nil { return "", "", err } + v = params[k] _, err = part.Write(v) if err != nil { return "", "", err diff --git a/lib/http/client_example_test.go b/lib/http/client_example_test.go new file mode 100644 index 00000000..2d7d3bdf --- /dev/null +++ b/lib/http/client_example_test.go @@ -0,0 +1,47 @@ +package http_test + +import ( + "crypto/rand" + "fmt" + "log" + "strings" + + libhttp "github.com/shuLhan/share/lib/http" + "github.com/shuLhan/share/lib/test/mock" +) + +func ExampleGenerateFormData() { + // Mock the random reader for predictable output. + // NOTE: do not do this on real code. + rand.Reader = mock.NewRandReader([]byte(`randomseed`)) + + var data = map[string][]byte{ + `name`: []byte(`test.txt`), + `size`: []byte(`42`), + } + + var ( + contentType string + body string + err error + ) + contentType, body, err = libhttp.GenerateFormData(data) + if err != nil { + log.Fatal(err) + } + fmt.Println(`contentType:`, contentType) + fmt.Println(`body:`) + fmt.Println(strings.ReplaceAll(body, "\r\n", "\n")) + // Output: + // contentType: multipart/form-data; boundary=72616e646f6d7365656472616e646f6d7365656472616e646f6d73656564 + // body: + // --72616e646f6d7365656472616e646f6d7365656472616e646f6d73656564 + // Content-Disposition: form-data; name="name" + // + // test.txt + // --72616e646f6d7365656472616e646f6d7365656472616e646f6d73656564 + // Content-Disposition: form-data; name="size" + // + // 42 + // --72616e646f6d7365656472616e646f6d7365656472616e646f6d73656564-- +} diff --git a/lib/http/client_request.go b/lib/http/client_request.go index 03496e45..635c88da 100644 --- a/lib/http/client_request.go +++ b/lib/http/client_request.go @@ -113,7 +113,7 @@ func (creq *ClientRequest) toHTTPRequest(client *Client) (httpReq *http.Request, case RequestTypeMultipartForm: paramsAsMultipart, ok := creq.Params.(map[string][]byte) if ok { - contentType, strBody, err = generateFormData(paramsAsMultipart) + contentType, strBody, err = GenerateFormData(paramsAsMultipart) if err != nil { return nil, fmt.Errorf("%s: %w", logp, err) } |
