step/http/http.go

127 lines
2.9 KiB
Go

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)
}
}
// Redirect, if returned from a template, will cause the server to redirect the
// client to the given location.
type Redirect struct {
Status int
Location string
}
func (err Redirect) Error () string {
return fmt.Sprintf (
"%d: %s: %s",
err.Status, http.StatusText(err.Status), err.Location)
}
// 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
}