github.com/bitcubate/cryptojournal@v1.2.5-0.20171102134152-f578b3d788ab/src/app/handlers.go (about) 1 package app 2 3 import ( 4 "net/http" 5 "os" 6 "path" 7 "strings" 8 9 "github.com/fragmenta/server" 10 "github.com/fragmenta/server/config" 11 "github.com/fragmenta/server/log" 12 "github.com/fragmenta/view" 13 ) 14 15 // Serve static files (assets, images etc) 16 func fileHandler(w http.ResponseWriter, r *http.Request) error { 17 18 // First try serving assets 19 err := serveAsset(w, r) 20 if err == nil { 21 return nil 22 } 23 24 // If assets fail, try to serve file in public 25 return serveFile(w, r) 26 } 27 28 // serveFile serves a file from ./public if it exists 29 func serveFile(w http.ResponseWriter, r *http.Request) error { 30 31 // Try a local path in the public directory 32 localPath := "./public" + path.Clean(r.URL.Path) 33 s, err := os.Stat(localPath) 34 if err != nil { 35 // If file not found return 404 36 if os.IsNotExist(err) { 37 return server.NotFoundError(err) 38 } 39 40 // For other errors return not authorised 41 return server.NotAuthorizedError(err) 42 } 43 44 // If not a file return immediately 45 if s.IsDir() { 46 return nil 47 } 48 49 // If the file exists and we can access it, serve it with cache control 50 w.Header().Set("Cache-Control", "max-age:3456000, public") 51 http.ServeFile(w, r, localPath) 52 return nil 53 } 54 55 // serveAsset serves a file from ./public/assets usings appAssets 56 func serveAsset(w http.ResponseWriter, r *http.Request) error { 57 58 p := path.Clean(r.URL.Path) 59 60 // It must be under /assets, or we don't serve 61 if !strings.HasPrefix(p, "/assets/") { 62 return server.NotFoundError(nil) 63 } 64 65 // Try to find an asset in our list 66 f := appAssets.File(path.Base(p)) 67 if f == nil { 68 return server.NotFoundError(nil) 69 } 70 71 // Serve the local file, with cache control 72 localPath := "./" + f.LocalPath() 73 w.Header().Set("Cache-Control", "max-age:3456000, public") 74 http.ServeFile(w, r, localPath) 75 return nil 76 } 77 78 // errHandler renders an error using error templates if available 79 func errHandler(w http.ResponseWriter, r *http.Request, e error) { 80 81 // Cast the error to a status error if it is one, if not wrap it in a Status 500 error 82 err := server.ToStatusError(e) 83 log.Error(log.V{"error": err}) 84 85 view := view.NewWithPath("", w) 86 view.AddKey("title", err.Title) 87 view.AddKey("message", err.Message) 88 // In production, provide no detail for security reasons 89 if !config.Production() { 90 view.AddKey("status", err.Status) 91 view.AddKey("file", err.FileLine()) 92 view.AddKey("error", err.Err) 93 } 94 view.Template("app/views/error.html.got") 95 w.WriteHeader(err.Status) 96 view.Render() 97 }