add access log
parent
0eea3e787c
commit
56a74a2767
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -17,9 +18,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -263,16 +266,23 @@ func pipe(a, b net.Conn) {
|
||||||
|
|
||||||
func (s *Server) Pre(foo http.HandlerFunc) http.HandlerFunc {
|
func (s *Server) Pre(foo http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
r, flush := withMeta(w, r)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
ctx, can := context.WithTimeout(r.Context(), time.Duration(config.GetTimeout()))
|
ctx, can := context.WithTimeout(r.Context(), time.Duration(config.GetTimeout()))
|
||||||
defer can()
|
defer can()
|
||||||
if err := s.limiter.Wait(ctx); err != nil {
|
if err := s.limiter.Wait(ctx); err != nil {
|
||||||
|
pushMeta(r, "explain", "limiter exceeded")
|
||||||
w.WriteHeader(http.StatusTooManyRequests)
|
w.WriteHeader(http.StatusTooManyRequests)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w, did := doCORS(w, r)
|
w, did := doCORS(w, r)
|
||||||
if did {
|
if did {
|
||||||
|
pushMeta(r, "explain", "did cors")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.auth.BOAuthZ {
|
if s.auth.BOAuthZ {
|
||||||
logb.Verbosef("doing boauthz for request to %s", r.URL.String())
|
logb.Verbosef("doing boauthz for request to %s", r.URL.String())
|
||||||
s.doBOAuthZ(foo)(w, r)
|
s.doBOAuthZ(foo)(w, r)
|
||||||
|
|
@ -285,11 +295,44 @@ func (s *Server) Pre(foo http.HandlerFunc) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withMeta(w http.ResponseWriter, r *http.Request) (*http.Request, func()) {
|
||||||
|
meta := map[string]string{
|
||||||
|
"ts": strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
"method": r.Method,
|
||||||
|
"url": r.URL.String(),
|
||||||
|
"id": uuid.New().String(),
|
||||||
|
}
|
||||||
|
w.Header().Set("meta-id", meta["id"])
|
||||||
|
ctx := r.Context()
|
||||||
|
ctx = context.WithValue(ctx, "meta", meta)
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
return r, func() {
|
||||||
|
b, err := json.Marshal(meta)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
log.Printf("[access] %s", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushMeta(r *http.Request, k, v string) {
|
||||||
|
got := r.Context().Value("meta")
|
||||||
|
if got == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
meta, ok := got.(map[string]string)
|
||||||
|
if !ok || meta == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
meta[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
s.Pre(s.Proxy)(w, r)
|
s.Pre(s.Proxy)(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
type corsResponseWriter struct {
|
type corsResponseWriter struct {
|
||||||
|
r *http.Request
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,21 +340,26 @@ func (cb corsResponseWriter) WriteHeader(code int) {
|
||||||
cb.Header().Set("Access-Control-Allow-Origin", "*")
|
cb.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
cb.Header().Set("Access-Control-Allow-Headers", "X-Auth-Token, content-type, Content-Type")
|
cb.Header().Set("Access-Control-Allow-Headers", "X-Auth-Token, content-type, Content-Type")
|
||||||
cb.ResponseWriter.WriteHeader(code)
|
cb.ResponseWriter.WriteHeader(code)
|
||||||
|
pushMeta(cb.r, "cors", "wrote headers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCORS(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, bool) {
|
func doCORS(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, bool) {
|
||||||
key := mapKey(r.Host)
|
key := mapKey(r.Host)
|
||||||
if !config.GetCORS(key) {
|
if !config.GetCORS(key) {
|
||||||
|
pushMeta(r, "do-cors", "not enabled for key")
|
||||||
return w, false
|
return w, false
|
||||||
}
|
}
|
||||||
|
pushMeta(r, "do-cors", "enabled for key")
|
||||||
return _doCORS(w, r)
|
return _doCORS(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _doCORS(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, bool) {
|
func _doCORS(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, bool) {
|
||||||
w2 := corsResponseWriter{ResponseWriter: w}
|
w2 := corsResponseWriter{r: r, ResponseWriter: w}
|
||||||
if r.Method != http.MethodOptions {
|
if r.Method != http.MethodOptions {
|
||||||
|
pushMeta(r, "-do-cors", "not options")
|
||||||
return w2, false
|
return w2, false
|
||||||
}
|
}
|
||||||
|
pushMeta(r, "-do-cors", "options")
|
||||||
w2.Header().Set("Content-Length", "0")
|
w2.Header().Set("Content-Length", "0")
|
||||||
w2.Header().Set("Content-Type", "text/plain")
|
w2.Header().Set("Content-Type", "text/plain")
|
||||||
w2.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, TRACE, PATCH, HEAD, DELETE")
|
w2.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, TRACE, PATCH, HEAD, DELETE")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue