From 927f98c66ba3ed47ca3314c8b59acea06bdf8a66 Mon Sep 17 00:00:00 2001 From: Julien Neuhart Date: Fri, 6 Dec 2019 11:22:11 +0100 Subject: [PATCH] adding custom headers for remoteURL --- internal/app/xhttp/handler.go | 12 ++++--- internal/app/xhttp/pkg/context/context.go | 4 +-- internal/app/xhttp/pkg/resource/header.go | 8 ++--- .../app/xhttp/pkg/resource/header_test.go | 32 +++++++----------- internal/app/xhttp/pkg/resource/resource.go | 19 ++++++----- internal/pkg/printer/chrome.go | 33 +++++++++++++++++++ test/multipartform.go | 2 +- 7 files changed, 71 insertions(+), 39 deletions(-) diff --git a/internal/app/xhttp/handler.go b/internal/app/xhttp/handler.go index 234c0903..03266198 100644 --- a/internal/app/xhttp/handler.go +++ b/internal/app/xhttp/handler.go @@ -124,6 +124,7 @@ func urlHandler(c echo.Context) error { if err != nil { return err } + opts.CustomHeaders = resource.RemoteURLCustomHeaders(r) if !r.HasArg(resource.RemoteURLArgKey) { return xerror.Invalid( op, @@ -323,11 +324,14 @@ func convertAsync(ctx context.Context, p printer.Printer, filename, fpath string } req.Header.Set(echo.HeaderContentType, "application/pdf") // set custom headers (if any). - for key, value := range resource.WebhookURLCustomHeaders(r) { - for _, v := range value { - req.Header.Add(key, v) - logger.DebugfOp(op, "added '%s' to custom header '%s'", v, key) + customHeaders := resource.WebhookURLCustomHeaders(r) + if len(customHeaders) > 0 { + for key, value := range customHeaders { + req.Header.Set(key, value) + logger.DebugfOp(op, "set '%s' to custom header '%s'", value, key) } + } else { + logger.DebugOp(op, "skipping custom headers as none have been provided...") } // send the result file. logger.DebugfOp( diff --git a/internal/app/xhttp/pkg/context/context.go b/internal/app/xhttp/pkg/context/context.go index 6a8122d1..41f430fb 100644 --- a/internal/app/xhttp/pkg/context/context.go +++ b/internal/app/xhttp/pkg/context/context.go @@ -79,8 +79,8 @@ func (ctx *Context) WithResource(directoryName string) error { return r, err } // retrieve custom headers from request. - for name, value := range ctx.Request().Header { - r.WithCustomHeader(name, value) + for key, value := range ctx.Request().Header { + r.WithCustomHeader(key, value[0]) } // retrieve form values from request. for _, key := range resource.ArgKeys() { diff --git a/internal/app/xhttp/pkg/resource/header.go b/internal/app/xhttp/pkg/resource/header.go index ac284643..9a9745d7 100644 --- a/internal/app/xhttp/pkg/resource/header.go +++ b/internal/app/xhttp/pkg/resource/header.go @@ -13,8 +13,8 @@ const ( WebhookURLCustomHeaderCanonicalBaseKey string = "Gotenberg-Webhookurl-" ) -func fetchCustomHeaders(r Resource, baseKey string) map[string][]string { - customHeaders := make(map[string][]string) +func fetchCustomHeaders(r Resource, baseKey string) map[string]string { + customHeaders := make(map[string]string) for key, value := range r.customHeaders { if strings.Contains(key, baseKey) { realKey := strings.Replace(key, baseKey, "", 1) @@ -26,12 +26,12 @@ func fetchCustomHeaders(r Resource, baseKey string) map[string][]string { // RemoteURLCustomHeaders is a helper for retrieving // the custom headers for the URL conversion. -func RemoteURLCustomHeaders(r Resource) map[string][]string { +func RemoteURLCustomHeaders(r Resource) map[string]string { return fetchCustomHeaders(r, RemoteURLCustomHeaderCanonicalBaseKey) } // WebhookURLCustomHeaders is a helper for retrieving // the custom headers for the webhook URL. -func WebhookURLCustomHeaders(r Resource) map[string][]string { +func WebhookURLCustomHeaders(r Resource) map[string]string { return fetchCustomHeaders(r, WebhookURLCustomHeaderCanonicalBaseKey) } diff --git a/internal/app/xhttp/pkg/resource/header_test.go b/internal/app/xhttp/pkg/resource/header_test.go index 07c71f0a..5f9856ee 100644 --- a/internal/app/xhttp/pkg/resource/header_test.go +++ b/internal/app/xhttp/pkg/resource/header_test.go @@ -18,17 +18,13 @@ func TestRemoteURLCustomHeaders(t *testing.T) { customHeaderValue := "bar" customHeaderCanonicalRealKey := "Foo" customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", RemoteURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) - r.WithCustomHeader(customHeaderCanonicalKey, []string{customHeaderValue}) - r.WithCustomHeader("Bar", []string{"Bar"}) - expected := map[string][]string{ - customHeaderCanonicalRealKey: []string{ - customHeaderValue, - }, + r.WithCustomHeader(customHeaderCanonicalKey, customHeaderValue) + r.WithCustomHeader("Bar", "Bar") + expected := map[string]string{ + customHeaderCanonicalRealKey: customHeaderValue, } - notExpected := map[string][]string{ - customHeaderCanonicalKey: []string{ - customHeaderValue, - }, + notExpected := map[string]string{ + customHeaderCanonicalKey: customHeaderValue, } v := RemoteURLCustomHeaders(r) assert.Equal(t, expected, v) @@ -44,17 +40,13 @@ func TestWebhookURLCustomHeaders(t *testing.T) { customHeaderValue := "bar" customHeaderCanonicalRealKey := "Foo" customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", WebhookURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) - r.WithCustomHeader(customHeaderCanonicalKey, []string{customHeaderValue}) - r.WithCustomHeader("Bar", []string{"Bar"}) - expected := map[string][]string{ - customHeaderCanonicalRealKey: []string{ - customHeaderValue, - }, + r.WithCustomHeader(customHeaderCanonicalKey, customHeaderValue) + r.WithCustomHeader("Bar", "Bar") + expected := map[string]string{ + customHeaderCanonicalRealKey: customHeaderValue, } - notExpected := map[string][]string{ - customHeaderCanonicalKey: []string{ - customHeaderValue, - }, + notExpected := map[string]string{ + customHeaderCanonicalKey: customHeaderValue, } v := WebhookURLCustomHeaders(r) assert.Equal(t, expected, v) diff --git a/internal/app/xhttp/pkg/resource/resource.go b/internal/app/xhttp/pkg/resource/resource.go index 39d1229b..29d1241d 100644 --- a/internal/app/xhttp/pkg/resource/resource.go +++ b/internal/app/xhttp/pkg/resource/resource.go @@ -3,6 +3,7 @@ package resource import ( "fmt" "io" + "net/http" "os" "path/filepath" "strings" @@ -25,7 +26,7 @@ const TemporaryDirectory string = "tmp" type Resource struct { logger xlog.Logger dirPath string - customHeaders map[string][]string + customHeaders map[string]string args map[ArgKey]string files map[string]file } @@ -53,7 +54,7 @@ func New(logger xlog.Logger, directoryName string) (Resource, error) { return Resource{ logger: logger, dirPath: dirPath, - customHeaders: make(map[string][]string), + customHeaders: make(map[string]string), args: make(map[ArgKey]string), files: make(map[string]file), }, nil @@ -76,15 +77,17 @@ func (r Resource) Close() error { // WithCustomHeader add a new custom header to the Resource. // Given key should be in canonical format. -func (r *Resource) WithCustomHeader(key string, value []string) { +func (r *Resource) WithCustomHeader(key string, value string) { const op string = "resource.Resource.WithCustomHeader" - if strings.Contains(key, RemoteURLCustomHeaderCanonicalBaseKey) || - strings.Contains(key, WebhookURLCustomHeaderCanonicalBaseKey) { - r.customHeaders[key] = value - r.logger.DebugfOp(op, "added '%s' with value '%s' to resource custom headers", key, value) + // should already be in canonical format. + canonicalKey := http.CanonicalHeaderKey(key) + if strings.Contains(canonicalKey, RemoteURLCustomHeaderCanonicalBaseKey) || + strings.Contains(canonicalKey, WebhookURLCustomHeaderCanonicalBaseKey) { + r.customHeaders[canonicalKey] = value + r.logger.DebugfOp(op, "added '%s' with value '%s' to resource custom headers", canonicalKey, value) return } - r.logger.DebugfOp(op, "skipping '%s' as it is not a custom header...", key) + r.logger.DebugfOp(op, "skipping '%s' as it is not a custom header...", canonicalKey) } // WithArg add a new argument to the Resource. diff --git a/internal/pkg/printer/chrome.go b/internal/pkg/printer/chrome.go index 8f1cc473..dce45a05 100644 --- a/internal/pkg/printer/chrome.go +++ b/internal/pkg/printer/chrome.go @@ -2,6 +2,7 @@ package printer import ( "context" + "encoding/json" "fmt" "io/ioutil" "strings" @@ -42,6 +43,7 @@ type ChromePrinterOptions struct { MarginRight float64 Landscape bool RpccBufferSize int64 + CustomHeaders map[string]string } // DefaultChromePrinterOptions returns the default @@ -61,6 +63,7 @@ func DefaultChromePrinterOptions(config conf.Config) ChromePrinterOptions { MarginRight: 1.0, Landscape: false, RpccBufferSize: config.DefaultGoogleChromeRpccBufferSize(), + CustomHeaders: make(map[string]string), } } @@ -144,6 +147,10 @@ func (p chromePrinter) Print(destination string) error { if err := p.enableEvents(ctx, targetClient); err != nil { return err } + // add custom headers (if any). + if err := p.setCustomHeaders(ctx, targetClient); err != nil { + return err + } // listen for all events. if err := p.listenEvents(ctx, targetClient); err != nil { return err @@ -247,6 +254,32 @@ func (p chromePrinter) enableEvents(ctx context.Context, client *cdp.Client) err return nil } +func (p chromePrinter) setCustomHeaders(ctx context.Context, client *cdp.Client) error { + const op string = "printer.chromePrinter.setCustomHeaders" + resolver := func() error { + if len(p.opts.CustomHeaders) == 0 { + p.logger.DebugOp(op, "skipping custom headers as none have been provided...") + return nil + } + customHeaders := make(map[string]string) + // useless but for the logs. + for key, value := range p.opts.CustomHeaders { + customHeaders[key] = value + p.logger.DebugfOp(op, "set '%s' to custom header '%s'", value, key) + } + b, err := json.Marshal(customHeaders) + if err != nil { + return err + } + // should always be called after client.Network.Enable. + return client.Network.SetExtraHTTPHeaders(ctx, network.NewSetExtraHTTPHeadersArgs(b)) + } + if err := resolver(); err != nil { + return xerror.New(op, err) + } + return nil +} + func (p chromePrinter) listenEvents(ctx context.Context, client *cdp.Client) error { const op string = "printer.chromePrinter.listenEvents" resolver := func() error { diff --git a/test/multipartform.go b/test/multipartform.go index 0bc73508..00e8e552 100644 --- a/test/multipartform.go +++ b/test/multipartform.go @@ -79,7 +79,7 @@ func multipartForm( require.Nil(t, err) } if kind == "url" { - err := writer.WriteField("remoteURL", "http://google.com") + err := writer.WriteField("remoteURL", "https://google.com") require.Nil(t, err) } for k, v := range formValues {