Last active
September 29, 2019 17:04
-
-
Save foxcpp/56135560de7feaadd9a0d6b07c57b1c9 to your computer and use it in GitHub Desktop.
Absolutely minimalistic webfs in Go
This file contains 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 ( | |
"errors" | |
"flag" | |
"log" | |
"net/http" | |
"os" | |
"path/filepath" | |
"strings" | |
) | |
// checkSymlink checks whether root/path doesn't contain symlinks that lead | |
// outside of the root directory. | |
func checkSymlink(root string, path string) error { | |
fullPath, err := filepath.EvalSymlinks(filepath.Join(root, path)) | |
if err != nil { | |
return err | |
} | |
if !filepath.HasPrefix(fullPath, root) { | |
return errors.New("symlink leads outside of the root directory") | |
} | |
return nil | |
} | |
func main() { | |
addr := flag.String("addr", ":8080", "Address port to use (ADDR:PORT)") | |
tlsCert := flag.String("tls.cert", "", "TLS certificate to use (optional)") | |
tlsKey := flag.String("tls.key", "", "TLS key to use (optional)") | |
dir := flag.String("dir", "", "Directory to server instead of PWD") | |
flag.Parse() | |
if *dir == "" { | |
pwd, err := os.Getwd() | |
if err != nil { | |
log.Fatalln(err) | |
} | |
dir = &pwd | |
} | |
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | |
file := filepath.Join(*dir, r.URL.Path) | |
log.Printf(`%s "%s %s %s"`, strings.Split(r.RemoteAddr, ":")[0], r.Method, r.URL, r.Proto) | |
if err := checkSymlink(*dir, r.URL.Path); err != nil { | |
w.WriteHeader(403) | |
w.Write([]byte(err.Error())) | |
return | |
} | |
http.ServeFile(w, r, file) | |
}) | |
if *tlsCert != "" && *tlsKey != "" { | |
log.Println("serving", *dir, "over", *addr, "with TLS") | |
if err := http.ListenAndServeTLS(*addr, *tlsCert, *tlsKey, nil); err != nil { | |
log.Fatalln(err) | |
} | |
return | |
} | |
log.Println("serving", *dir, "over", *addr) | |
if err := http.ListenAndServe(*addr, nil); err != nil { | |
log.Fatalln(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment