Skip to content

Instantly share code, notes, and snippets.

@fractalbach
Last active August 3, 2018 23:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fractalbach/abd69ddc9f9b6f2b9ec821f97c1baa44 to your computer and use it in GitHub Desktop.
Save fractalbach/abd69ddc9f9b6f2b9ec821f97c1baa44 to your computer and use it in GitHub Desktop.
example go server where paths that have no extensions are directed to "/index.html"
package main
import (
"os"
"flag"
"fmt"
"log"
"net/http"
"path"
)
// HelpMessage is the extra information given when using flags -h or --help.
// it is prefixed to the automatically generated info by flag.PrintDefaults()
const HelpMessage = `
Example Server
USAGE:
exampleServer [options]
OPTIONS:
`
// Define the help messages for the OPTIONS. These are appeneded to
// HelpMessage when flag.PrintDefaults() is called.
const (
HelpAddress = "Host Address and Port for HTTP connections."
DefaultAddress = "localhost:8080"
)
var (
addr string
)
func init() {
flag.StringVar(&addr, "a", DefaultAddress, HelpAddress)
flag.Usage = func() {
fmt.Fprint(os.Stderr, HelpMessage)
flag.PrintDefaults()
}
}
func main() {
flag.Parse()
mux := http.NewServeMux()
mux.HandleFunc("/", handleFiles)
s := &http.Server{
Addr: (addr),
Handler: mux,
}
log.Printf("Listening and Serving on %v", (addr))
log.Fatal(s.ListenAndServe())
}
// handleFiles will serve the index page and all other files based on URL.
// This exposes all folder contents, and makes them accessible by filename.
// All incoming requests will be logged via the "logRequest" function.
func handleFiles(w http.ResponseWriter, r *http.Request) {
logRequest(r)
if r.Method != "GET" {
http.Error(w, http.StatusText(405), 405)
return
}
// removes trailing slash from the user input, for example of
// this, see https://golang.org/doc/articles/wiki/#tmp_3
target := path.Clean(r.URL.Path[1:])
// checks for an extention. If there is a no extention,
// path.Ext(path) returns an empty string, see
// https://golang.org/pkg/path/#Ext
// path.Join will add the paths together, adding another slash
// (/) only if it needs to. See
// https://golang.org/pkg/path/#Join
if path.Ext(target) == "" {
target = path.Join(target, "index.html")
}
// Check to see if the file exists or not. 404 if it does
// not, this prevents the file directory from being displayed
// if there is no index.html file present.
// https://golang.org/pkg/os/#IsNotExist
file, err := os.Stat(target)
if os.IsNotExist(err) {
http.Error(w, http.StatusText(404), 404)
return
}
// At this point, if the path is still pointing to a directory,
// then the index file does not exist. Show a fun message.
if file.IsDir() {
fmt.Fprint(w, "I don't wanna show you my files!")
return
}
// If there is an extention, keep it. Most likely it will be
// something like .js, .css, .json, or something else. Note
// that if http.ServeFile will automatically clear away
// "/index.html" from the url bar in your browser. See
// https://golang.org/pkg/net/http/#ServeFile
log.Println("serving file:", target)
http.ServeFile(w, r, target)
}
// logRequest prints out a useful message to the command line log,
// displaying information about the request that was just made to the server.
func logRequest(r *http.Request) {
log.Printf("(%v) %v %v %v", r.RemoteAddr, r.Proto, r.Method, r.URL)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment