Compare commits
4 commits
Author | SHA1 | Date | |
---|---|---|---|
51b35036ab | |||
7881a55436 | |||
4eb5d68fbf | |||
d7ed5b1eae |
2 changed files with 63 additions and 2 deletions
37
http/sse.go
Normal file
37
http/sse.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package webutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWriterNotFlushable = errors.New("response writer not flushable")
|
||||
)
|
||||
|
||||
// SseWriter provides a simple implementation for sending data via Server Side Events
|
||||
// to the client. The function runs until the dataStream channel is closed.
|
||||
// The ResponseWriter must not be used after calling this function
|
||||
//
|
||||
// Inspired by and partially copied from https://medium.com/@rian.eka.cahya/server-sent-event-sse-with-go-10592d9c2aa1
|
||||
func SseWriter(w http.ResponseWriter, dataStream chan []byte) error {
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Content-Type")
|
||||
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
return ErrWriterNotFlushable
|
||||
}
|
||||
for data := range dataStream {
|
||||
_, err := fmt.Fprintf(w, "%s\n\n", string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flusher.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -45,7 +45,7 @@ func BuildLoggingMiddleware(
|
|||
}
|
||||
logger.Send()
|
||||
}),
|
||||
hlog.RemoteAddrHandler("ip"),
|
||||
RealIpAppenderMiddleware("ip"),
|
||||
hlog.UserAgentHandler("user_agent"),
|
||||
hlog.RefererHandler("referer"),
|
||||
hlog.RequestIDHandler("req_id", "Request-Id"),
|
||||
|
@ -68,9 +68,33 @@ func LoggingMiddleware(handler http.Handler) http.Handler {
|
|||
Dur("duration", duration).
|
||||
Send()
|
||||
}),
|
||||
hlog.RemoteAddrHandler("ip"),
|
||||
RealIpAppenderMiddleware("ip"),
|
||||
hlog.UserAgentHandler("user_agent"),
|
||||
hlog.RefererHandler("referer"),
|
||||
hlog.RequestIDHandler("req_id", "Request-Id"),
|
||||
)
|
||||
}
|
||||
|
||||
// hlog.RemoteAddrHandler except fixed to check the X-Real-Ip and X-Forwarded-For
|
||||
// headers first for the IP instead of relying on RemoteAddr
|
||||
// (which would only return the last proxy's address instead of the caller's)
|
||||
func RealIpAppenderMiddleware(fieldKey string) func(handler http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
IPAddress := r.Header.Get("X-Real-Ip")
|
||||
if IPAddress == "" {
|
||||
IPAddress = r.Header.Get("X-Forwarded-For")
|
||||
}
|
||||
if IPAddress == "" {
|
||||
IPAddress = r.RemoteAddr
|
||||
}
|
||||
if IPAddress != "" {
|
||||
log := zerolog.Ctx(r.Context())
|
||||
log.UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str(fieldKey, IPAddress)
|
||||
})
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue