Skip to content

Instantly share code, notes, and snippets.

@technoweenie
Last active December 14, 2015 22:19
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 technoweenie/5157569 to your computer and use it in GitHub Desktop.
Save technoweenie/5157569 to your computer and use it in GitHub Desktop.
really crappy implementation of the ruby Heel gem in Go. Serve your local files over HTTP
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
)
func main() {
pwd, _ := os.Getwd()
http.HandleFunc("/", indexHandler(pwd))
log.Fatal(http.ListenAndServe(":8080", nil))
}
func indexHandler(pwd string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" && r.Method != "HEAD" {
w.WriteHeader(http.StatusNotAcceptable)
fmt.Fprint(w, "Only GET/HEAD supported")
return
} else if len(r.URL.Path) == 1 {
renderDir(w, r, pwd)
return
}
checkPath(w, r, pwd, r.URL.Path[1:])
}
}
func checkPath(w http.ResponseWriter, r *http.Request, pwd string, path string) {
cleaned := filepath.Clean(path)
joined := filepath.Join(pwd, cleaned)
stat, err := os.Stat(joined)
if err != nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Error loading %s: %s", joined, err)
return
}
if stat.IsDir() {
renderDir(w, r, joined)
} else {
renderFile(w, r, stat, joined)
}
}
func renderDir(w http.ResponseWriter, r *http.Request, pwd string) {
fmt.Fprintf(w, "%s\n\n", r.URL.Path)
files, _ := ioutil.ReadDir(pwd)
fmt.Fprintf(w, "%s\n\n", pwd)
for _, file := range files {
fmt.Fprintf(w, "%s (%d)\n", file.Name(), file.Size())
}
}
func renderFile(w http.ResponseWriter, r *http.Request, stat os.FileInfo, path string) {
file, err := os.Open(path)
defer file.Close()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error loading %s: %s", path, err)
return
}
fileSize := stat.Size()
headers := w.Header()
headers.Set("Content-Type", "application/octet-stream")
headers.Set("Content-Length", fmt.Sprintf("%d", fileSize))
if r.Method == "HEAD" {
w.WriteHeader(http.StatusOK)
return
} else {
io.CopyN(w, file, fileSize)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment