server: use custom error page
This commit is contained in:
parent
dcb8094403
commit
3bfcf5794f
2 changed files with 49 additions and 23 deletions
|
|
@ -31,7 +31,8 @@ type Page interface {
|
||||||
func writePage(p Page, w http.ResponseWriter) {
|
func writePage(p Page, w http.ResponseWriter) {
|
||||||
t, err := template.ParseFS(staticFS, "static/templates/" + p.SourceFile())
|
t, err := template.ParseFS(staticFS, "static/templates/" + p.SourceFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, "Internal server error: " + err.Error(),
|
||||||
|
http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,6 +42,21 @@ func writePage(p Page, w http.ResponseWriter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrorPage struct {
|
||||||
|
Status string
|
||||||
|
Reason string
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeErrorPage(status, reason string) (p ErrorPage) {
|
||||||
|
p.Status = status
|
||||||
|
p.Reason = reason
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ErrorPage) SourceFile() string { return "error.html" }
|
||||||
|
func (p ErrorPage) Title() string { return "" }
|
||||||
|
func (p ErrorPage) Body() template.HTML { return template.HTML("") }
|
||||||
|
|
||||||
type IndexPage struct {
|
type IndexPage struct {
|
||||||
Showcase string
|
Showcase string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,16 @@ var artistPages map[string]map[string]ArtistPage
|
||||||
// mapping of artist names to album names to pages
|
// mapping of artist names to album names to pages
|
||||||
var albumPages map[string]map[string]AlbumPage
|
var albumPages map[string]map[string]AlbumPage
|
||||||
|
|
||||||
|
func httpErrorReason(w http.ResponseWriter, error int, reason string) {
|
||||||
|
errorName := fmt.Sprintf("%d %s", error, http.StatusText(error))
|
||||||
|
w.WriteHeader(error)
|
||||||
|
writePage(MakeErrorPage(errorName, reason), w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func httpError(w http.ResponseWriter, error int) {
|
||||||
|
httpErrorReason(w, error, "")
|
||||||
|
}
|
||||||
|
|
||||||
func doIndexPage(w http.ResponseWriter, req *http.Request) {
|
func doIndexPage(w http.ResponseWriter, req *http.Request) {
|
||||||
writePage(indexPage, w)
|
writePage(indexPage, w)
|
||||||
}
|
}
|
||||||
|
|
@ -64,13 +74,13 @@ func detectTextType(fileName string) string {
|
||||||
|
|
||||||
func serveStaticFiles(w http.ResponseWriter, req *http.Request) {
|
func serveStaticFiles(w http.ResponseWriter, req *http.Request) {
|
||||||
if strings.HasPrefix(req.RequestURI, "/static/templates/") {
|
if strings.HasPrefix(req.RequestURI, "/static/templates/") {
|
||||||
http.Error(w, "forbidden", http.StatusForbidden)
|
httpError(w, http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contents, err := staticFS.ReadFile(req.RequestURI[1:])
|
contents, err := staticFS.ReadFile(req.RequestURI[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,30 +96,31 @@ func serveStaticFiles(w http.ResponseWriter, req *http.Request) {
|
||||||
func serveMediaDirectory(w http.ResponseWriter, req *http.Request) {
|
func serveMediaDirectory(w http.ResponseWriter, req *http.Request) {
|
||||||
path, err := url.QueryUnescape("/" + strings.SplitN(req.RequestURI[1:], "/", 2)[1])
|
path, err := url.QueryUnescape("/" + strings.SplitN(req.RequestURI[1:], "/", 2)[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := musicindex.MediaDirectory() + path
|
filePath := musicindex.MediaDirectory() + path
|
||||||
|
|
||||||
if strings.Contains(path, "/..") || strings.Contains(path, "/.") {
|
if strings.Contains(path, "/../") || strings.Contains(path, "/./") {
|
||||||
http.Error(w, "forbidden", http.StatusForbidden)
|
httpError(w, http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stat, err := os.Stat(filePath)
|
stat, err := os.Stat(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
http.Error(w, "is a directory; maybe you are looking for " + path, http.StatusForbidden)
|
httpErrorReason(w, http.StatusForbidden,
|
||||||
|
"is a directory; maybe you are looking for " + path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(filePath)
|
f, err := os.Open(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
@ -120,14 +131,14 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
// test artist
|
// test artist
|
||||||
rx, err := regexp.Compile("^/([^/?]+)/?(\\?.*)?$")
|
rx, err := regexp.Compile("^/([^/?]+)/?(\\?.*)?$")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
httpError(w, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx.MatchString(req.RequestURI)) {
|
if (rx.MatchString(req.RequestURI)) {
|
||||||
artist, err := url.QueryUnescape(rx.FindStringSubmatch(req.RequestURI)[1])
|
artist, err := url.QueryUnescape(rx.FindStringSubmatch(req.RequestURI)[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if musicindex.ArtistExists(artist) {
|
if musicindex.ArtistExists(artist) {
|
||||||
|
|
@ -142,14 +153,14 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// artist not found
|
// artist not found
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// test album tarball
|
// test album tarball
|
||||||
rx, err = regexp.Compile("^/([^/?]+)/([^/?]+)\\.tar\\.gz$")
|
rx, err = regexp.Compile("^/([^/?]+)/([^/?]+)\\.tar\\.gz$")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
httpError(w, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,12 +168,12 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
captures := rx.FindStringSubmatch(req.RequestURI)
|
captures := rx.FindStringSubmatch(req.RequestURI)
|
||||||
artist, err := url.QueryUnescape(captures[1])
|
artist, err := url.QueryUnescape(captures[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
albumName, err := url.QueryUnescape(captures[2])
|
albumName, err := url.QueryUnescape(captures[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,8 +182,7 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
if ok {
|
if ok {
|
||||||
f, err := os.Open(album.Tarball)
|
f, err := os.Open(album.Tarball)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "internal server error: " + err.Error(),
|
httpErrorReason(w, http.StatusInternalServerError, err.Error())
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
@ -187,14 +197,14 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// artist or album not found
|
// artist or album not found
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// test album
|
// test album
|
||||||
rx, err = regexp.Compile("^/([^/?]+)/([^/?]+)/?(\\?.*)?$")
|
rx, err = regexp.Compile("^/([^/?]+)/([^/?]+)/?(\\?.*)?$")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
httpErrorReason(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,12 +212,12 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
captures := rx.FindStringSubmatch(req.RequestURI)
|
captures := rx.FindStringSubmatch(req.RequestURI)
|
||||||
artist, err := url.QueryUnescape(captures[1])
|
artist, err := url.QueryUnescape(captures[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
albumName, err := url.QueryUnescape(captures[2])
|
albumName, err := url.QueryUnescape(captures[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "bad request", http.StatusBadRequest)
|
httpError(w, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,12 +230,12 @@ func handleArtistAlbumPage(w http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// artist or album not found
|
// artist or album not found
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// illegal URI format
|
// illegal URI format
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
httpError(w, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunOn(address string) {
|
func RunOn(address string) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue