[tor-commits] [check/master] Buffer template rendering.

arlo at torproject.org arlo at torproject.org
Thu Oct 3 18:48:28 UTC 2013


commit 8652915e57f200c60cdbf8082f04e5d96448e616
Author: Arlo Breault <arlolra at gmail.com>
Date:   Thu Oct 3 11:46:53 2013 -0700

    Buffer template rendering.
    
    This allows for better error handling and a place to deal with HEAD
    requests.
---
 check.go              |    4 ++--
 handlers.go           |   55 ++++++++++++++++++++++++++++++++++---------------
 public/torbutton.html |    2 +-
 utils.go              |    6 ------
 4 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/check.go b/check.go
index 3354e69..3cdc989 100644
--- a/check.go
+++ b/check.go
@@ -45,8 +45,8 @@ func main() {
 	Phttp.Handle("/", files)
 
 	// routes
-	http.HandleFunc("/", RootHandler(CompileTemplate(domain, "index.html"), exits, Phttp))
-	bulk := BulkHandler(CompileTemplate(domain, "bulk.html"), exits)
+	http.HandleFunc("/", RootHandler(CompileTemplate(domain, "index.html"), exits, domain, Phttp))
+	bulk := BulkHandler(CompileTemplate(domain, "bulk.html"), exits, domain)
 	http.HandleFunc("/torbulkexitlist", bulk)
 	http.HandleFunc("/cgi-bin/TorBulkExitList.py", bulk)
 
diff --git a/handlers.go b/handlers.go
index cef330d..cd8e815 100644
--- a/handlers.go
+++ b/handlers.go
@@ -1,11 +1,15 @@
 package main
 
 import (
+	"bytes"
 	"fmt"
+	"github.com/samuel/go-gettext/gettext"
 	"html/template"
+	"io"
 	"log"
 	"net"
 	"net/http"
+	"strconv"
 	"time"
 )
 
@@ -24,7 +28,7 @@ type Page struct {
 	Locales     map[string]string
 }
 
-func RootHandler(Layout *template.Template, Exits *Exits, Phttp *http.ServeMux) func(http.ResponseWriter, *http.Request) {
+func RootHandler(Layout *template.Template, Exits *Exits, domain *gettext.Domain, Phttp *http.ServeMux) http.HandlerFunc {
 
 	return func(w http.ResponseWriter, r *http.Request) {
 
@@ -34,17 +38,18 @@ func RootHandler(Layout *template.Template, Exits *Exits, Phttp *http.ServeMux)
 			return
 		}
 
+		var (
+			err         error
+			isTor       bool
+			fingerprint string
+		)
+
 		// get remote ip
 		host := r.Header.Get("X-Forwarded-For")
-		var err error
 		if len(host) == 0 {
 			host, _, err = net.SplitHostPort(r.RemoteAddr)
 		}
 
-		var (
-			isTor       bool
-			fingerprint string
-		)
 		// determine if we're in Tor
 		if err != nil {
 			isTor = false
@@ -54,9 +59,7 @@ func RootHandler(Layout *template.Template, Exits *Exits, Phttp *http.ServeMux)
 
 		// short circuit for torbutton
 		if len(r.URL.Query().Get("TorButton")) > 0 {
-			if err := Layout.ExecuteTemplate(w, "torbutton.html", isTor); err != nil && NotHeadErr(err) {
-				log.Printf("Layout.ExecuteTemplate: %v", err)
-			}
+			WriteHTMLBuf(w, r, Layout, domain, "torbutton.html", Page{IsTor: isTor})
 			return
 		}
 
@@ -95,24 +98,19 @@ func RootHandler(Layout *template.Template, Exits *Exits, Phttp *http.ServeMux)
 		}
 
 		// render the template
-		if err := Layout.ExecuteTemplate(w, "index.html", p); err != nil && NotHeadErr(err) {
-			log.Printf("Layout.ExecuteTemplate: %v", err)
-		}
-
+		WriteHTMLBuf(w, r, Layout, domain, "index.html", p)
 	}
 
 }
 
-func BulkHandler(Layout *template.Template, Exits *Exits) func(http.ResponseWriter, *http.Request) {
+func BulkHandler(Layout *template.Template, Exits *Exits, domain *gettext.Domain) http.HandlerFunc {
 
 	return func(w http.ResponseWriter, r *http.Request) {
 		q := r.URL.Query()
 
 		ip := q.Get("ip")
 		if net.ParseIP(ip) == nil {
-			if err := Layout.ExecuteTemplate(w, "bulk.html", nil); err != nil && NotHeadErr(err) {
-				log.Printf("Layout.ExecuteTemplate: %v", err)
-			}
+			WriteHTMLBuf(w, r, Layout, domain, "bulk.html", Page{})
 			return
 		}
 
@@ -128,3 +126,26 @@ func BulkHandler(Layout *template.Template, Exits *Exits) func(http.ResponseWrit
 	}
 
 }
+
+func WriteHTMLBuf(w http.ResponseWriter, r *http.Request, Layout *template.Template, domain *gettext.Domain, tmp string, p Page) {
+	buf := new(bytes.Buffer)
+
+	// render template
+	if err := Layout.ExecuteTemplate(buf, tmp, p); err != nil {
+		log.Printf("Layout.ExecuteTemplate: %v", err)
+		http.Error(w, domain.GetText(p.Lang, "Sorry, your query failed or an unexpected response was received."), http.StatusInternalServerError)
+		return
+	}
+
+	// set some headers
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	if r.Method == "HEAD" {
+		w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
+		return
+	}
+
+	// write buf
+	if _, err := io.Copy(w, buf); err != nil {
+		log.Printf("io.Copy: %v", err)
+	}
+}
diff --git a/public/torbutton.html b/public/torbutton.html
index ef97d09..3369f50 100644
--- a/public/torbutton.html
+++ b/public/torbutton.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <html>
 <body>
-  <a id="TorCheckResult" target="{{ if . }}success{{ else }}fail{{ end }}" href="/"></a>
+  <a id="TorCheckResult" target="{{ if .IsTor }}success{{ else }}fail{{ end }}" href="/"></a>
 </body>
 </html>
\ No newline at end of file
diff --git a/utils.go b/utils.go
index d2ab661..9d2667b 100644
--- a/utils.go
+++ b/utils.go
@@ -12,7 +12,6 @@ import (
 	"net/url"
 	"os"
 	"strconv"
-	"strings"
 )
 
 func UpToDate(r *http.Request) bool {
@@ -49,11 +48,6 @@ func GetQS(q url.Values, param string, deflt int) (num int, str string) {
 	return
 }
 
-func NotHeadErr(err error) bool {
-	// should just be able to compare errors but executetemplate formats it
-	return !strings.Contains(err.Error(), http.ErrBodyNotAllowed.Error())
-}
-
 func FuncMap(domain *gettext.Domain) template.FuncMap {
 	return template.FuncMap{
 		"UnEscaped": func(x string) interface{} {



More information about the tor-commits mailing list