github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/web/static.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package web 5 6 import ( 7 "net/http" 8 "path" 9 "path/filepath" 10 "strings" 11 12 "github.com/NYTimes/gziphandler" 13 14 "github.com/vnforks/kid/v5/mlog" 15 "github.com/vnforks/kid/v5/model" 16 "github.com/vnforks/kid/v5/utils" 17 "github.com/vnforks/kid/v5/utils/fileutils" 18 ) 19 20 var robotsTxt = []byte("User-agent: *\nDisallow: /\n") 21 22 func (w *Web) InitStatic() { 23 if *w.ConfigService.Config().ServiceSettings.WebserverMode != "disabled" { 24 if err := utils.UpdateAssetsSubpathFromConfig(w.ConfigService.Config()); err != nil { 25 mlog.Error("Failed to update assets subpath from config", mlog.Err(err)) 26 } 27 28 staticDir, _ := fileutils.FindDir(model.CLIENT_DIR) 29 mlog.Debug("Using client directory", mlog.String("clientDir", staticDir)) 30 31 subpath, _ := utils.GetSubpathFromConfig(w.ConfigService.Config()) 32 33 staticHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static"), http.FileServer(http.Dir(staticDir)))) 34 pluginHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static", "plugins"), http.FileServer(http.Dir(*w.ConfigService.Config().PluginSettings.ClientDirectory)))) 35 36 if *w.ConfigService.Config().ServiceSettings.WebserverMode == "gzip" { 37 staticHandler = gziphandler.GzipHandler(staticHandler) 38 pluginHandler = gziphandler.GzipHandler(pluginHandler) 39 } 40 41 w.MainRouter.PathPrefix("/static/plugins/").Handler(pluginHandler) 42 w.MainRouter.PathPrefix("/static/").Handler(staticHandler) 43 w.MainRouter.Handle("/robots.txt", http.HandlerFunc(robotsHandler)) 44 w.MainRouter.Handle("/unsupported_browser.js", http.HandlerFunc(unsupportedBrowserScriptHandler)) 45 w.MainRouter.Handle("/{anything:.*}", w.NewStaticHandler(root)).Methods("GET") 46 47 // When a subpath is defined, it's necessary to handle redirects without a 48 // trailing slash. We don't want to use StrictSlash on the w.MainRouter and affect 49 // all routes, just /subpath -> /subpath/. 50 w.MainRouter.HandleFunc("", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 51 r.URL.Path += "/" 52 http.Redirect(w, r, r.URL.String(), http.StatusFound) 53 })) 54 } 55 } 56 57 func root(c *Context, w http.ResponseWriter, r *http.Request) { 58 59 if !CheckClientCompatability(r.UserAgent()) { 60 renderUnsupportedBrowser(c.App, w, r) 61 return 62 } 63 64 if IsApiCall(c.App, r) { 65 Handle404(c.App, w, r) 66 return 67 } 68 69 w.Header().Set("Cache-Control", "no-cache, max-age=31556926, public") 70 71 staticDir, _ := fileutils.FindDir(model.CLIENT_DIR) 72 http.ServeFile(w, r, filepath.Join(staticDir, "root.html")) 73 } 74 75 func staticFilesHandler(handler http.Handler) http.Handler { 76 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 77 //wrap our ResponseWriter with our no-cache 404-handler 78 w = ¬FoundNoCacheResponseWriter{ResponseWriter: w} 79 80 w.Header().Set("Cache-Control", "max-age=31556926, public") 81 82 if strings.HasSuffix(r.URL.Path, "/") { 83 http.NotFound(w, r) 84 return 85 } 86 handler.ServeHTTP(w, r) 87 }) 88 } 89 90 type notFoundNoCacheResponseWriter struct { 91 http.ResponseWriter 92 } 93 94 func (w *notFoundNoCacheResponseWriter) WriteHeader(statusCode int) { 95 if statusCode == http.StatusNotFound { 96 // we have a 404, update our cache header first then fall through 97 w.Header().Set("Cache-Control", "no-cache, public") 98 } 99 w.ResponseWriter.WriteHeader(statusCode) 100 } 101 102 func robotsHandler(w http.ResponseWriter, r *http.Request) { 103 if strings.HasSuffix(r.URL.Path, "/") { 104 http.NotFound(w, r) 105 return 106 } 107 w.Write(robotsTxt) 108 } 109 110 func unsupportedBrowserScriptHandler(w http.ResponseWriter, r *http.Request) { 111 if strings.HasSuffix(r.URL.Path, "/") { 112 http.NotFound(w, r) 113 return 114 } 115 116 templatesDir, _ := fileutils.FindDir("templates") 117 http.ServeFile(w, r, filepath.Join(templatesDir, "unsupported_browser.js")) 118 }