From fc542c645ad172792e5c364c1831d006c2c72098 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 30 Oct 2024 11:41:48 +0200 Subject: [PATCH] Set content-length header when available When uploading raw data in the request data a file on disk, the file size is known and can be added as a content length header. Extended the executor to retrieve the file size and add it as a content-length header when available. --- executor/http_executor.go | 34 +++++++++++++++++++++++----------- test/execution_test.go | 4 ++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/executor/http_executor.go b/executor/http_executor.go index e032b3d..3e36ebb 100644 --- a/executor/http_executor.go +++ b/executor/http_executor.go @@ -175,7 +175,7 @@ func (e HttpExecutor) progressReader(text string, completedText string, reader i } func (e HttpExecutor) writeMultipartBody(bodyWriter *io.PipeWriter, parameters []ExecutionParameter, errorChan chan error) (string, int64) { - contentLength := e.calculateMultipartSize(parameters) + multipartSize := e.calculateMultipartSize(parameters) formWriter := multipart.NewWriter(bodyWriter) go func() { defer bodyWriter.Close() @@ -186,7 +186,7 @@ func (e HttpExecutor) writeMultipartBody(bodyWriter *io.PipeWriter, parameters [ return } }() - return formWriter.FormDataContentType(), contentLength + return formWriter.FormDataContentType(), multipartSize } func (e HttpExecutor) writeInputBody(bodyWriter *io.PipeWriter, input utils.Stream, errorChan chan error) { @@ -230,30 +230,39 @@ func (e HttpExecutor) writeJsonBody(bodyWriter *io.PipeWriter, parameters []Exec }() } -func (e HttpExecutor) writeBody(context ExecutionContext, errorChan chan error) (io.Reader, string, int64) { +func (e HttpExecutor) writeBody(context ExecutionContext, errorChan chan error) (io.Reader, string, int64, int64) { if context.Input != nil { reader, writer := io.Pipe() e.writeInputBody(writer, context.Input, errorChan) - return reader, context.ContentType, -1 + contentLength, _ := context.Input.Size() + return reader, context.ContentType, contentLength, contentLength } formParameters := context.Parameters.Form() if len(formParameters) > 0 { reader, writer := io.Pipe() - contentType, contentLength := e.writeMultipartBody(writer, formParameters, errorChan) - return reader, contentType, contentLength + contentType, multipartSize := e.writeMultipartBody(writer, formParameters, errorChan) + return reader, contentType, -1, multipartSize } bodyParameters := context.Parameters.Body() if len(bodyParameters) > 0 && context.ContentType == "application/x-www-form-urlencoded" { reader, writer := io.Pipe() e.writeUrlEncodedBody(writer, bodyParameters, errorChan) - return reader, context.ContentType, -1 + return reader, context.ContentType, -1, -1 } if len(bodyParameters) > 0 { reader, writer := io.Pipe() e.writeJsonBody(writer, bodyParameters, errorChan) - return reader, context.ContentType, -1 + return reader, context.ContentType, -1, -1 } - return bytes.NewReader([]byte{}), context.ContentType, -1 + return bytes.NewReader([]byte{}), context.ContentType, -1, -1 +} + +func (e HttpExecutor) contentLength(context ExecutionContext) int64 { + if context.Input == nil { + return -1 + } + contentLength, _ := context.Input.Size() + return contentLength } func (e HttpExecutor) send(client *http.Client, request *http.Request, errorChan chan error) (*http.Response, error) { @@ -306,9 +315,9 @@ func (e HttpExecutor) call(context ExecutionContext, writer output.OutputWriter, return err } requestError := make(chan error) - bodyReader, contentType, contentLength := e.writeBody(context, requestError) + bodyReader, contentType, contentLength, size := e.writeBody(context, requestError) uploadBar := utils.NewProgressBar(logger) - uploadReader := e.progressReader("uploading...", "completing ", bodyReader, contentLength, uploadBar) + uploadReader := e.progressReader("uploading...", "completing ", bodyReader, size, uploadBar) defer uploadBar.Remove() request, err := http.NewRequest(context.Method, uri.String(), uploadReader) if err != nil { @@ -317,6 +326,9 @@ func (e HttpExecutor) call(context ExecutionContext, writer output.OutputWriter, if contentType != "" { request.Header.Add("Content-Type", contentType) } + if contentLength != -1 { + request.ContentLength = contentLength + } e.addHeaders(request, context.Parameters.Header()) auth, err := e.executeAuthenticators(context.AuthConfig, context.IdentityUri, context.Debug, context.Insecure, request) if err != nil { diff --git a/test/execution_test.go b/test/execution_test.go index 9ea99ac..05122fc 100644 --- a/test/execution_test.go +++ b/test/execution_test.go @@ -1260,6 +1260,10 @@ paths: if contentType != "application/octet-stream" { t.Errorf("Content-Type is not application/octet-stream, got: %v", contentType) } + contentLength := result.RequestHeader["content-length"] + if contentLength != "11" { + t.Errorf("Content-Length is not 11, got: %v", contentLength) + } if result.RequestBody != "hello-world" { t.Errorf("Request body is not as expected, got: %v", result.RequestBody) }