Ross Light avatar Ross Light committed f18d912

initial import

Comments (0)

Files changed (3)

+package webapp
+
+import (
+	"encoding/json"
+	"net/http"
+)
+
+// Content types
+const (
+	HTMLType = "text/html; charset=utf-8"
+	JSONType = "application/json; charset=utf-8"
+)
+
+// JSONResponse writes a JSON value to w, setting the Content-Type.
+func JSONResponse(w http.ResponseWriter, v interface{}) error {
+	w.Header().Set("Content-Type", JSONType)
+	return json.NewEncoder(w).Encode(v)
+}
+package webapp
+
+import (
+	"bytes"
+	"encoding/json"
+	"io"
+	"log"
+	"net/http"
+	"net/url"
+)
+
+// HTTP 404 error.
+type NotFound struct {
+	URL *url.URL
+}
+
+func (nf *NotFound) Error() string {
+	return "not found: " + nf.URL.Path
+}
+
+// A ResponseBuffer is a ResponseWriter that stores the data written to it in memory.  The zero value is an empty response.
+type ResponseBuffer struct {
+	bytes.Buffer
+	code   int
+	header http.Header
+	sent   http.Header
+}
+
+// StatusCode returns the status code sent with WriteHeader or 0 if WriteHeader has not been called.
+func (br *ResponseBuffer) StatusCode() int {
+	return br.code
+}
+
+// Size returns the number of bytes in the buffer.
+func (br *ResponseBuffer) Size() int64 {
+	return int64(br.Len())
+}
+
+// HeaderSent returns the headers that were sent when WriteHeader was called or nil if WriteHeader has not been called.
+func (br *ResponseBuffer) HeaderSent() http.Header {
+	return br.sent
+}
+
+// Copy sends br's data to another ResponseWriter.
+func (br *ResponseBuffer) Copy(w http.ResponseWriter) error {
+	for k, v := range br.sent {
+		w.Header()[k] = v
+	}
+	w.WriteHeader(br.code)
+	_, err := io.Copy(w, br)
+	return err
+}
+
+func (br *ResponseBuffer) Header() http.Header {
+	if br.header == nil {
+		br.header = make(http.Header)
+	}
+	return br.header
+}
+
+func (br *ResponseBuffer) WriteHeader(code int) {
+	if br.sent == nil {
+		br.code = code
+		br.sent = make(http.Header, len(br.header))
+		for k, v := range br.header {
+			v2 := make([]string, len(v))
+			copy(v2, v)
+			br.sent[k] = v2
+		}
+	}
+}
+
+func (br *ResponseBuffer) Write(p []byte) (int, error) {
+	br.WriteHeader(http.StatusOK)
+	return br.Buffer.Write(p)
+}
+
+// ResponseStats is a ResponseWriter that records statistics about a response.
+type ResponseStats struct {
+	w          http.ResponseWriter
+	statusCode int
+	size       int64
+}
+
+// NewResponseStats returns a new ResponseStats that writes to w.
+func NewResponseStats(w http.ResponseWriter) *ResponseStats {
+	return &ResponseStats{w: w}
+}
+
+// StatusCode returns the status code sent with WriteHeader or 0 if WriteHeader has not been called.
+func (r *ResponseStats) StatusCode() int {
+	return r.code
+}
+
+// Size returns the number of bytes written to the underlying ResponseWriter.
+func (r *ResponseStats) Size() int64 {
+	return r.size
+}
+
+func (r *ResponseStats) Header() http.Header {
+	return r.w.Header()
+}
+
+func (r *ResponseStats) WriteHeader(statusCode int) {
+	r.w.WriteHeader(statusCode)
+	r.statusCode = statusCode
+}
+
+func (r *ResponseStats) Write(p []byte) (n int, err error) {
+	if r.statusCode == 0 {
+		r.statusCode = http.StatusOK
+	}
+	n, err = r.w.Write(p)
+	r.size += int64(n)
+	return
+}
+
+// Logger logs all HTTP requests sent to an http.Handler.
+type Logger struct {
+	http.Handler
+}
+
+func (l Logger) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	method, path, remote := req.Method, req.URL.Path, req.RemoteAddr
+	stats := NewResponseStats(w)
+	l.Handler.ServeHTTP(stats, req)
+	log.Printf("%s %s %d %d %s", method, path, stats.StatusCode(), stats.Size(), remote)
+}
+package webapp
+
+import (
+	"fmt"
+	"github.com/gorilla/mux"
+	"html/template"
+)
+
+// AddFuncs adds the package's template functions.
+func AddFuncs(t *template.Template, router *mux.Router) {
+	t.Funcs(template.FuncMap{
+		"path": routePath(router),
+		"url":  routeURL(router),
+	})
+}
+
+// RoutePath returns a function suitable for a template that returns the path
+// for a route and its parameters.
+func RoutePath(router *mux.Router) func(string, ...interface{}) (template.URL, error) {
+	return func(name string, pairs ...interface{}) (template.URL, error) {
+		route := router.Get(name)
+		if route == nil {
+			return "", fmt.Errorf("path: no such route %q", name)
+		}
+		spairs := make([]string, len(pairs))
+		for i := range pairs {
+			spairs[i] = fmt.Sprint(pairs[i])
+		}
+		u, err := route.URLPath(spairs...)
+		return template.URL(u.Path), err
+	}
+}
+
+// RouteURL returns a function suitable for a template that returns the full URL
+// for a route and its parameters.
+func RouteURL(router *mux.Router) func(string, ...interface{}) (template.URL, error) {
+	return func(name string, pairs ...interface{}) (template.URL, error) {
+		route := router.Get(name)
+		if route == nil {
+			return "", fmt.Errorf("path: no such route %q", name)
+		}
+		spairs := make([]string, len(pairs))
+		for i := range pairs {
+			spairs[i] = fmt.Sprint(pairs[i])
+		}
+		u, err := route.URL(spairs...)
+		return template.URL(u.String()), err
+	}
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.