package http import "io" import "fmt" import "bytes" import "net/http" // Error represents an HTTP error. It is passed to error documents as data. // If returned from a template, the server will show the appropriate error page. type Error struct { Status int Message any } func (err Error) Error () string { message := fmt.Sprint(err.Message) text := http.StatusText(err.Status) if message == "" { return fmt.Sprintf("%d: %s", err.Status, text) } else { return fmt.Sprintf("%d: %s: %s", err.Status, text, message) } } // HTTPData represents information about an ongoing HTTP request that is made // available to templates as they are being executed. type HTTPData struct { // Res is like an http.ResponseWriter. Res WrappedResponseWriter // Req is the HTTP request. Req *http.Request } type WrappedResponseWriter struct { responseWriter http.ResponseWriter resetFunc func () Header WrappedHeader } func (this WrappedResponseWriter) WriteHeader (statusCode int) string { this.responseWriter.WriteHeader(statusCode) return "" } func (this WrappedResponseWriter) Reset () string { this.resetFunc() return "" } type WrappedHeader struct { http.Header } func (this WrappedHeader) Add (name, value string) string { this.Header.Add(name, value) return "" } func (this WrappedHeader) Del (name string) string { this.Header.Del(name) return "" } func (this WrappedHeader) Set (name, value string) string { this.Header.Set(name, value) return "" } var _ http.ResponseWriter = new(HTTPResponseRecorder) // HTTPResponseRecorder is an http.ResponseWriter that can buffer a response to // be played back later. type HTTPResponseRecorder struct { Status int Head http.Header buffer bytes.Buffer } func (this *HTTPResponseRecorder) Header () http.Header { if this.Head == nil { this.Head = make(http.Header) } return this.Head } func (this *HTTPResponseRecorder) Write (buffer []byte) (int, error) { return this.buffer.Write(buffer) } func (this *HTTPResponseRecorder) WriteHeader (statusCode int) { this.Status = statusCode } // Play replays the response to the given http.ResponseWriter. This resets the // recorder. func (this *HTTPResponseRecorder) Play (res http.ResponseWriter) error { defer this.Reset() status := this.Status if status == 0 { status = http.StatusOK } header := res.Header() for name, value := range this.Head { header[name] = value } res.WriteHeader(status) _, err := io.Copy(res, &this.buffer) return err } // Reset resets this response recorder so it can be used again. func (this *HTTPResponseRecorder) Reset () { this.buffer.Reset() this.Head = nil this.Status = http.StatusOK }