Make ResponseWriter an interface
This commit is contained in:
parent
5ef5824d6f
commit
f6824bd813
@ -54,7 +54,7 @@ func fingerprint(cert *x509.Certificate) string {
|
|||||||
return string(b[:])
|
return string(b[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func profile(w *gemini.ResponseWriter, r *gemini.Request) {
|
func profile(w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
if r.Certificate == nil {
|
if r.Certificate == nil {
|
||||||
w.Status(gemini.StatusCertificateRequired)
|
w.Status(gemini.StatusCertificateRequired)
|
||||||
return
|
return
|
||||||
@ -69,7 +69,7 @@ func profile(w *gemini.ResponseWriter, r *gemini.Request) {
|
|||||||
fmt.Fprintln(w, "=> /username Change username")
|
fmt.Fprintln(w, "=> /username Change username")
|
||||||
}
|
}
|
||||||
|
|
||||||
func changeUsername(w *gemini.ResponseWriter, r *gemini.Request) {
|
func changeUsername(w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
if r.Certificate == nil {
|
if r.Certificate == nil {
|
||||||
w.Status(gemini.StatusCertificateRequired)
|
w.Status(gemini.StatusCertificateRequired)
|
||||||
return
|
return
|
||||||
|
@ -38,7 +38,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// stream writes an infinite stream to w.
|
// stream writes an infinite stream to w.
|
||||||
func stream(w *gemini.ResponseWriter, r *gemini.Request) {
|
func stream(w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
ch := make(chan string)
|
ch := make(chan string)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
4
fs.go
4
fs.go
@ -26,7 +26,7 @@ type fsHandler struct {
|
|||||||
FS
|
FS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fsh fsHandler) ServeGemini(w *ResponseWriter, r *Request) {
|
func (fsh fsHandler) ServeGemini(w ResponseWriter, r *Request) {
|
||||||
p := path.Clean(r.URL.Path)
|
p := path.Clean(r.URL.Path)
|
||||||
f, err := fsh.Open(p)
|
f, err := fsh.Open(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -73,7 +73,7 @@ func (d Dir) Open(name string) (File, error) {
|
|||||||
// or directory.
|
// or directory.
|
||||||
//
|
//
|
||||||
// TODO: Use io/fs.FS when available.
|
// TODO: Use io/fs.FS when available.
|
||||||
func ServeFile(w *ResponseWriter, fs FS, name string) {
|
func ServeFile(w ResponseWriter, fs FS, name string) {
|
||||||
f, err := fs.Open(name)
|
f, err := fs.Open(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Status(StatusNotFound)
|
w.Status(StatusNotFound)
|
||||||
|
4
mux.go
4
mux.go
@ -132,7 +132,7 @@ func (mux *ServeMux) shouldRedirectRLocked(path string) bool {
|
|||||||
|
|
||||||
// ServeGemini dispatches the request to the handler whose
|
// ServeGemini dispatches the request to the handler whose
|
||||||
// pattern most closely matches the request URL.
|
// pattern most closely matches the request URL.
|
||||||
func (mux *ServeMux) ServeGemini(w *ResponseWriter, r *Request) {
|
func (mux *ServeMux) ServeGemini(w ResponseWriter, r *Request) {
|
||||||
path := cleanPath(r.URL.Path)
|
path := cleanPath(r.URL.Path)
|
||||||
|
|
||||||
// If the given path is /tree and its handler is not registered,
|
// If the given path is /tree and its handler is not registered,
|
||||||
@ -202,7 +202,7 @@ func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleFunc registers the handler function for the given pattern.
|
// HandleFunc registers the handler function for the given pattern.
|
||||||
func (mux *ServeMux) HandleFunc(pattern string, handler func(*ResponseWriter, *Request)) {
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
panic("gemini: nil responder")
|
panic("gemini: nil responder")
|
||||||
}
|
}
|
||||||
|
69
response.go
69
response.go
@ -129,8 +129,39 @@ func (b *readCloserBody) Read(p []byte) (n int, err error) {
|
|||||||
return b.ReadCloser.Read(p)
|
return b.ReadCloser.Read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResponseWriter is used to construct a Gemini response.
|
// A ResponseWriter interface is used by a Gemini handler
|
||||||
type ResponseWriter struct {
|
// to construct a Gemini response.
|
||||||
|
type ResponseWriter interface {
|
||||||
|
// Header sets the response header.
|
||||||
|
Header(status int, meta string)
|
||||||
|
|
||||||
|
// Status sets the response status code.
|
||||||
|
// It also sets the response meta to Meta(status).
|
||||||
|
Status(status int)
|
||||||
|
|
||||||
|
// Meta sets the response meta.
|
||||||
|
//
|
||||||
|
// For successful responses, meta should contain the media type of the response.
|
||||||
|
// For failure responses, meta should contain a short description of the failure.
|
||||||
|
// The response meta should not be greater than 1024 bytes.
|
||||||
|
Meta(meta string)
|
||||||
|
|
||||||
|
// Write writes data to the connection as part of the response body.
|
||||||
|
// If the response status does not allow for a response body, Write returns
|
||||||
|
// ErrBodyNotAllowed.
|
||||||
|
//
|
||||||
|
// Write writes the response header if it has not already been written.
|
||||||
|
// It writes a successful status code if one is not set.
|
||||||
|
Write([]byte) (int, error)
|
||||||
|
|
||||||
|
// Flush writes any buffered data to the underlying io.Writer.
|
||||||
|
//
|
||||||
|
// Flush writes the response header if it has not already been written.
|
||||||
|
// It writes a failure status code if one is not set.
|
||||||
|
Flush() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type responseWriter struct {
|
||||||
b *bufio.Writer
|
b *bufio.Writer
|
||||||
status int
|
status int
|
||||||
meta string
|
meta string
|
||||||
@ -139,41 +170,27 @@ type ResponseWriter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewResponseWriter returns a ResponseWriter that uses the provided io.Writer.
|
// NewResponseWriter returns a ResponseWriter that uses the provided io.Writer.
|
||||||
func NewResponseWriter(w io.Writer) *ResponseWriter {
|
func NewResponseWriter(w io.Writer) ResponseWriter {
|
||||||
return &ResponseWriter{
|
return &responseWriter{
|
||||||
b: bufio.NewWriter(w),
|
b: bufio.NewWriter(w),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header sets the response header.
|
func (w *responseWriter) Header(status int, meta string) {
|
||||||
func (w *ResponseWriter) Header(status int, meta string) {
|
|
||||||
w.status = status
|
w.status = status
|
||||||
w.meta = meta
|
w.meta = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status sets the response status code.
|
func (w *responseWriter) Status(status int) {
|
||||||
// It also sets the response meta to Meta(status).
|
|
||||||
func (w *ResponseWriter) Status(status int) {
|
|
||||||
w.status = status
|
w.status = status
|
||||||
w.meta = Meta(status)
|
w.meta = Meta(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Meta sets the response meta.
|
func (w *responseWriter) Meta(meta string) {
|
||||||
//
|
|
||||||
// For successful responses, meta should contain the media type of the response.
|
|
||||||
// For failure responses, meta should contain a short description of the failure.
|
|
||||||
// The response meta should not be greater than 1024 bytes.
|
|
||||||
func (w *ResponseWriter) Meta(meta string) {
|
|
||||||
w.meta = meta
|
w.meta = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes data to the connection as part of the response body.
|
func (w *responseWriter) Write(b []byte) (int, error) {
|
||||||
// If the response status does not allow for a response body, Write returns
|
|
||||||
// ErrBodyNotAllowed.
|
|
||||||
//
|
|
||||||
// Write writes the response header if it has not already been written.
|
|
||||||
// It writes a successful status code if one is not set.
|
|
||||||
func (w *ResponseWriter) Write(b []byte) (int, error) {
|
|
||||||
if !w.wroteHeader {
|
if !w.wroteHeader {
|
||||||
w.writeHeader(StatusSuccess)
|
w.writeHeader(StatusSuccess)
|
||||||
}
|
}
|
||||||
@ -183,7 +200,7 @@ func (w *ResponseWriter) Write(b []byte) (int, error) {
|
|||||||
return w.b.Write(b)
|
return w.b.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ResponseWriter) writeHeader(defaultStatus int) {
|
func (w *responseWriter) writeHeader(defaultStatus int) {
|
||||||
status := w.status
|
status := w.status
|
||||||
if status == 0 {
|
if status == 0 {
|
||||||
status = defaultStatus
|
status = defaultStatus
|
||||||
@ -205,11 +222,7 @@ func (w *ResponseWriter) writeHeader(defaultStatus int) {
|
|||||||
w.wroteHeader = true
|
w.wroteHeader = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush writes any buffered data to the underlying io.Writer.
|
func (w *responseWriter) Flush() error {
|
||||||
//
|
|
||||||
// Flush writes the response header if it has not already been written.
|
|
||||||
// It writes a failure status code if one is not set.
|
|
||||||
func (w *ResponseWriter) Flush() error {
|
|
||||||
if !w.wroteHeader {
|
if !w.wroteHeader {
|
||||||
w.writeHeader(StatusTemporaryFailure)
|
w.writeHeader(StatusTemporaryFailure)
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func (s *Server) Handle(pattern string, handler Handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleFunc registers the handler function for the given pattern.
|
// HandleFunc registers the handler function for the given pattern.
|
||||||
func (s *Server) HandleFunc(pattern string, handler func(*ResponseWriter, *Request)) {
|
func (s *Server) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
||||||
s.Handle(pattern, HandlerFunc(handler))
|
s.Handle(pattern, HandlerFunc(handler))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,15 +258,15 @@ func (s *Server) logf(format string, args ...interface{}) {
|
|||||||
// ServeGemini should write the response header and data to the ResponseWriter
|
// ServeGemini should write the response header and data to the ResponseWriter
|
||||||
// and then return.
|
// and then return.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
ServeGemini(*ResponseWriter, *Request)
|
ServeGemini(ResponseWriter, *Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
||||||
// as Gemini handlers. If f is a function with the appropriate signature,
|
// as Gemini handlers. If f is a function with the appropriate signature,
|
||||||
// HandlerFunc(f) is a Handler that calls f.
|
// HandlerFunc(f) is a Handler that calls f.
|
||||||
type HandlerFunc func(*ResponseWriter, *Request)
|
type HandlerFunc func(ResponseWriter, *Request)
|
||||||
|
|
||||||
// ServeGemini calls f(w, r).
|
// ServeGemini calls f(w, r).
|
||||||
func (f HandlerFunc) ServeGemini(w *ResponseWriter, r *Request) {
|
func (f HandlerFunc) ServeGemini(w ResponseWriter, r *Request) {
|
||||||
f(w, r)
|
f(w, r)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user