Add URL signature feature (#194)
* Add URL signature feature * Fix signature salt empty & key/salt check
This commit is contained in:
parent
3a3bd3a462
commit
2a374823ff
|
@ -8,6 +8,7 @@ Thumbs.db
|
|||
# Folders
|
||||
_obj
|
||||
_test
|
||||
.idea
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
|
|
42
README.md
42
README.md
|
@ -6,7 +6,7 @@
|
|||
It's almost dependency-free and only uses [`net/http`](http://golang.org/pkg/net/http/) native package without additional abstractions for better [performance](#performance).
|
||||
|
||||
Supports multiple [image operations](#supported-image-operations) exposed as a simple [HTTP API](#http-api),
|
||||
with additional optional features such as **API token authorization**, **HTTP traffic throttle** strategy and **CORS support** for web clients.
|
||||
with additional optional features such as **API token authorization**, **URL signature protection**, **HTTP traffic throttle** strategy and **CORS support** for web clients.
|
||||
|
||||
`imaginary` **can read** images **from HTTP POST payloads**, **server local path** or **remote HTTP servers**, supporting **JPEG**, **PNG**, **WEBP**, and optionally **TIFF**, **PDF**, **GIF** and **SVG** formats if `libvips@8.3+` is compiled with proper library bindings.
|
||||
|
||||
|
@ -38,6 +38,7 @@ To get started, take a look the [installation](#installation) steps, [usage](#us
|
|||
- [Usage](#usage)
|
||||
- [HTTP API](#http-api)
|
||||
- [Authorization](#authorization)
|
||||
- [URL signature](#url-signature)
|
||||
- [Errors](#errors)
|
||||
- [Form data](#form-data)
|
||||
- [Params](#params)
|
||||
|
@ -293,6 +294,7 @@ Usage:
|
|||
imaginary -enable-url-source -authorization "Basic AwDJdL2DbwrD=="
|
||||
imaginary -enable-placeholder
|
||||
imaginary -enable-url-source -placeholder ./placeholder.jpg
|
||||
imaginary -enable-url-signature -url-signature-key 4f46feebafc4b5e988f131c4ff8b5997 -url-signature-salt 88f131c4ff8b59974f46feebafc4b5e9
|
||||
imaginary -h | -help
|
||||
imaginary -v | -version
|
||||
|
||||
|
@ -313,6 +315,9 @@ Options:
|
|||
-enable-url-source Restrict remote image source processing to certain origins (separated by commas)
|
||||
-enable-placeholder Enable image response placeholder to be used in case of error [default: false]
|
||||
-enable-auth-forwarding Forwards X-Forward-Authorization or Authorization header to the image source server. -enable-url-source flag must be defined. Tip: secure your server from public access to prevent attack vectors
|
||||
-enable-url-signature Enable URL signature (URL-safe Base64-encoded HMAC digest) [default: false]
|
||||
-url-signature-key The URL signature key (32 characters minimum)
|
||||
-url-signature-salt The URL signature salt (32 characters minimum)
|
||||
-allowed-origins <urls> Restrict remote image source processing to certain origins (separated by commas)
|
||||
-max-allowed-size <bytes> Restrict maximum size of http image source (in bytes)
|
||||
-certfile <path> TLS certificate file path
|
||||
|
@ -385,6 +390,18 @@ Supported custom placeholder image types are: `JPEG`, `PNG` and `WEBP`.
|
|||
imaginary -p 8080 -placeholder=placeholder.jpg -enable-url-source
|
||||
```
|
||||
|
||||
Enable URL signature (URL-safe Base64-encoded HMAC digest).
|
||||
|
||||
This feature is particularly useful to protect against multiple image operations attacks and to verify the requester identity.
|
||||
```
|
||||
imaginary -p 8080 -enable-url-signature -url-signature-key 4f46feebafc4b5e988f131c4ff8b5997 -url-signature-salt 88f131c4ff8b59974f46feebafc4b5e9
|
||||
```
|
||||
|
||||
It is recommanded to pass key and salt as environment variables:
|
||||
```
|
||||
URL_SIGNATURE_KEY=4f46feebafc4b5e988f131c4ff8b5997 URL_SIGNATURE_SALT=88f131c4ff8b59974f46feebafc4b5e9 imaginary -p 8080 -enable-url-signature
|
||||
```
|
||||
|
||||
Increase libvips threads concurrency (experimental):
|
||||
```
|
||||
VIPS_CONCURRENCY=10 imaginary -p 8080 -concurrency 10
|
||||
|
@ -438,6 +455,28 @@ Host: localhost:8088
|
|||
API-Key: secret
|
||||
```
|
||||
|
||||
### URL signature
|
||||
|
||||
The URL signature is provided by the `sign` request parameter.
|
||||
|
||||
The HMAC-SHA256 hash is created by taking the URL path (including the leading /), the request parameters (alphabetically-sorted, excluding the `sign` one and concatenated with & into a string) and the signature salt. The hash is then base64url-encoded.
|
||||
|
||||
Here an example in Go:
|
||||
```
|
||||
signKey := "4f46feebafc4b5e988f131c4ff8b5997"
|
||||
signSalt := "88f131c4ff8b59974f46feebafc4b5e9"
|
||||
urlPath := "/resize"
|
||||
urlQuery := "file=image.jpg&height=200&type=jpeg&width=300"
|
||||
|
||||
h := hmac.New(sha256.New, []byte(signKey))
|
||||
h.Write([]byte(urlPath))
|
||||
h.Write([]byte(urlQuery))
|
||||
h.Write([]byte(signSalt))
|
||||
buf := h.Sum(nil)
|
||||
|
||||
fmt.Println("sign=" + base64.RawURLEncoding.EncodeToString(buf))
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
`imaginary` will always reply with the proper HTTP status code and JSON body with error details.
|
||||
|
@ -512,6 +551,7 @@ Image measures are always in pixels, unless otherwise indicated.
|
|||
- **sigma** `float` - Size of the gaussian mask to use when blurring an image. Example: `15.0`
|
||||
- **minampl** `float` - Minimum amplitude of the gaussian filter to use when blurring an image. Default: Example: `0.5`
|
||||
- **operations** `json` - Pipeline of image operation transformations defined as URL safe encoded JSON array. See [pipeline](#get--post-pipeline) endpoints for more details.
|
||||
- **sign** `string` - URL signature (URL-safe Base64-encoded HMAC digest)
|
||||
|
||||
#### GET /
|
||||
Content-Type: `application/json`
|
||||
|
|
28
error.go
28
error.go
|
@ -18,20 +18,23 @@ const (
|
|||
InternalError
|
||||
NotFound
|
||||
NotImplemented
|
||||
Forbidden
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = NewError("Not found", NotFound)
|
||||
ErrInvalidApiKey = NewError("Invalid or missing API key", Unauthorized)
|
||||
ErrMethodNotAllowed = NewError("Method not allowed", NotAllowed)
|
||||
ErrUnsupportedMedia = NewError("Unsupported media type", Unsupported)
|
||||
ErrOutputFormat = NewError("Unsupported output image format", BadRequest)
|
||||
ErrEmptyBody = NewError("Empty image", BadRequest)
|
||||
ErrMissingParamFile = NewError("Missing required param: file", BadRequest)
|
||||
ErrInvalidFilePath = NewError("Invalid file path", BadRequest)
|
||||
ErrInvalidImageURL = NewError("Invalid image URL", BadRequest)
|
||||
ErrMissingImageSource = NewError("Cannot process the image due to missing or invalid params", BadRequest)
|
||||
ErrNotImplemented = NewError("Not implemented endpoint", NotImplemented)
|
||||
ErrNotFound = NewError("Not found", NotFound)
|
||||
ErrInvalidApiKey = NewError("Invalid or missing API key", Unauthorized)
|
||||
ErrMethodNotAllowed = NewError("Method not allowed", NotAllowed)
|
||||
ErrUnsupportedMedia = NewError("Unsupported media type", Unsupported)
|
||||
ErrOutputFormat = NewError("Unsupported output image format", BadRequest)
|
||||
ErrEmptyBody = NewError("Empty image", BadRequest)
|
||||
ErrMissingParamFile = NewError("Missing required param: file", BadRequest)
|
||||
ErrInvalidFilePath = NewError("Invalid file path", BadRequest)
|
||||
ErrInvalidImageURL = NewError("Invalid image URL", BadRequest)
|
||||
ErrMissingImageSource = NewError("Cannot process the image due to missing or invalid params", BadRequest)
|
||||
ErrNotImplemented = NewError("Not implemented endpoint", NotImplemented)
|
||||
ErrInvalidURLSignature = NewError("Invalid URL signature", BadRequest)
|
||||
ErrURLSignatureMismatch = NewError("URL signature mismatch", Forbidden)
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
|
@ -70,6 +73,9 @@ func (e Error) HTTPCode() int {
|
|||
if e.Code == NotImplemented {
|
||||
return http.StatusNotImplemented
|
||||
}
|
||||
if e.Code == Forbidden {
|
||||
return http.StatusForbidden
|
||||
}
|
||||
return http.StatusServiceUnavailable
|
||||
}
|
||||
|
||||
|
|
140
imaginary.go
140
imaginary.go
|
@ -17,34 +17,37 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
aAddr = flag.String("a", "", "Bind address")
|
||||
aPort = flag.Int("p", 8088, "Port to listen")
|
||||
aVers = flag.Bool("v", false, "Show version")
|
||||
aVersl = flag.Bool("version", false, "Show version")
|
||||
aHelp = flag.Bool("h", false, "Show help")
|
||||
aHelpl = flag.Bool("help", false, "Show help")
|
||||
aPathPrefix = flag.String("path-prefix", "/", "Url path prefix to listen to")
|
||||
aCors = flag.Bool("cors", false, "Enable CORS support")
|
||||
aGzip = flag.Bool("gzip", false, "Enable gzip compression (deprecated)")
|
||||
aAuthForwarding = flag.Bool("enable-auth-forwarding", false, "Forwards X-Forward-Authorization or Authorization header to the image source server. -enable-url-source flag must be defined. Tip: secure your server from public access to prevent attack vectors")
|
||||
aEnableURLSource = flag.Bool("enable-url-source", false, "Enable remote HTTP URL image source processing")
|
||||
aEnablePlaceholder = flag.Bool("enable-placeholder", false, "Enable image response placeholder to be used in case of error")
|
||||
aAlloweOrigins = flag.String("allowed-origins", "", "Restrict remote image source processing to certain origins (separated by commas)")
|
||||
aMaxAllowedSize = flag.Int("max-allowed-size", 0, "Restrict maximum size of http image source (in bytes)")
|
||||
aKey = flag.String("key", "", "Define API key for authorization")
|
||||
aMount = flag.String("mount", "", "Mount server local directory")
|
||||
aCertFile = flag.String("certfile", "", "TLS certificate file path")
|
||||
aKeyFile = flag.String("keyfile", "", "TLS private key file path")
|
||||
aAuthorization = flag.String("authorization", "", "Defines a constant Authorization header value passed to all the image source servers. -enable-url-source flag must be defined. This overwrites authorization headers forwarding behavior via X-Forward-Authorization")
|
||||
aPlaceholder = flag.String("placeholder", "", "Image path to image custom placeholder to be used in case of error. Recommended minimum image size is: 1200x1200")
|
||||
aDisableEndpoints = flag.String("disable-endpoints", "", "Comma separated endpoints to disable. E.g: form,crop,rotate,health")
|
||||
aHTTPCacheTTL = flag.Int("http-cache-ttl", -1, "The TTL in seconds")
|
||||
aReadTimeout = flag.Int("http-read-timeout", 60, "HTTP read timeout in seconds")
|
||||
aWriteTimeout = flag.Int("http-write-timeout", 60, "HTTP write timeout in seconds")
|
||||
aConcurrency = flag.Int("concurrency", 0, "Throttle concurrency limit per second")
|
||||
aBurst = flag.Int("burst", 100, "Throttle burst max cache size")
|
||||
aMRelease = flag.Int("mrelease", 30, "OS memory release interval in seconds")
|
||||
aCpus = flag.Int("cpus", runtime.GOMAXPROCS(-1), "Number of cpu cores to use")
|
||||
aAddr = flag.String("a", "", "Bind address")
|
||||
aPort = flag.Int("p", 8088, "Port to listen")
|
||||
aVers = flag.Bool("v", false, "Show version")
|
||||
aVersl = flag.Bool("version", false, "Show version")
|
||||
aHelp = flag.Bool("h", false, "Show help")
|
||||
aHelpl = flag.Bool("help", false, "Show help")
|
||||
aPathPrefix = flag.String("path-prefix", "/", "Url path prefix to listen to")
|
||||
aCors = flag.Bool("cors", false, "Enable CORS support")
|
||||
aGzip = flag.Bool("gzip", false, "Enable gzip compression (deprecated)")
|
||||
aAuthForwarding = flag.Bool("enable-auth-forwarding", false, "Forwards X-Forward-Authorization or Authorization header to the image source server. -enable-url-source flag must be defined. Tip: secure your server from public access to prevent attack vectors")
|
||||
aEnableURLSource = flag.Bool("enable-url-source", false, "Enable remote HTTP URL image source processing")
|
||||
aEnablePlaceholder = flag.Bool("enable-placeholder", false, "Enable image response placeholder to be used in case of error")
|
||||
aEnableURLSignature = flag.Bool("enable-url-signature", false, "Enable URL signature (URL-safe Base64-encoded HMAC digest)")
|
||||
aURLSignatureKey = flag.String("url-signature-key", "", "The URL signature key (32 characters minimum)")
|
||||
aURLSignatureSalt = flag.String("url-signature-salt", "", "The URL signature salt (32 characters minimum)")
|
||||
aAllowedOrigins = flag.String("allowed-origins", "", "Restrict remote image source processing to certain origins (separated by commas)")
|
||||
aMaxAllowedSize = flag.Int("max-allowed-size", 0, "Restrict maximum size of http image source (in bytes)")
|
||||
aKey = flag.String("key", "", "Define API key for authorization")
|
||||
aMount = flag.String("mount", "", "Mount server local directory")
|
||||
aCertFile = flag.String("certfile", "", "TLS certificate file path")
|
||||
aKeyFile = flag.String("keyfile", "", "TLS private key file path")
|
||||
aAuthorization = flag.String("authorization", "", "Defines a constant Authorization header value passed to all the image source servers. -enable-url-source flag must be defined. This overwrites authorization headers forwarding behavior via X-Forward-Authorization")
|
||||
aPlaceholder = flag.String("placeholder", "", "Image path to image custom placeholder to be used in case of error. Recommended minimum image size is: 1200x1200")
|
||||
aDisableEndpoints = flag.String("disable-endpoints", "", "Comma separated endpoints to disable. E.g: form,crop,rotate,health")
|
||||
aHTTPCacheTTL = flag.Int("http-cache-ttl", -1, "The TTL in seconds")
|
||||
aReadTimeout = flag.Int("http-read-timeout", 60, "HTTP read timeout in seconds")
|
||||
aWriteTimeout = flag.Int("http-write-timeout", 60, "HTTP write timeout in seconds")
|
||||
aConcurrency = flag.Int("concurrency", 0, "Throttle concurrency limit per second")
|
||||
aBurst = flag.Int("burst", 100, "Throttle burst max cache size")
|
||||
aMRelease = flag.Int("mrelease", 30, "OS memory release interval in seconds")
|
||||
aCpus = flag.Int("cpus", runtime.GOMAXPROCS(-1), "Number of cpu cores to use")
|
||||
)
|
||||
|
||||
const usage = `imaginary %s
|
||||
|
@ -61,6 +64,7 @@ Usage:
|
|||
imaginary -enable-url-source -authorization "Basic AwDJdL2DbwrD=="
|
||||
imaginary -enable-placeholder
|
||||
imaginary -enable-url-source -placeholder ./placeholder.jpg
|
||||
imaginary -enable-url-signature -url-signature-key 4f46feebafc4b5e988f131c4ff8b5997 -url-signature-salt 88f131c4ff8b59974f46feebafc4b5e9
|
||||
imaginary -h | -help
|
||||
imaginary -v | -version
|
||||
|
||||
|
@ -81,6 +85,9 @@ Options:
|
|||
-enable-url-source Restrict remote image source processing to certain origins (separated by commas)
|
||||
-enable-placeholder Enable image response placeholder to be used in case of error [default: false]
|
||||
-enable-auth-forwarding Forwards X-Forward-Authorization or Authorization header to the image source server. -enable-url-source flag must be defined. Tip: secure your server from public access to prevent attack vectors
|
||||
-enable-url-signature Enable URL signature (URL-safe Base64-encoded HMAC digest) [default: false]
|
||||
-url-signature-key The URL signature key (32 characters minimum)
|
||||
-url-signature-salt The URL signature salt (32 characters minimum)
|
||||
-allowed-origins <urls> Restrict remote image source processing to certain origins (separated by commas)
|
||||
-max-allowed-size <bytes> Restrict maximum size of http image source (in bytes)
|
||||
-certfile <path> TLS certificate file path
|
||||
|
@ -94,6 +101,11 @@ Options:
|
|||
(default for current machine is %d cores)
|
||||
`
|
||||
|
||||
type URLSignature struct {
|
||||
Key string
|
||||
Salt string
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprint(os.Stderr, fmt.Sprintf(usage, Version, runtime.NumCPU()))
|
||||
|
@ -111,27 +123,32 @@ func main() {
|
|||
runtime.GOMAXPROCS(*aCpus)
|
||||
|
||||
port := getPort(*aPort)
|
||||
urlSignature := getURLSignature(*aURLSignatureKey, *aURLSignatureSalt)
|
||||
|
||||
opts := ServerOptions{
|
||||
Port: port,
|
||||
Address: *aAddr,
|
||||
CORS: *aCors,
|
||||
AuthForwarding: *aAuthForwarding,
|
||||
EnableURLSource: *aEnableURLSource,
|
||||
EnablePlaceholder: *aEnablePlaceholder,
|
||||
PathPrefix: *aPathPrefix,
|
||||
APIKey: *aKey,
|
||||
Concurrency: *aConcurrency,
|
||||
Burst: *aBurst,
|
||||
Mount: *aMount,
|
||||
CertFile: *aCertFile,
|
||||
KeyFile: *aKeyFile,
|
||||
Placeholder: *aPlaceholder,
|
||||
HTTPCacheTTL: *aHTTPCacheTTL,
|
||||
HTTPReadTimeout: *aReadTimeout,
|
||||
HTTPWriteTimeout: *aWriteTimeout,
|
||||
Authorization: *aAuthorization,
|
||||
AlloweOrigins: parseOrigins(*aAlloweOrigins),
|
||||
MaxAllowedSize: *aMaxAllowedSize,
|
||||
Port: port,
|
||||
Address: *aAddr,
|
||||
CORS: *aCors,
|
||||
AuthForwarding: *aAuthForwarding,
|
||||
EnableURLSource: *aEnableURLSource,
|
||||
EnablePlaceholder: *aEnablePlaceholder,
|
||||
EnableURLSignature: *aEnableURLSignature,
|
||||
URLSignatureKey: urlSignature.Key,
|
||||
URLSignatureSalt: urlSignature.Salt,
|
||||
PathPrefix: *aPathPrefix,
|
||||
APIKey: *aKey,
|
||||
Concurrency: *aConcurrency,
|
||||
Burst: *aBurst,
|
||||
Mount: *aMount,
|
||||
CertFile: *aCertFile,
|
||||
KeyFile: *aKeyFile,
|
||||
Placeholder: *aPlaceholder,
|
||||
HTTPCacheTTL: *aHTTPCacheTTL,
|
||||
HTTPReadTimeout: *aReadTimeout,
|
||||
HTTPWriteTimeout: *aWriteTimeout,
|
||||
Authorization: *aAuthorization,
|
||||
AllowedOrigins: parseOrigins(*aAllowedOrigins),
|
||||
MaxAllowedSize: *aMaxAllowedSize,
|
||||
}
|
||||
|
||||
// Show warning if gzip flag is passed
|
||||
|
@ -177,6 +194,21 @@ func main() {
|
|||
opts.PlaceholderImage = placeholder
|
||||
}
|
||||
|
||||
// Check URL signature key and salt, if required
|
||||
if *aEnableURLSignature == true {
|
||||
if urlSignature.Key == "" || urlSignature.Salt == "" {
|
||||
exitWithError("URL signature key and salt are required")
|
||||
}
|
||||
|
||||
if len(urlSignature.Key) < 32 {
|
||||
exitWithError("URL signature key must be a minimum of 32 characters")
|
||||
}
|
||||
|
||||
if len(urlSignature.Salt) < 32 {
|
||||
exitWithError("URL signature salt must be a minimum of 32 characters")
|
||||
}
|
||||
}
|
||||
|
||||
debug("imaginary server listening on port :%d/%s", opts.Port, strings.TrimPrefix(opts.PathPrefix, "/"))
|
||||
|
||||
// Load image source providers
|
||||
|
@ -199,6 +231,18 @@ func getPort(port int) int {
|
|||
return port
|
||||
}
|
||||
|
||||
func getURLSignature(key string, salt string) URLSignature {
|
||||
if keyEnv := os.Getenv("URL_SIGNATURE_KEY"); keyEnv != "" {
|
||||
key = keyEnv
|
||||
}
|
||||
|
||||
if saltEnv := os.Getenv("URL_SIGNATURE_SALT"); saltEnv != "" {
|
||||
salt = saltEnv
|
||||
}
|
||||
|
||||
return URLSignature{key, salt}
|
||||
}
|
||||
|
||||
func showUsage() {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
|
|
|
@ -5,6 +5,9 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/rs/cors"
|
||||
"gopkg.in/h2non/bimg.v1"
|
||||
|
@ -36,7 +39,13 @@ func Middleware(fn func(http.ResponseWriter, *http.Request), o ServerOptions) ht
|
|||
|
||||
func ImageMiddleware(o ServerOptions) func(Operation) http.Handler {
|
||||
return func(fn Operation) http.Handler {
|
||||
return validateImage(Middleware(imageController(o, Operation(fn)), o), o)
|
||||
handler := validateImage(Middleware(imageController(o, Operation(fn)), o), o)
|
||||
|
||||
if o.EnableURLSignature == true {
|
||||
return validateURLSignature(handler, o)
|
||||
}
|
||||
|
||||
return handler
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,3 +162,32 @@ func getCacheControl(ttl int) string {
|
|||
func isPublicPath(path string) bool {
|
||||
return path == "/" || path == "/health" || path == "/form"
|
||||
}
|
||||
|
||||
func validateURLSignature(next http.Handler, o ServerOptions) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Retrieve and remove URL signature from request parameters
|
||||
query := r.URL.Query()
|
||||
sign := query.Get("sign")
|
||||
query.Del("sign")
|
||||
|
||||
// Compute expected URL signature
|
||||
h := hmac.New(sha256.New, []byte(o.URLSignatureKey))
|
||||
h.Write([]byte(r.URL.Path))
|
||||
h.Write([]byte(query.Encode()))
|
||||
h.Write([]byte(o.URLSignatureSalt))
|
||||
expectedSign := h.Sum(nil)
|
||||
|
||||
urlSign, err := base64.RawURLEncoding.DecodeString(sign)
|
||||
if err != nil {
|
||||
ErrorReply(r, w, ErrInvalidURLSignature, o)
|
||||
return
|
||||
}
|
||||
|
||||
if hmac.Equal(urlSign, expectedSign) == false {
|
||||
ErrorReply(r, w, ErrURLSignatureMismatch, o)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
|
49
server.go
49
server.go
|
@ -11,29 +11,32 @@ import (
|
|||
)
|
||||
|
||||
type ServerOptions struct {
|
||||
Port int
|
||||
Burst int
|
||||
Concurrency int
|
||||
HTTPCacheTTL int
|
||||
HTTPReadTimeout int
|
||||
HTTPWriteTimeout int
|
||||
MaxAllowedSize int
|
||||
CORS bool
|
||||
Gzip bool // deprecated
|
||||
AuthForwarding bool
|
||||
EnableURLSource bool
|
||||
EnablePlaceholder bool
|
||||
Address string
|
||||
PathPrefix string
|
||||
APIKey string
|
||||
Mount string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
Authorization string
|
||||
Placeholder string
|
||||
PlaceholderImage []byte
|
||||
Endpoints Endpoints
|
||||
AlloweOrigins []*url.URL
|
||||
Port int
|
||||
Burst int
|
||||
Concurrency int
|
||||
HTTPCacheTTL int
|
||||
HTTPReadTimeout int
|
||||
HTTPWriteTimeout int
|
||||
MaxAllowedSize int
|
||||
CORS bool
|
||||
Gzip bool // deprecated
|
||||
AuthForwarding bool
|
||||
EnableURLSource bool
|
||||
EnablePlaceholder bool
|
||||
EnableURLSignature bool
|
||||
URLSignatureKey string
|
||||
URLSignatureSalt string
|
||||
Address string
|
||||
PathPrefix string
|
||||
APIKey string
|
||||
Mount string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
Authorization string
|
||||
Placeholder string
|
||||
PlaceholderImage []byte
|
||||
Endpoints Endpoints
|
||||
AllowedOrigins []*url.URL
|
||||
}
|
||||
|
||||
// Endpoints represents a list of endpoint names to disable.
|
||||
|
|
Loading…
Reference in New Issue