diff --git a/integration/fixtures/grpc/config_retry.toml b/integration/fixtures/grpc/config_retry.toml new file mode 100644 index 000000000..0b1e712ad --- /dev/null +++ b/integration/fixtures/grpc/config_retry.toml @@ -0,0 +1,31 @@ +defaultEntryPoints = ["https"] + +rootCAs = [ """{{ .CertContent }}""" ] + +[retry] + +[entryPoints] + [entryPoints.https] + address = ":4443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + certFile = """{{ .CertContent }}""" + keyFile = """{{ .KeyContent }}""" + + +[api] + +[file] + +[backends] + [backends.backend1] + [backends.backend1.servers.server1] + url = "https://127.0.0.1:{{ .GRPCServerPort }}" + weight = 1 + + +[frontends] + [frontends.frontend1] + backend = "backend1" + [frontends.frontend1.routes.test_1] + rule = "Host:127.0.0.1" diff --git a/integration/grpc_test.go b/integration/grpc_test.go index d26f8a502..4330d60a7 100644 --- a/integration/grpc_test.go +++ b/integration/grpc_test.go @@ -417,3 +417,45 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) { }) c.Assert(err, check.IsNil) } + +func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) { + lis, err := net.Listen("tcp", ":0") + _, port, err := net.SplitHostPort(lis.Addr().String()) + c.Assert(err, check.IsNil) + + go func() { + err := startGRPCServer(lis, &myserver{}) + c.Log(err) + c.Assert(err, check.IsNil) + }() + + file := s.adaptFile(c, "fixtures/grpc/config_retry.toml", struct { + CertContent string + KeyContent string + GRPCServerPort string + }{ + CertContent: string(LocalhostCert), + KeyContent: string(LocalhostKey), + GRPCServerPort: port, + }) + + defer os.Remove(file) + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + + err = cmd.Start() + c.Assert(err, check.IsNil) + defer cmd.Process.Kill() + + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1*time.Second, try.BodyContains("Host:127.0.0.1")) + c.Assert(err, check.IsNil) + + var response string + err = try.Do(1*time.Second, func() error { + response, err = callHelloClientGRPC("World", true) + return err + }) + c.Assert(err, check.IsNil) + c.Assert(response, check.Equals, "Hello World") +} diff --git a/middlewares/retry.go b/middlewares/retry.go index 5166ca8f6..1072a045d 100644 --- a/middlewares/retry.go +++ b/middlewares/retry.go @@ -110,6 +110,7 @@ type retryResponseWriterWithoutCloseNotify struct { responseWriter http.ResponseWriter headers http.Header shouldRetry bool + written bool } func (rr *retryResponseWriterWithoutCloseNotify) ShouldRetry() bool { @@ -121,6 +122,9 @@ func (rr *retryResponseWriterWithoutCloseNotify) DisableRetries() { } func (rr *retryResponseWriterWithoutCloseNotify) Header() http.Header { + if rr.written { + return rr.responseWriter.Header() + } return rr.headers } @@ -155,6 +159,7 @@ func (rr *retryResponseWriterWithoutCloseNotify) WriteHeader(code int) { } rr.responseWriter.WriteHeader(code) + rr.written = true } func (rr *retryResponseWriterWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {