mirror of
https://github.com/binwiederhier/ntfy.git
synced 2024-11-23 11:49:19 +01:00
Custom HTTP response writer
This commit is contained in:
parent
7fb6f794e5
commit
db1a1fec0c
2 changed files with 58 additions and 0 deletions
|
@ -291,6 +291,7 @@ func (s *Server) closeDatabases() {
|
||||||
|
|
||||||
// handle is the main entry point for all HTTP requests
|
// handle is the main entry point for all HTTP requests
|
||||||
func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w = newHTTPResponseWriter(w) // Avoid logging "superfluous response.WriteHeader call" warning
|
||||||
v, err := s.maybeAuthenticate(r) // Note: Always returns v, even when error is returned
|
v, err := s.maybeAuthenticate(r) // Note: Always returns v, even when error is returned
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.handleError(w, r, v, err)
|
s.handleError(w, r, v, err)
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"heckel.io/ntfy/util"
|
"heckel.io/ntfy/util"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readBoolParam(r *http.Request, defaultValue bool, names ...string) bool {
|
func readBoolParam(r *http.Request, defaultValue bool, names ...string) bool {
|
||||||
|
@ -85,3 +88,57 @@ func readJSONWithLimit[T any](r io.ReadCloser, limit int, allowEmpty bool) (*T,
|
||||||
}
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type httpResponseWriter struct {
|
||||||
|
w http.ResponseWriter
|
||||||
|
headerWritten bool
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpResponseWriterWithHijacker struct {
|
||||||
|
httpResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ http.ResponseWriter = (*httpResponseWriter)(nil)
|
||||||
|
var _ http.Flusher = (*httpResponseWriter)(nil)
|
||||||
|
var _ http.Hijacker = (*httpResponseWriterWithHijacker)(nil)
|
||||||
|
|
||||||
|
func newHTTPResponseWriter(w http.ResponseWriter) http.ResponseWriter {
|
||||||
|
if _, ok := w.(http.Hijacker); ok {
|
||||||
|
return &httpResponseWriterWithHijacker{httpResponseWriter: httpResponseWriter{w: w}}
|
||||||
|
}
|
||||||
|
return &httpResponseWriter{w: w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *httpResponseWriter) Header() http.Header {
|
||||||
|
return w.w.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *httpResponseWriter) Write(bytes []byte) (int, error) {
|
||||||
|
w.mu.Lock()
|
||||||
|
w.headerWritten = true
|
||||||
|
w.mu.Unlock()
|
||||||
|
return w.w.Write(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *httpResponseWriter) WriteHeader(statusCode int) {
|
||||||
|
w.mu.Lock()
|
||||||
|
if w.headerWritten {
|
||||||
|
w.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.headerWritten = true
|
||||||
|
w.mu.Unlock()
|
||||||
|
w.w.WriteHeader(statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *httpResponseWriter) Flush() {
|
||||||
|
if f, ok := w.w.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *httpResponseWriterWithHijacker) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
h, _ := w.w.(http.Hijacker)
|
||||||
|
return h.Hijack()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue