diff options
| author | Horus3 | 2015-05-09 01:57:32 +0200 |
|---|---|---|
| committer | Horus3 | 2015-05-09 01:57:32 +0200 |
| commit | 9c757388f1974b32a2f88cf36b709a160491baf8 (patch) | |
| tree | 5111934ab42db0f1beafd16ffea5fb04d9350478 | |
| parent | 5def3f17f1809eb3727efd21d4b482452620342b (diff) | |
| download | uhttpd-9c757388f1974b32a2f88cf36b709a160491baf8.tar.gz | |
Show pretty html pages.
| -rw-r--r-- | main.go | 15 | ||||
| -rw-r--r-- | template.go | 176 |
2 files changed, 188 insertions, 3 deletions
@@ -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 +} |
