diff --git a/integration/access_log_test.go b/integration/access_log_test.go new file mode 100644 index 000000000..b48705134 --- /dev/null +++ b/integration/access_log_test.go @@ -0,0 +1,110 @@ +package main + +import ( + "fmt" + "io/ioutil" + "net" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "regexp" + "strings" + "time" + + "github.com/go-check/check" + shellwords "github.com/mattn/go-shellwords" + + checker "github.com/vdemeester/shakers" +) + +// AccessLogSuite +type AccessLogSuite struct{ BaseSuite } + +func (s *AccessLogSuite) TestAccessLog(c *check.C) { + // Ensure working directory is clean + os.Remove("access.log") + os.Remove("traefik.log") + + // Start Traefik + cmd := exec.Command(traefikBinary, "--configFile=fixtures/access_log_config.toml") + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + defer os.Remove("access.log") + defer os.Remove("traefik.log") + + time.Sleep(500 * time.Millisecond) + + // Verify Traefik started OK + if traefikLog, err := ioutil.ReadFile("traefik.log"); err != nil { + c.Assert(err.Error(), checker.Equals, "") + } else if len(traefikLog) > 0 { + fmt.Printf("%s\n", string(traefikLog)) + c.Assert(len(traefikLog), checker.Equals, 0) + } + + // Start test servers + ts1 := startAccessLogServer(8081) + defer ts1.Close() + ts2 := startAccessLogServer(8082) + defer ts2.Close() + ts3 := startAccessLogServer(8083) + defer ts3.Close() + + // Make some requests + _, err = http.Get("http://127.0.0.1:8000/test1") + c.Assert(err, checker.IsNil) + _, err = http.Get("http://127.0.0.1:8000/test2") + c.Assert(err, checker.IsNil) + _, err = http.Get("http://127.0.0.1:8000/test2") + c.Assert(err, checker.IsNil) + + // Verify access.log output as expected + if accessLog, err := ioutil.ReadFile("access.log"); err != nil { + c.Assert(err.Error(), checker.Equals, "") + } else { + lines := strings.Split(string(accessLog), "\n") + count := 0 + for i, line := range lines { + if len(line) > 0 { + count++ + if tokens, err := shellwords.Parse(line); err != nil { + c.Assert(err.Error(), checker.Equals, "") + } else { + c.Assert(len(tokens), checker.Equals, 13) + c.Assert(tokens[6], checker.Equals, "200") + c.Assert(tokens[9], checker.Equals, fmt.Sprintf("%d", i+1)) + c.Assert(strings.HasPrefix(tokens[10], "frontend"), checker.True) + c.Assert(strings.HasPrefix(tokens[11], "http://127.0.0.1:808"), checker.True) + c.Assert(regexp.MustCompile("^\\d+\\.\\d+.*s$").MatchString(tokens[12]), checker.True) + } + } + } + c.Assert(count, checker.Equals, 3) + } + + // Verify no other Trarfik problems + if traefikLog, err := ioutil.ReadFile("traefik.log"); err != nil { + c.Assert(err.Error(), checker.Equals, "") + } else if len(traefikLog) > 0 { + fmt.Printf("%s\n", string(traefikLog)) + c.Assert(len(traefikLog), checker.Equals, 0) + } +} + +func startAccessLogServer(port int) (ts *httptest.Server) { + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Received query %s!\n", r.URL.Path[1:]) + }) + if listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)); err != nil { + panic(err) + } else { + ts = &httptest.Server{ + Listener: listener, + Config: &http.Server{Handler: handler}, + } + ts.Start() + } + return +} diff --git a/integration/fixtures/access_log_config.toml b/integration/fixtures/access_log_config.toml new file mode 100644 index 000000000..2a3e0ed08 --- /dev/null +++ b/integration/fixtures/access_log_config.toml @@ -0,0 +1,46 @@ +################################################################ +# Global configuration +################################################################ +traefikLogsFile = "traefik.log" +accessLogsFile = "access.log" +logLevel = "ERROR" +defaultEntryPoints = ["http"] +[entryPoints] + [entryPoints.http] + address = ":8000" + +################################################################ +# Web configuration backend +################################################################ +[web] +address = ":7888" + +################################################################ +# File configuration backend +################################################################ +[file] + +################################################################ +# rules +################################################################ + [backends] + [backends.backend1] + [backends.backend1.servers.server1] + url = "http://127.0.0.1:8081" + [backends.backend2] + [backends.backend2.LoadBalancer] + method = "drr" + [backends.backend2.servers.server1] + url = "http://127.0.0.1:8082" + [backends.backend2.servers.server2] + url = "http://127.0.0.1:8083" + [frontends] + [frontends.frontend1] + backend = "backend1" + [frontends.frontend1.routes.test_1] + rule = "Path: /test1" + [frontends.frontend2] + backend = "backend2" + passHostHeader = true + [frontends.frontend2.routes.test_2] + rule = "Path: /test2" \ No newline at end of file diff --git a/integration/integration_test.go b/integration/integration_test.go index 7178bb070..d472f7d23 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -23,6 +23,7 @@ func Test(t *testing.T) { func init() { check.Suite(&SimpleSuite{}) + check.Suite(&AccessLogSuite{}) check.Suite(&HTTPSSuite{}) check.Suite(&FileSuite{}) check.Suite(&DockerSuite{}) diff --git a/middlewares/logger.go b/middlewares/logger.go index 1a876b82f..f73f16965 100644 --- a/middlewares/logger.go +++ b/middlewares/logger.go @@ -38,7 +38,7 @@ type frontendBackendLoggingHandler struct { var ( reqidCounter uint64 // Request ID infoRwMap = cmap.New() // Map of reqid to response writer - backend2FrontendMap map[string]string + backend2FrontendMap *map[string]string ) // logInfoResponseWriter is a wrapper of type http.ResponseWriter @@ -65,7 +65,7 @@ func NewLogger(file string) *Logger { // SetBackend2FrontendMap is called by server.go to set up frontend translation func SetBackend2FrontendMap(newMap *map[string]string) { - backend2FrontendMap = *newMap + backend2FrontendMap = newMap } func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { @@ -93,7 +93,7 @@ func saveBackendNameForLogger(r *http.Request, backendName string) { reqid := reqidHdr[0] if infoRw, ok := infoRwMap.Get(reqid); ok { infoRw.(*logInfoResponseWriter).SetBackend(backendName) - infoRw.(*logInfoResponseWriter).SetFrontend(backend2FrontendMap[backendName]) + infoRw.(*logInfoResponseWriter).SetFrontend((*backend2FrontendMap)[backendName]) } } } diff --git a/server.go b/server.go index c4a14f14c..a3d29bba4 100644 --- a/server.go +++ b/server.go @@ -35,10 +35,7 @@ import ( "github.com/streamrail/concurrent-map" ) -var ( - oxyLogger = &OxyLogger{} - backend2FrontendMap map[string]string -) +var oxyLogger = &OxyLogger{} // Server is the reverse-proxy/load-balancer engine type Server struct {