summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHorus32015-05-09 01:57:32 +0200
committerHorus32015-05-09 01:57:32 +0200
commit9c757388f1974b32a2f88cf36b709a160491baf8 (patch)
tree5111934ab42db0f1beafd16ffea5fb04d9350478
parent5def3f17f1809eb3727efd21d4b482452620342b (diff)
downloaduhttpd-9c757388f1974b32a2f88cf36b709a160491baf8.tar.gz
Show pretty html pages.
-rw-r--r--main.go15
-rw-r--r--template.go176
2 files changed, 188 insertions, 3 deletions
diff --git a/main.go b/main.go
index 36781f2..9ec7157 100644
--- a/main.go
+++ b/main.go
@@ -11,11 +11,20 @@ import (
)
func accessLog(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ t := &TemplateHandler{handler: h}
+ //t := &TemplateHandler{}
+ fn := func(w http.ResponseWriter, r *http.Request) {
log.Println(r.Method, r.URL.Path, r.RemoteAddr)
- h.ServeHTTP(w, r)
- })
+ t.ServeHTTP(w, r)
+ }
+ return http.HandlerFunc(fn)
+}
+
+/*
+func TemplateHandler(h http.Handler) http.Handler {
+ h.handler
}
+*/
func uploadHandler(dir string) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
diff --git a/template.go b/template.go
new file mode 100644
index 0000000..c90b13c
--- /dev/null
+++ b/template.go
@@ -0,0 +1,176 @@
+package main
+
+import (
+ "html/template"
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+)
+
+type TemplateHandler struct {
+ handler http.Handler
+}
+
+func (t *TemplateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+
+ // We use our custom handler to prettify directories. Files are served via default.
+ if strings.HasSuffix(r.URL.Path, "/") {
+ r.Header.Del("If-Modified-Since")
+ rec := httptest.NewRecorder()
+
+ defer rec.Body.Reset()
+
+ // passing the recorder instead of the real ResponseWriter
+ t.handler.ServeHTTP(rec, r)
+
+ // we copy the original headers first
+ for k, v := range rec.Header() {
+ w.Header()[k] = v
+ }
+
+ // BUG: Sometimes we get a 0 byte response
+ if rec.Body.Len() == 0 {
+ log.Println("Error: Empty body. Requested:", r.URL.Path)
+ }
+
+ // we serve a file instead of a html page
+ if !strings.Contains(w.Header().Get("Content-Type"), "text/html") {
+ w.Write(rec.Body.Bytes())
+ return
+ }
+
+ data := rec.Body.String()
+
+ // we serve the directoy page
+ if strings.HasPrefix(data, "<pre>") {
+ execTemplate(w, r, data)
+ } else {
+ w.Write(rec.Body.Bytes())
+ }
+
+ return
+ } else {
+ t.handler.ServeHTTP(w, r)
+ }
+}
+
+func execTemplate(w http.ResponseWriter, r *http.Request, data string) {
+ data = strings.Replace(data, "<pre>", "", 1)
+ data = strings.Replace(data, "</pre>", "", 1)
+ data = strings.Replace(data, "</a>", "</a><br>", -1)
+ data = "<a class=\"dir\" href=\"..\">.. (up a dir)</a><br><br>" + data
+
+ tmpl := template.New("page")
+ tmpl, err := tmpl.Parse(renderTemplate())
+ if err != nil {
+ log.Println(err.Error())
+ w.WriteHeader(500)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ err = tmpl.Execute(w, struct {
+ Data template.HTML
+ URL string
+ }{Data: template.HTML(data), URL: r.URL.Path})
+ if err != nil {
+ log.Println(err)
+ }
+
+}
+
+func NewTemplateHandler(handler http.Handler, allowedHost string) *TemplateHandler {
+ return &TemplateHandler{handler: handler}
+}
+
+func renderTemplate() string {
+ html := `<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>{{.URL}}</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <style>
+ /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-moz-box-sizing:content-box;-webkit-box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}.container{position:relative;width:100%;max-width:960px;margin:0 auto;padding:0 20px;box-sizing:border-box}.column,.columns{width:100%;float:left;box-sizing:border-box}@media (min-width:400px){.container{width:85%;padding:0}}@media (min-width:550px){.container{width:80%}.column,.columns{margin-left:4%}.column:first-child,.columns:first-child{margin-left:0}.one.column,.one.columns{width:4.66666666667%}.two.columns{width:13.3333333333%}.three.columns{width:22%}.four.columns{width:30.6666666667%}.five.columns{width:39.3333333333%}.six.columns{width:48%}.seven.columns{width:56.6666666667%}.eight.columns{width:65.3333333333%}.nine.columns{width:74%}.ten.columns{width:82.6666666667%}.eleven.columns{width:91.3333333333%}.twelve.columns{width:100%;margin-left:0}.one-third.column{width:30.6666666667%}.two-thirds.column{width:65.3333333333%}.one-half.column{width:48%}.offset-by-one.column,.offset-by-one.columns{margin-left:8.66666666667%}.offset-by-two.column,.offset-by-two.columns{margin-left:17.3333333333%}.offset-by-three.column,.offset-by-three.columns{margin-left:26%}.offset-by-four.column,.offset-by-four.columns{margin-left:34.6666666667%}.offset-by-five.column,.offset-by-five.columns{margin-left:43.3333333333%}.offset-by-six.column,.offset-by-six.columns{margin-left:52%}.offset-by-seven.column,.offset-by-seven.columns{margin-left:60.6666666667%}.offset-by-eight.column,.offset-by-eight.columns{margin-left:69.3333333333%}.offset-by-nine.column,.offset-by-nine.columns{margin-left:78%}.offset-by-ten.column,.offset-by-ten.columns{margin-left:86.6666666667%}.offset-by-eleven.column,.offset-by-eleven.columns{margin-left:95.3333333333%}.offset-by-one-third.column,.offset-by-one-third.columns{margin-left:34.6666666667%}.offset-by-two-thirds.column,.offset-by-two-thirds.columns{margin-left:69.3333333333%}.offset-by-one-half.column,.offset-by-one-half.columns{margin-left:52%}}html{font-size:62.5%}body{font-size:1.5em;line-height:1.6;font-weight:400;font-family:Raleway,HelveticaNeue,"Helvetica Neue",Helvetica,Arial,sans-serif;color:#222}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:2rem;font-weight:300}h1{font-size:4rem;line-height:1.2;letter-spacing:-.1rem}h2{font-size:3.6rem;line-height:1.25;letter-spacing:-.1rem}h3{font-size:3rem;line-height:1.3;letter-spacing:-.1rem}h4{font-size:2.4rem;line-height:1.35;letter-spacing:-.08rem}h5{font-size:1.8rem;line-height:1.5;letter-spacing:-.05rem}h6{font-size:1.5rem;line-height:1.6;letter-spacing:0}@media (min-width:550px){h1{font-size:5rem}h2{font-size:4.2rem}h3{font-size:3.6rem}h4{font-size:3rem}h5{font-size:2.4rem}h6{font-size:1.5rem}}p{margin-top:0}a{color:#1EAEDB}a:hover{color:#0FA0CE}.button,button,input[type=button],input[type=reset],input[type=submit]{display:inline-block;height:38px;padding:0 30px;color:#555;text-align:center;font-size:11px;font-weight:600;line-height:38px;letter-spacing:.1rem;text-transform:uppercase;text-decoration:none;white-space:nowrap;background-color:transparent;border-radius:4px;border:1px solid #bbb;cursor:pointer;box-sizing:border-box}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{color:#333;border-color:#888;outline:0}.button.button-primary,button.button-primary,input[type=button].button-primary,input[type=reset].button-primary,input[type=submit].button-primary{color:#FFF;background-color:#33C3F0;border-color:#33C3F0}.button.button-primary:focus,.button.button-primary:hover,button.button-primary:focus,button.button-primary:hover,input[type=button].button-primary:focus,input[type=button].button-primary:hover,input[type=reset].button-primary:focus,input[type=reset].button-primary:hover,input[type=submit].button-primary:focus,input[type=submit].button-primary:hover{color:#FFF;background-color:#1EAEDB;border-color:#1EAEDB}input[type=email],input[type=text],input[type=tel],input[type=url],input[type=password],input[type=number],input[type=search],select,textarea{height:38px;padding:6px 10px;background-color:#fff;border:1px solid #D1D1D1;border-radius:4px;box-shadow:none;box-sizing:border-box}input[type=email],input[type=text],input[type=tel],input[type=url],input[type=password],input[type=number],input[type=search],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none}textarea{min-height:65px;padding-top:6px;padding-bottom:6px}input[type=email]:focus,input[type=text]:focus,input[type=tel]:focus,input[type=url]:focus,input[type=password]:focus,input[type=number]:focus,input[type=search]:focus,select:focus,textarea:focus{border:1px solid #33C3F0;outline:0}label,legend{display:block;margin-bottom:.5rem;font-weight:600}fieldset{padding:0;border-width:0}input[type=checkbox],input[type=radio]{display:inline}label>.label-body{display:inline-block;margin-left:.5rem;font-weight:400}ul{list-style:none}ol{list-style:decimal inside}ol,ul{padding-left:0;margin-top:0}ol ol,ol ul,ul ol,ul ul{margin:1.5rem 0 1.5rem 3rem;font-size:90%}li{margin-bottom:1rem}code{padding:.2rem .5rem;margin:0 .2rem;font-size:90%;white-space:nowrap;background:#F1F1F1;border:1px solid #E1E1E1;border-radius:4px}pre>code{display:block;padding:1rem 1.5rem;white-space:pre}td,th{padding:12px 15px;text-align:left;border-bottom:1px solid #E1E1E1}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}.button,button{margin-bottom:1rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}.u-full-width{width:100%;box-sizing:border-box}.u-max-full-width{max-width:100%;box-sizing:border-box}.u-pull-right{float:right}.u-pull-left{float:left}hr{margin-top:3rem;margin-bottom:3.5rem;border-width:0;border-top:1px solid #E1E1E1}.container:after,.row:after,.u-cf{content:"";display:table;clear:both}.margin-top{margin-top:20px}.dir,.dir:hover{color: #000}.dir:hover{text-decoration:none}.dir:before{content: "> "}
+div.icon {
+ height: 32px;
+ width: 32px;
+ position: relative;
+ margin: 15px;
+ overflow: hidden;
+ display: inline-block;
+}
+div.icon div.home {
+ height: 0px;
+ width: 0px;
+ border-width: 16px;
+ border-style: solid;
+ border-color: transparent transparent #333 transparent;
+ position: absolute;
+ bottom: 16px;
+ left: 0;
+}
+
+div.icon div.home:after {
+ content: '';
+ width: 5px;
+ height: 16px;
+ background-color: transparent;
+ position: absolute;
+ top: 16px;
+ right: -11px;
+ border-left: 8px solid #333;
+ border-right: 8px solid #333;
+}
+
+div.icon div.home:before {
+ content: '';
+ width: 9px;
+ height: 6px;
+ background-color: #333;
+ position: absolute;
+ top: 16px;
+ right: -5px;
+}
+
+div.icon div.chimney {
+ width: 4px;
+ height: 10px;
+ background: #333;
+ position: absolute;
+ right: 6px;
+ top: 3px;
+}
+ </style>
+</head>
+<body>
+ <div class="container">
+ <div class="row">
+ <div class="column margin-top">
+ <a href="/.."><div class="icon"><div class="home"></div><div class="chimney"></div></div></a>
+ <h4>{{.URL}}</h4>
+ <blockquote>
+ {{.Data}}
+ </blockquote>
+ </div>
+ </div>
+ </div>
+<script>
+ String.prototype.endsWith = function(suffix) {
+ return this.indexOf(suffix, this.length - suffix.length) !== -1;
+ }
+ allAnchors = document.querySelectorAll("a");
+ for(i=0;i<allAnchors.length;i++){
+ if (allAnchors[i].getAttribute("href").endsWith("/")){
+ allAnchors[i].className = allAnchors[i].className + " dir";
+ }
+ allAnchors[i].className = allAnchors[i].className + " item";
+ }
+
+</script>
+</body>
+</html>`
+
+ return html
+}