1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| type custom_error struct { content string time time.Time position string }
type userError string
func (r userError) Error() string { return r.Message() } func (r userError) Message() string { return string(r)
}
func (e custom_error) Error() string { return fmt.Sprintf(" %s : %s", e.position, e.content) }
func judgeCustomErr(err error) bool { switch err.(type) { case custom_error: return true default: return false } }
const prefix = "/source/"
func fileHandler(writer http.ResponseWriter, request *http.Request) error { if strings.Index(request.URL.Path, prefix) != 0 { return userError("path must start with " + prefix) } path := request.URL.Path[len(prefix):] file, err := os.Open(path) if err != nil { return err } defer file.Close()
all, err := ioutil.ReadAll(file) if err != nil { return err }
writer.Write(all) return nil }
type appHandler func(writer http.ResponseWriter, request *http.Request) error
func errWraper(handler appHandler) func(writer http.ResponseWriter, request *http.Request) { return func(writer http.ResponseWriter, request *http.Request) { defer func() { if r := recover(); r != nil { log.Printf("process error: %v", r) http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }()
err := handler(writer, request) if err != nil { if userErr, ok := err.(userError); ok { http.Error(writer, userErr.Message(), http.StatusInternalServerError) }
code := http.StatusOK r, ok := err.(custom_error) log.Printf("err occured during handling open file: %s ", err.Error()) switch { case os.IsNotExist(err): code = http.StatusNotFound case os.IsPermission(err): code = http.StatusForbidden case ok: http.Error(writer, r.Error(), 500) default: code = http.StatusInternalServerError } if !judgeCustomErr(err) { http.Error(writer, http.StatusText(code), code) } } } }
func main(){
http.HandleFunc("/source/", errWraper(fileHandler))
err := http.ListenAndServe(":8888", nil) if err != nil { panic(err) } }
|