Skip to content

Commit

Permalink
Added the ability to enable debug logging.
Browse files Browse the repository at this point in the history
  • Loading branch information
halverneus committed Oct 18, 2018
1 parent 053077e commit f2f41ef
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 126 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Available on GitHub at https://github.com/halverneus/static-file-server
Environment variables with defaults:

```bash
# Enable debugging for troubleshooting. If set to 'true' this prints extra
# information during execution. Default value is 'false'.
DEBUG=false
# Optional Hostname for binding. Leave black to accept any incoming HTTP request
# on the prescribed port.
HOST=
Expand All @@ -34,6 +37,7 @@ configuration file with defaults. Pass in the path to the configuration file
using the command line option ('-c', '-config', '--config').

```yaml
debug: false
host: ""
port: 8080
show-listing: true
Expand Down
5 changes: 5 additions & 0 deletions cli/help/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ DEPENDENCIES
None... not even libc!
ENVIRONMENT VARIABLES
DEBUG
When set to 'true' enables additional logging, including the
configuration used and an access log for each request. Default value is
'false'.
FOLDER
The path to the folder containing the contents to be served over
HTTP(s). If not supplied, defaults to '/web' (for Docker reasons).
Expand Down Expand Up @@ -69,6 +73,7 @@ CONFIGURATION FILE
Example config.yml with defaults:
----------------------------------------------------------------------------
debug: false
folder: /web
host: ""
port: 8080
Expand Down
17 changes: 15 additions & 2 deletions cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ var (

// Run server.
func Run() error {
if config.Get.Debug {
config.Log()
}
// Choose and set the appropriate, optimized static file serving function.
handler := selectHandler()

Expand All @@ -30,11 +33,21 @@ func Run() error {
// handlerSelector returns the appropriate request handler based on
// configuration.
func handlerSelector() (handler http.HandlerFunc) {
var serveFileHandler handle.FileServerFunc
serveFileHandler = http.ServeFile
if config.Get.Debug {
serveFileHandler = handle.WithLogging(serveFileHandler)
}

// Choose and set the appropriate, optimized static file serving function.
if 0 == len(config.Get.URLPrefix) {
handler = handle.Basic(config.Get.Folder)
handler = handle.Basic(serveFileHandler, config.Get.Folder)
} else {
handler = handle.Prefix(config.Get.Folder, config.Get.URLPrefix)
handler = handle.Prefix(
serveFileHandler,
config.Get.Folder,
config.Get.URLPrefix,
)
}

// Determine whether index files should hidden.
Expand Down
24 changes: 18 additions & 6 deletions cli/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ func TestRun(t *testing.T) {
}
}

config.Get.Debug = false
if err := Run(); listenerError != err {
t.Errorf("Expected %v but got %v", listenerError, err)
t.Errorf("Without debug expected %v but got %v", listenerError, err)
}

config.Get.Debug = true
if err := Run(); listenerError != err {
t.Errorf("With debug expected %v but got %v", listenerError, err)
}
}

Expand All @@ -32,18 +38,24 @@ func TestHandlerSelector(t *testing.T) {
folder string
prefix string
listing bool
debug bool
}{
{"Basic handler", testFolder, "", true},
{"Prefix handler", testFolder, testPrefix, true},
{"Basic and hide listing handler", testFolder, "", false},
{"Prefix and hide listing handler", testFolder, testPrefix, false},
{"Basic handler w/o debug", testFolder, "", true, false},
{"Prefix handler w/o debug", testFolder, testPrefix, true, false},
{"Basic and hide listing handler w/o debug", testFolder, "", false, false},
{"Prefix and hide listing handler w/o debug", testFolder, testPrefix, false, false},
{"Basic handler w/debug", testFolder, "", true, true},
{"Prefix handler w/debug", testFolder, testPrefix, true, true},
{"Basic and hide listing handler w/debug", testFolder, "", false, true},
{"Prefix and hide listing handler w/debug", testFolder, testPrefix, false, true},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config.Get.Debug = tc.debug
config.Get.Folder = tc.folder
config.Get.URLPrefix = tc.prefix
config.Get.ShowListing = tc.listing
config.Get.URLPrefix = tc.prefix

handlerSelector()
})
Expand Down
4 changes: 2 additions & 2 deletions cli/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ var (
MajorVersion = 1

// MinorVersion of static-file-server.
MinorVersion = 3
MinorVersion = 4

// FixVersion of static-file-server.
FixVersion = 3
FixVersion = 0

// Text for directly accessing the static-file-server version.
Text = fmt.Sprintf(
Expand Down
16 changes: 16 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
var (
// Get the desired configuration value.
Get struct {
Debug bool `yaml:"debug"`
Folder string `yaml:"folder"`
Host string `yaml:"host"`
Port uint16 `yaml:"port"`
Expand All @@ -25,6 +26,7 @@ var (
)

const (
debugKey = "DEBUG"
folderKey = "FOLDER"
hostKey = "HOST"
portKey = "PORT"
Expand All @@ -35,6 +37,7 @@ const (
)

const (
defaultDebug = false
defaultFolder = "/web"
defaultHost = ""
defaultPort = uint16(8080)
Expand All @@ -50,6 +53,7 @@ func init() {
}

func setDefaults() {
Get.Debug = defaultDebug
Get.Folder = defaultFolder
Get.Host = defaultHost
Get.Port = defaultPort
Expand Down Expand Up @@ -82,9 +86,21 @@ func Load(filename string) (err error) {
return validate()
}

// Log the current configuration.
func Log() {
// YAML marshalling should never error, but if it could, the result is that
// the contents of the configuration are not logged.
contents, _ := yaml.Marshal(&Get)

// Log the configuration.
fmt.Println("Using the following configuration:")
fmt.Println(string(contents))
}

// overrideWithEnvVars the default values and the configuration file values.
func overrideWithEnvVars() {
// Assign envvars, if set.
Get.Debug = envAsBool(debugKey, Get.Debug)
Get.Folder = envAsStr(folderKey, Get.Folder)
Get.Host = envAsStr(hostKey, Get.Host)
Get.Port = envAsUint16(portKey, Get.Port)
Expand Down
14 changes: 14 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"os"
"strconv"
"testing"

"gopkg.in/yaml.v2"
)

func TestLoad(t *testing.T) {
Expand Down Expand Up @@ -65,8 +67,17 @@ func TestLoad(t *testing.T) {
}(t)
}

func TestLog(t *testing.T) {
// Test whether YAML marshalling works, as that is the only error case.
if _, err := yaml.Marshal(&Get); nil != err {
t.Errorf("While testing YAML marshalling for config Log() got %v", err)
}
Log()
}

func TestOverrideWithEnvvars(t *testing.T) {
// Choose values that are different than defaults.
testDebug := true
testFolder := "/my/directory"
testHost := "apets.life"
testPort := uint16(666)
Expand All @@ -76,6 +87,7 @@ func TestOverrideWithEnvvars(t *testing.T) {
testURLPrefix := "/url/prefix"

// Set all environment variables with test values.
os.Setenv(debugKey, fmt.Sprintf("%t", testDebug))
os.Setenv(folderKey, testFolder)
os.Setenv(hostKey, testHost)
os.Setenv(portKey, strconv.Itoa(int(testPort)))
Expand Down Expand Up @@ -113,6 +125,7 @@ func TestOverrideWithEnvvars(t *testing.T) {
// Verify defaults.
setDefaults()
phase := "defaults"
equalBool(t, phase, debugKey, defaultDebug, Get.Debug)
equalStrings(t, phase, folderKey, defaultFolder, Get.Folder)
equalStrings(t, phase, hostKey, defaultHost, Get.Host)
equalUint16(t, phase, portKey, defaultPort, Get.Port)
Expand All @@ -126,6 +139,7 @@ func TestOverrideWithEnvvars(t *testing.T) {

// Verify overrides.
phase = "overrides"
equalBool(t, phase, debugKey, testDebug, Get.Debug)
equalStrings(t, phase, folderKey, testFolder, Get.Folder)
equalStrings(t, phase, hostKey, testHost, Get.Host)
equalUint16(t, phase, portKey, testPort, Get.Port)
Expand Down
29 changes: 25 additions & 4 deletions handle/handle.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handle

import (
"log"
"net/http"
"strings"
)
Expand All @@ -21,23 +22,43 @@ var (
// occur.
type ListenerFunc func(string, http.HandlerFunc) error

// FileServerFunc is used to serve the file from the local file system to the
// requesting client.
type FileServerFunc func(http.ResponseWriter, *http.Request, string)

// WithLogging returns a function that logs information about the request prior
// to serving the requested file.
func WithLogging(serveFile FileServerFunc) FileServerFunc {
return func(w http.ResponseWriter, r *http.Request, name string) {
log.Printf(
"REQ: %s %s %s%s -> %s\n",
r.Method,
r.Proto,
r.Host,
r.URL.Path,
name,
)
serveFile(w, r, name)
}
}

// Basic file handler servers files from the passed folder.
func Basic(folder string) http.HandlerFunc {
func Basic(serveFile FileServerFunc, folder string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, folder+r.URL.Path)
serveFile(w, r, folder+r.URL.Path)
}
}

// Prefix file handler is an alternative to Basic where a URL prefix is removed
// prior to serving a file (http://my.machine/prefix/file.txt will serve
// file.txt from the root of the folder being served (ignoring 'prefix')).
func Prefix(folder, urlPrefix string) http.HandlerFunc {
func Prefix(serveFile FileServerFunc, folder, urlPrefix string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(r.URL.Path, urlPrefix) {
http.NotFound(w, r)
return
}
http.ServeFile(w, r, folder+strings.TrimPrefix(r.URL.Path, urlPrefix))
serveFile(w, r, folder+strings.TrimPrefix(r.URL.Path, urlPrefix))
}
}

Expand Down
Loading

0 comments on commit f2f41ef

Please sign in to comment.