Merge pull request #37 from halverneus/dev

Added CORS wildcard support.
This commit is contained in:
Jeromy Streets 2019-10-16 09:43:40 -07:00 committed by GitHub
commit 3ddb069d05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 129 additions and 20 deletions

View File

@ -3,7 +3,7 @@
################################################################################ ################################################################################
FROM golang:1.13.1 as builder FROM golang:1.13.1 as builder
ENV VERSION 1.6.6 ENV VERSION 1.7.0
ENV BUILD_DIR /build ENV BUILD_DIR /build
RUN mkdir -p ${BUILD_DIR} RUN mkdir -p ${BUILD_DIR}
@ -31,5 +31,5 @@ LABEL life.apets.vendor="Halverneus" \
life.apets.url="https://github.com/halverneus/static-file-server" \ life.apets.url="https://github.com/halverneus/static-file-server" \
life.apets.name="Static File Server" \ life.apets.name="Static File Server" \
life.apets.description="A tiny static file server" \ life.apets.description="A tiny static file server" \
life.apets.version="v1.6.6" \ life.apets.version="v1.7.0" \
life.apets.schema-version="1.0" life.apets.schema-version="1.0"

View File

@ -1,6 +1,6 @@
FROM golang:1.13.1 as builder FROM golang:1.13.1 as builder
ENV VERSION 1.6.6 ENV VERSION 1.7.0
ENV BUILD_DIR /build ENV BUILD_DIR /build
RUN mkdir -p ${BUILD_DIR} RUN mkdir -p ${BUILD_DIR}
@ -21,5 +21,5 @@ LABEL life.apets.vendor="Halverneus" \
life.apets.url="https://github.com/halverneus/static-file-server" \ life.apets.url="https://github.com/halverneus/static-file-server" \
life.apets.name="Static File Server" \ life.apets.name="Static File Server" \
life.apets.description="A tiny static file server" \ life.apets.description="A tiny static file server" \
life.apets.version="v1.6.6" \ life.apets.version="v1.7.0" \
life.apets.schema-version="1.0" life.apets.schema-version="1.0"

View File

@ -14,6 +14,9 @@ Install from any of the following locations:
Default values are shown with the associated environment variable. Default values are shown with the associated environment variable.
```bash ```bash
# Enables resource access from any domain.
CORS=false
# Enable debugging for troubleshooting. If set to 'true' this prints extra # Enable debugging for troubleshooting. If set to 'true' this prints extra
# information during execution. IMPORTANT NOTE: The configuration summary is # information during execution. IMPORTANT NOTE: The configuration summary is
# printed to stdout while logs generated during execution are printed to stderr. # printed to stdout while logs generated during execution are printed to stderr.
@ -60,6 +63,7 @@ the path to the configuration file using the command line option
('-c', '-config', '--config'). ('-c', '-config', '--config').
```yaml ```yaml
cors: false
debug: false debug: false
folder: /web folder: /web
host: "" host: ""

View File

@ -33,6 +33,10 @@ DEPENDENCIES
None... not even libc! None... not even libc!
ENVIRONMENT VARIABLES ENVIRONMENT VARIABLES
CORS
When set to 'true' it enables resource access from any domain. All
responses will include the headers 'Access-Control-Allow-Origin' and
'Access-Control-Allow-Headers' with a wildcard value ('*').
DEBUG DEBUG
When set to 'true' enables additional logging, including the When set to 'true' enables additional logging, including the
configuration used and an access log for each request. IMPORTANT NOTE: configuration used and an access log for each request. IMPORTANT NOTE:
@ -85,6 +89,7 @@ CONFIGURATION FILE
Example config.yml with defaults: Example config.yml with defaults:
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
cors: false
debug: false debug: false
folder: /web folder: /web
host: "" host: ""

View File

@ -61,6 +61,12 @@ func handlerSelector() (handler http.HandlerFunc) {
if !config.Get.ShowListing { if !config.Get.ShowListing {
handler = handle.IgnoreIndex(handler) handler = handle.IgnoreIndex(handler)
} }
// If configured, apply wildcard CORS support.
if config.Get.Cors {
handler = handle.AddCorsWildcardHeaders(handler)
}
return return
} }

View File

@ -42,23 +42,28 @@ func TestHandlerSelector(t *testing.T) {
listing bool listing bool
debug bool debug bool
refer []string refer []string
cors bool
}{ }{
{"Basic handler w/o debug", testFolder, "", true, false, ignoreReferrer}, {"Basic handler w/o debug", testFolder, "", true, false, ignoreReferrer, false},
{"Prefix handler w/o debug", testFolder, testPrefix, true, false, ignoreReferrer}, {"Prefix handler w/o debug", testFolder, testPrefix, true, false, ignoreReferrer, false},
{"Basic and hide listing handler w/o debug", testFolder, "", false, false, ignoreReferrer}, {"Basic and hide listing handler w/o debug", testFolder, "", false, false, ignoreReferrer, false},
{"Prefix and hide listing handler w/o debug", testFolder, testPrefix, false, false, ignoreReferrer}, {"Prefix and hide listing handler w/o debug", testFolder, testPrefix, false, false, ignoreReferrer, false},
{"Basic handler w/debug", testFolder, "", true, true, ignoreReferrer}, {"Basic handler w/debug", testFolder, "", true, true, ignoreReferrer, false},
{"Prefix handler w/debug", testFolder, testPrefix, true, true, ignoreReferrer}, {"Prefix handler w/debug", testFolder, testPrefix, true, true, ignoreReferrer, false},
{"Basic and hide listing handler w/debug", testFolder, "", false, true, ignoreReferrer}, {"Basic and hide listing handler w/debug", testFolder, "", false, true, ignoreReferrer, false},
{"Prefix and hide listing handler w/debug", testFolder, testPrefix, false, true, ignoreReferrer}, {"Prefix and hide listing handler w/debug", testFolder, testPrefix, false, true, ignoreReferrer, false},
{"Basic handler w/o debug w/refer", testFolder, "", true, false, testReferrer}, {"Basic handler w/o debug w/refer", testFolder, "", true, false, testReferrer, false},
{"Prefix handler w/o debug w/refer", testFolder, testPrefix, true, false, testReferrer}, {"Prefix handler w/o debug w/refer", testFolder, testPrefix, true, false, testReferrer, false},
{"Basic and hide listing handler w/o debug w/refer", testFolder, "", false, false, testReferrer}, {"Basic and hide listing handler w/o debug w/refer", testFolder, "", false, false, testReferrer, false},
{"Prefix and hide listing handler w/o debug w/refer", testFolder, testPrefix, false, false, testReferrer}, {"Prefix and hide listing handler w/o debug w/refer", testFolder, testPrefix, false, false, testReferrer, false},
{"Basic handler w/debug w/refer", testFolder, "", true, true, testReferrer}, {"Basic handler w/debug w/refer w/o cors", testFolder, "", true, true, testReferrer, false},
{"Prefix handler w/debug w/refer", testFolder, testPrefix, true, true, testReferrer}, {"Prefix handler w/debug w/refer w/o cors", testFolder, testPrefix, true, true, testReferrer, false},
{"Basic and hide listing handler w/debug w/refer", testFolder, "", false, true, testReferrer}, {"Basic and hide listing handler w/debug w/refer w/o cors", testFolder, "", false, true, testReferrer, false},
{"Prefix and hide listing handler w/debug w/refer", testFolder, testPrefix, false, true, testReferrer}, {"Prefix and hide listing handler w/debug w/refer w/o cors", testFolder, testPrefix, false, true, testReferrer, false},
{"Basic handler w/debug w/refer w/cors", testFolder, "", true, true, testReferrer, true},
{"Prefix handler w/debug w/refer w/cors", testFolder, testPrefix, true, true, testReferrer, true},
{"Basic and hide listing handler w/debug w/refer w/cors", testFolder, "", false, true, testReferrer, true},
{"Prefix and hide listing handler w/debug w/refer w/cors", testFolder, testPrefix, false, true, testReferrer, true},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -68,6 +73,7 @@ func TestHandlerSelector(t *testing.T) {
config.Get.ShowListing = tc.listing config.Get.ShowListing = tc.listing
config.Get.URLPrefix = tc.prefix config.Get.URLPrefix = tc.prefix
config.Get.Referrers = tc.refer config.Get.Referrers = tc.refer
config.Get.Cors = tc.cors
handlerSelector() handlerSelector()
}) })

View File

