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
ENV VERSION 1.6.6
ENV VERSION 1.7.0
ENV BUILD_DIR /build
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.name="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"

View File

@ -1,6 +1,6 @@
FROM golang:1.13.1 as builder
ENV VERSION 1.6.6
ENV VERSION 1.7.0
ENV BUILD_DIR /build
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.name="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"

View File

@ -14,6 +14,9 @@ Install from any of the following locations:
Default values are shown with the associated environment variable.
```bash
# Enables resource access from any domain.
CORS=false
# Enable debugging for troubleshooting. If set to 'true' this prints extra
# information during execution. IMPORTANT NOTE: The configuration summary is
# 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').
```yaml
cors: false
debug: false
folder: /web
host: ""

View File

@ -33,6 +33,10 @@ DEPENDENCIES
None... not even libc!
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
When set to 'true' enables additional logging, including the
configuration used and an access log for each request. IMPORTANT NOTE:
@ -85,6 +89,7 @@ CONFIGURATION FILE
Example config.yml with defaults:
----------------------------------------------------------------------------
cors: false
debug: false
folder: /web
host: ""

View File

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

View File

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

View File

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