Last active
December 14, 2015 22:19
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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