@ -14,6 +14,7 @@ import (
var ( var (
// Get the desired configuration value. // Get the desired configuration value.
Get struct { Get struct {
Cors bool `yaml:"cors"`
Debug bool `yaml:"debug"` Debug bool `yaml:"debug"`
Folder string `yaml:"folder"` Folder string `yaml:"folder"`
Host string `yaml:"host"` Host string `yaml:"host"`
@ -27,6 +28,7 @@ var (
) )
const ( const (
corsKey = "CORS"
debugKey = "DEBUG" debugKey = "DEBUG"
folderKey = "FOLDER" folderKey = "FOLDER"
hostKey = "HOST" hostKey = "HOST"
@ -48,6 +50,7 @@ var (
defaultTLSCert = "" defaultTLSCert = ""
defaultTLSKey = "" defaultTLSKey = ""
defaultURLPrefix = "" defaultURLPrefix = ""
defaultCors = false
) )
func init() { func init() {
@ -65,6 +68,7 @@ func setDefaults() {
Get.TLSCert = defaultTLSCert Get.TLSCert = defaultTLSCert
Get.TLSKey = defaultTLSKey Get.TLSKey = defaultTLSKey
Get.URLPrefix = defaultURLPrefix Get.URLPrefix = defaultURLPrefix
Get.Cors = defaultCors
} }
// Load the configuration file. // Load the configuration file.
@ -104,6 +108,7 @@ func Log() {
// overrideWithEnvVars the default values and the configuration file values. // overrideWithEnvVars the default values and the configuration file values.
func overrideWithEnvVars() { func overrideWithEnvVars() {
// Assign envvars, if set. // Assign envvars, if set.
Get.Cors = envAsBool(corsKey, Get.Cors)
Get.Debug = envAsBool(debugKey, Get.Debug) Get.Debug = envAsBool(debugKey, Get.Debug)
Get.Folder = envAsStr(folderKey, Get.Folder) Get.Folder = envAsStr(folderKey, Get.Folder)
Get.Host = envAsStr(hostKey, Get.Host) Get.Host = envAsStr(hostKey, Get.Host)

View File

@ -109,6 +109,16 @@ func IgnoreIndex(serve http.HandlerFunc) http.HandlerFunc {
} }
} }
// AddCorsWildcardHeaders wraps an HTTP request to notify client browsers that
// resources should be allowed to be retrieved by any other domain.
func AddCorsWildcardHeaders(serve http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
serve(w, r)
}
}
// Listening function for serving the handler function. // Listening function for serving the handler function.
func Listening() ListenerFunc { func Listening() ListenerFunc {
return func(binding string, handler http.HandlerFunc) error { return func(binding string, handler http.HandlerFunc) error {

View File

@ -458,3 +458,76 @@ func TestValidReferrer(t *testing.T) {
}) })
} }
} }
func TestAddCorsWildcardHeaders(t *testing.T) {
testCases := []struct {
name string
corsEnabled bool
}{
{"CORS disabled", false},
{"CORS enabled", true},
}
corsHeaders := map[string]string{
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
}
for _, serveFile := range serveFileFuncs {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var handler http.HandlerFunc
if tc.corsEnabled {
handler = AddCorsWildcardHeaders(Basic(serveFile, baseDir))
} else {
handler = Basic(serveFile, baseDir)
}
fullpath := "http://localhost/" + tmpFileName
req := httptest.NewRequest("GET", fullpath, nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
body, err := ioutil.ReadAll(resp.Body)
if nil != err {
t.Errorf("While reading body got %v", err)
}
contents := string(body)
if ok != resp.StatusCode {
t.Errorf(
"While retrieving %s expected status code of %d but got %d",
fullpath, ok, resp.StatusCode,
)
}
if tmpFile != contents {
t.Errorf(
"While retrieving %s expected contents '%s' but got '%s'",
fullpath, tmpFile, contents,
)
}
if tc.corsEnabled {
for k, v := range corsHeaders {
if v != resp.Header.Get(k) {
t.Errorf(
"With CORS enabled expect header '%s' to return '%s' but got '%s'",
k, v, resp.Header.Get(k),
)
}
}
} else {
for k := range corsHeaders {
if "" != resp.Header.Get(k) {
t.Errorf(
"With CORS disabled expected header '%s' to return '' but got '%s'",
k, resp.Header.Get(k),
)
}
}
}
})
}
}
}