Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 53 additions & 13 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ type ServerConfig struct {
RecoverPanic bool
Profiler bool
ColorOutput bool
FilterParams []string
}

var defaultConfig = ServerConfig{
RecoverPanic: true,
ColorOutput: true,
FilterParams: []string{"^password$", "^password_confirm.*$"},
}

// Server represents a web.go server.
Expand All @@ -37,14 +44,16 @@ type Server struct {
Logger *log.Logger
Env map[string]interface{}
//save the listener so it can be closed
l net.Listener
encKey []byte
signKey []byte
l net.Listener
encKey []byte
signKey []byte
filterParams []*regexp.Regexp
}

func NewServer() *Server {
var config = defaultConfig
return &Server{
Config: Config,
Config: &config,
Logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
Env: map[string]interface{}{},
}
Expand All @@ -64,6 +73,11 @@ func (s *Server) initServer() {
s.encKey = genKey(s.Config.CookieSecret, "encryption key salt")
s.signKey = genKey(s.Config.CookieSecret, "signature key salt")
}

s.filterParams = make([]*regexp.Regexp, len(s.Config.FilterParams))
for i, f := range s.Config.FilterParams {
s.filterParams[i] = regexp.MustCompile(f)
}
}

type route struct {
Expand Down Expand Up @@ -294,27 +308,53 @@ func (s *Server) logRequest(ctx Context, sTime time.Time) {

var logEntry bytes.Buffer
logEntry.WriteString(client)
logEntry.WriteString(" - " + s.ttyGreen(req.Method+" "+requestPath))
logEntry.WriteString(" - " + s.ttyGreen() + req.Method + " " + requestPath + s.ttyReset())
logEntry.WriteString(" - " + duration.String())
if len(ctx.Params) > 0 {
logEntry.WriteString(" - " + s.ttyWhite(fmt.Sprintf("Params: %v\n", ctx.Params)))
s.logParams(&logEntry, ctx.Params)
}
ctx.Server.Logger.Print(logEntry.String())
}

func (s *Server) ttyGreen(msg string) string {
return s.ttyColor(msg, ttyCodes.green)
func (s *Server) logParams(logEntry *bytes.Buffer, params map[string]string) {
logEntry.WriteString(" - ")
logEntry.WriteString(s.ttyWhite())
logEntry.WriteString("Params: {")
i := 0
for k, v := range params {
out := v
for _, r := range s.filterParams {
if r.MatchString(k) {
out = "[filtered]"
}
}
fmt.Fprintf(logEntry, "%q: %q", k, out)
i += 1
if i < len(params) {
logEntry.WriteString(", ")
}
}
logEntry.WriteString("}")
logEntry.WriteString(s.ttyReset())
}

func (s *Server) ttyGreen() string {
return s.ttyColor(ttyCodes.green)
}

func (s *Server) ttyWhite() string {
return s.ttyColor(ttyCodes.white)
}

func (s *Server) ttyWhite(msg string) string {
return s.ttyColor(msg, ttyCodes.white)
func (s *Server) ttyReset() string {
return s.ttyColor(ttyCodes.reset)
}

func (s *Server) ttyColor(msg string, colorCode string) string {
func (s *Server) ttyColor(code string) string {
if s.Config.ColorOutput {
return colorCode + msg + ttyCodes.reset
return code
} else {
return msg
return ""
}
}

Expand Down
9 changes: 3 additions & 6 deletions web.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,7 @@ func SetLogger(logger *log.Logger) {
mainServer.Logger = logger
}

// Config is the configuration of the main server.
var Config = &ServerConfig{
RecoverPanic: true,
ColorOutput: true,
}

var mainServer = NewServer()

// Config is the configuration of the main server.
var Config = mainServer.Config
30 changes: 30 additions & 0 deletions web_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,26 @@ func TestNoColorOutput(t *testing.T) {
}
}

// test that output contains ASCII color codes by default
func TestFilterParams(t *testing.T) {
s := NewServer()
var logOutput bytes.Buffer
logger := log.New(&logOutput, "", 0)
s.Logger = logger
s.initServer()
s.Post("/test", func() string {
return "test"
})
req := buildTestRequest("POST", "/test", "password=12345&password_confirm=12345", map[string][]string{"Content-Type": {"application/x-www-form-urlencoded"}}, nil)
var buf bytes.Buffer
iob := ioBuffer{input: nil, output: &buf}
c := scgiConn{wroteHeaders: false, req: req, headers: make(map[string][]string), fd: &iob}
s.Process(&c, req)
if strings.Contains(logOutput.String(), "12345") {
t.Fatalf("Params are not being filtered")
}
}

// a malformed SCGI request should be discarded and not cause a panic
func TestMaformedScgiRequest(t *testing.T) {
var headerBuf bytes.Buffer
Expand Down Expand Up @@ -639,6 +659,16 @@ func TestCustomHandlerContentType(t *testing.T) {
}
}

func TestNewServerDoesNotInheritMainConfig(t *testing.T) {
s1 := NewServer()
mainServer.Config.RecoverPanic = !mainServer.Config.RecoverPanic
s2 := NewServer()
if s1.Config.RecoverPanic != s2.Config.RecoverPanic {
t.Fatalf("New servers are using the main package config")
}
mainServer.Config.RecoverPanic = !mainServer.Config.RecoverPanic
}

func BuildBasicAuthCredentials(user string, pass string) string {
s := user + ":" + pass
return "Basic " + base64.StdEncoding.EncodeToString([]byte(s))
Expand Down