89 lines
2.1 KiB
Go
89 lines
2.1 KiB
Go
package httpd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
// ResponseWriter is an interface for writing a response.
|
|
type ResponseWriter interface {
|
|
// WriteResponse writes a response.
|
|
WriteResponse(resp Response) (int, error)
|
|
|
|
http.ResponseWriter
|
|
}
|
|
|
|
// NewResponseWriter creates a new ResponseWriter based on the Accept header
|
|
// in the request that wraps the ResponseWriter.
|
|
func NewResponseWriter(w http.ResponseWriter, r *http.Request) ResponseWriter {
|
|
pretty := r.URL.Query().Get("pretty") == "true"
|
|
rw := &responseWriter{ResponseWriter: w}
|
|
switch r.Header.Get("Accept") {
|
|
case "application/json":
|
|
fallthrough
|
|
default:
|
|
w.Header().Add("Content-Type", "application/json")
|
|
rw.formatter = &jsonFormatter{Pretty: pretty, Writer: w}
|
|
}
|
|
return rw
|
|
}
|
|
|
|
// WriteError is a convenience function for writing an error response to the ResponseWriter.
|
|
func WriteError(w ResponseWriter, err error) (int, error) {
|
|
return w.WriteResponse(Response{Err: err})
|
|
}
|
|
|
|
// responseWriter is an implementation of ResponseWriter.
|
|
type responseWriter struct {
|
|
formatter interface {
|
|
WriteResponse(resp Response) (int, error)
|
|
}
|
|
http.ResponseWriter
|
|
}
|
|
|
|
// WriteResponse writes the response using the formatter.
|
|
func (w *responseWriter) WriteResponse(resp Response) (int, error) {
|
|
return w.formatter.WriteResponse(resp)
|
|
}
|
|
|
|
// Flush flushes the ResponseWriter if it has a Flush() method.
|
|
func (w *responseWriter) Flush() {
|
|
if w, ok := w.ResponseWriter.(http.Flusher); ok {
|
|
w.Flush()
|
|
}
|
|
}
|
|
|
|
// CloseNotify calls CloseNotify on the underlying http.ResponseWriter if it
|
|
// exists. Otherwise, it returns a nil channel that will never notify.
|
|
func (w *responseWriter) CloseNotify() <-chan bool {
|
|
if notifier, ok := w.ResponseWriter.(http.CloseNotifier); ok {
|
|
return notifier.CloseNotify()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type jsonFormatter struct {
|
|
io.Writer
|
|
Pretty bool
|
|
}
|
|
|
|
func (w *jsonFormatter) WriteResponse(resp Response) (n int, err error) {
|
|
var b []byte
|
|
if w.Pretty {
|
|
b, err = json.MarshalIndent(resp, "", " ")
|
|
} else {
|
|
b, err = json.Marshal(resp)
|
|
}
|
|
|
|
if err != nil {
|
|
n, err = io.WriteString(w, err.Error())
|
|
} else {
|
|
n, err = w.Write(b)
|
|
}
|
|
|
|
w.Write([]byte("\n"))
|
|
n++
|
|
return n, err
|
|
}
|