adding custom headers for remoteURL

This commit is contained in:
Julien Neuhart
2019-12-06 11:22:11 +01:00
parent 782f6ac27e
commit 927f98c66b
7 changed files with 71 additions and 39 deletions

View File

@@ -124,6 +124,7 @@ func urlHandler(c echo.Context) error {
if err != nil { if err != nil {
return err return err
} }
opts.CustomHeaders = resource.RemoteURLCustomHeaders(r)
if !r.HasArg(resource.RemoteURLArgKey) { if !r.HasArg(resource.RemoteURLArgKey) {
return xerror.Invalid( return xerror.Invalid(
op, op,
@@ -323,11 +324,14 @@ func convertAsync(ctx context.Context, p printer.Printer, filename, fpath string
} }
req.Header.Set(echo.HeaderContentType, "application/pdf") req.Header.Set(echo.HeaderContentType, "application/pdf")
// set custom headers (if any). // set custom headers (if any).
for key, value := range resource.WebhookURLCustomHeaders(r) { customHeaders := resource.WebhookURLCustomHeaders(r)
for _, v := range value { if len(customHeaders) > 0 {
req.Header.Add(key, v) for key, value := range customHeaders {
logger.DebugfOp(op, "added '%s' to custom header '%s'", v, key) 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. // send the result file.
logger.DebugfOp( logger.DebugfOp(

View File

@@ -79,8 +79,8 @@ func (ctx *Context) WithResource(directoryName string) error {
return r, err return r, err
} }
// retrieve custom headers from request. // retrieve custom headers from request.
for name, value := range ctx.Request().Header { for key, value := range ctx.Request().Header {
r.WithCustomHeader(name, value) r.WithCustomHeader(key, value[0])
} }
// retrieve form values from request. // retrieve form values from request.
for _, key := range resource.ArgKeys() { for _, key := range resource.ArgKeys() {

View File

@@ -13,8 +13,8 @@ const (
WebhookURLCustomHeaderCanonicalBaseKey string = "Gotenberg-Webhookurl-" WebhookURLCustomHeaderCanonicalBaseKey string = "Gotenberg-Webhookurl-"
) )
func fetchCustomHeaders(r Resource, baseKey string) map[string][]string { func fetchCustomHeaders(r Resource, baseKey string) map[string]string {
customHeaders := make(map[string][]string) customHeaders := make(map[string]string)
for key, value := range r.customHeaders { for key, value := range r.customHeaders {
if strings.Contains(key, baseKey) { if strings.Contains(key, baseKey) {
realKey := strings.Replace(key, baseKey, "", 1) 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 // RemoteURLCustomHeaders is a helper for retrieving
// the custom headers for the URL conversion. // 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) return fetchCustomHeaders(r, RemoteURLCustomHeaderCanonicalBaseKey)
} }
// WebhookURLCustomHeaders is a helper for retrieving // WebhookURLCustomHeaders is a helper for retrieving
// the custom headers for the webhook URL. // 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) return fetchCustomHeaders(r, WebhookURLCustomHeaderCanonicalBaseKey)
} }

View File

@@ -18,17 +18,13 @@ func TestRemoteURLCustomHeaders(t *testing.T) {
customHeaderValue := "bar" customHeaderValue := "bar"
customHeaderCanonicalRealKey := "Foo" customHeaderCanonicalRealKey := "Foo"
customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", RemoteURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", RemoteURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey))
r.WithCustomHeader(customHeaderCanonicalKey, []string{customHeaderValue}) r.WithCustomHeader(customHeaderCanonicalKey, customHeaderValue)
r.WithCustomHeader("Bar", []string{"Bar"}) r.WithCustomHeader("Bar", "Bar")
expected := map[string][]string{ expected := map[string]string{
customHeaderCanonicalRealKey: []string{ customHeaderCanonicalRealKey: customHeaderValue,
customHeaderValue,
},
} }
notExpected := map[string][]string{ notExpected := map[string]string{
customHeaderCanonicalKey: []string{ customHeaderCanonicalKey: customHeaderValue,
customHeaderValue,
},
} }
v := RemoteURLCustomHeaders(r) v := RemoteURLCustomHeaders(r)
assert.Equal(t, expected, v) assert.Equal(t, expected, v)
@@ -44,17 +40,13 @@ func TestWebhookURLCustomHeaders(t *testing.T) {
customHeaderValue := "bar" customHeaderValue := "bar"
customHeaderCanonicalRealKey := "Foo" customHeaderCanonicalRealKey := "Foo"
customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", WebhookURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey)) customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", WebhookURLCustomHeaderCanonicalBaseKey, customHeaderCanonicalRealKey))
r.WithCustomHeader(customHeaderCanonicalKey, []string{customHeaderValue}) r.WithCustomHeader(customHeaderCanonicalKey, customHeaderValue)
r.WithCustomHeader("Bar", []string{"Bar"}) r.WithCustomHeader("Bar", "Bar")
expected := map[string][]string{ expected := map[string]string{
customHeaderCanonicalRealKey: []string{ customHeaderCanonicalRealKey: customHeaderValue,
customHeaderValue,
},
} }
notExpected := map[string][]string{ notExpected := map[string]string{
customHeaderCanonicalKey: []string{ customHeaderCanonicalKey: customHeaderValue,
customHeaderValue,
},
} }
v := WebhookURLCustomHeaders(r) v := WebhookURLCustomHeaders(r)
assert.Equal(t, expected, v) assert.Equal(t, expected, v)

View File

@@ -3,6 +3,7 @@ package resource
import ( import (
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -25,7 +26,7 @@ const TemporaryDirectory string = "tmp"
type Resource struct { type Resource struct {
logger xlog.Logger logger xlog.Logger
dirPath string dirPath string
customHeaders map[string][]string customHeaders map[string]string
args map[ArgKey]string args map[ArgKey]string
files map[string]file files map[string]file
} }
@@ -53,7 +54,7 @@ func New(logger xlog.Logger, directoryName string) (Resource, error) {
return Resource{ return Resource{
logger: logger, logger: logger,
dirPath: dirPath, dirPath: dirPath,
customHeaders: make(map[string][]string), customHeaders: make(map[string]string),
args: make(map[ArgKey]string), args: make(map[ArgKey]string),
files: make(map[string]file), files: make(map[string]file),
}, nil }, nil
@@ -76,15 +77,17 @@ func (r Resource) Close() error {
// WithCustomHeader add a new custom header to the Resource. // WithCustomHeader add a new custom header to the Resource.
// Given key should be in canonical format. // 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" const op string = "resource.Resource.WithCustomHeader"
if strings.Contains(key, RemoteURLCustomHeaderCanonicalBaseKey) || // should already be in canonical format.
strings.Contains(key, WebhookURLCustomHeaderCanonicalBaseKey) { canonicalKey := http.CanonicalHeaderKey(key)
r.customHeaders[key] = value if strings.Contains(canonicalKey, RemoteURLCustomHeaderCanonicalBaseKey) ||
r.logger.DebugfOp(op, "added '%s' with value '%s' to resource custom headers", key, value) strings.Contains(canonicalKey, WebhookURLCustomHeaderCanonicalBaseKey) {
r.customHeaders[canonicalKey] = value
r.logger.DebugfOp(op, "added '%s' with value '%s' to resource custom headers", canonicalKey, value)
return 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. // WithArg add a new argument to the Resource.

View File

@@ -2,6 +2,7 @@ package printer
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strings" "strings"
@@ -42,6 +43,7 @@ type ChromePrinterOptions struct {
MarginRight float64 MarginRight float64
Landscape bool Landscape bool
RpccBufferSize int64 RpccBufferSize int64
CustomHeaders map[string]string
} }
// DefaultChromePrinterOptions returns the default // DefaultChromePrinterOptions returns the default
@@ -61,6 +63,7 @@ func DefaultChromePrinterOptions(config conf.Config) ChromePrinterOptions {
MarginRight: 1.0, MarginRight: 1.0,
Landscape: false, Landscape: false,
RpccBufferSize: config.DefaultGoogleChromeRpccBufferSize(), 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 { if err := p.enableEvents(ctx, targetClient); err != nil {
return err return err
} }
// add custom headers (if any).
if err := p.setCustomHeaders(ctx, targetClient); err != nil {
return err
}
// listen for all events. // listen for all events.
if err := p.listenEvents(ctx, targetClient); err != nil { if err := p.listenEvents(ctx, targetClient); err != nil {
return err return err
@@ -247,6 +254,32 @@ func (p chromePrinter) enableEvents(ctx context.Context, client *cdp.Client) err
return nil 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 { func (p chromePrinter) listenEvents(ctx context.Context, client *cdp.Client) error {
const op string = "printer.chromePrinter.listenEvents" const op string = "printer.chromePrinter.listenEvents"
resolver := func() error { resolver := func() error {

View File

@@ -79,7 +79,7 @@ func multipartForm(
require.Nil(t, err) require.Nil(t, err)
} }
if kind == "url" { if kind == "url" {
err := writer.WriteField("remoteURL", "http://google.com") err := writer.WriteField("remoteURL", "https://google.com")
require.Nil(t, err) require.Nil(t, err)
} }
for k, v := range formValues { for k, v := range formValues {