[pluggable-transports/snowflake] branch main updated (56f15a5 -> 788e3ae)

This is an automated email from the git hooks/post-receive script. shelikhoo pushed a change to branch main in repository pluggable-transports/snowflake. from 56f15a5 Update ChangeLog for v2.4.0 new d8d3e53 Fix uTLS RoundTripper Inconsistent Key for host:port new 788e3ae Refactor utls roundtripper_test to deduplicate The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: common/utls/roundtripper.go | 7 ++++++- common/utls/roundtripper_test.go | 27 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) -- To stop receiving notification emails like this one, please contact the administrator of this repository.

This is an automated email from the git hooks/post-receive script. shelikhoo pushed a commit to branch main in repository pluggable-transports/snowflake. commit d8d3e538f1fe2c60369876970900fe00a7958aca Author: Shelikhoo <xiaokangwang@outlook.com> AuthorDate: Fri Nov 25 14:29:58 2022 +0000 Fix uTLS RoundTripper Inconsistent Key for host:port This commit fixes an issue described at: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowf... This bug has been fixed, with test case describing this bug added. --- common/utls/roundtripper.go | 7 +- common/utls/roundtripper_test.go | 295 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 1 deletion(-) diff --git a/common/utls/roundtripper.go b/common/utls/roundtripper.go index 53b997f..5b74aec 100644 --- a/common/utls/roundtripper.go +++ b/common/utls/roundtripper.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "errors" + "fmt" "net" "net/http" "sync" @@ -66,7 +67,11 @@ func (r *uTLSHTTPRoundTripperImpl) RoundTrip(req *http.Request) (*http.Response, return r.backdropTransport.RoundTrip(req) } for retryCount := 0; retryCount < 5; retryCount++ { - if r.getShouldConnectWithH1(req.URL.Host) { + effectivePort := req.URL.Port() + if effectivePort == "" { + effectivePort = "443" + } + if r.getShouldConnectWithH1(fmt.Sprintf("%v:%v", req.URL.Hostname(), effectivePort)) { resp, err := r.httpsH1Transport.RoundTrip(req) if errors.Is(err, errEAGAIN) { continue diff --git a/common/utls/roundtripper_test.go b/common/utls/roundtripper_test.go index bccb799..d21df52 100644 --- a/common/utls/roundtripper_test.go +++ b/common/utls/roundtripper_test.go @@ -8,6 +8,7 @@ import ( "math/big" "math/rand" "net/http" + "os" "testing" "time" @@ -162,3 +163,297 @@ func TestRoundTripper(t *testing.T) { cancel() } + +func TestRoundTripperOnH1DefaultPort(t *testing.T) { + if os.Getuid() != 0 { + t.SkipNow() + } + var selfSignedCert []byte + var selfSignedPrivateKey *rsa.PrivateKey + httpServerContext, cancel := stdcontext.WithCancel(stdcontext.Background()) + Convey("[Test]Set up http servers", t, func(c C) { + c.Convey("[Test]Generate Self-Signed Cert", func(c C) { + // Ported from https://gist.github.com/samuel/8b500ddd3f6118d052b5e6bc16bc4c09 + + // note that we use the insecure math/rand here because some platforms + // fail the test suite at build time in Debian, due to entropy starvation. + // since that's not a problem at test time, we do *not* use a secure + // mechanism for key generation. + // + // DO NOT REUSE THIS CODE IN PRODUCTION, IT IS DANGEROUS + insecureRandReader := rand.New(rand.NewSource(1337)) + priv, err := rsa.GenerateKey(insecureRandReader, 4096) + c.So(err, ShouldBeNil) + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Testing Certificate", + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour * 24 * 180), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + derBytes, err := x509.CreateCertificate(insecureRandReader, &template, &template, priv.Public(), priv) + c.So(err, ShouldBeNil) + selfSignedPrivateKey = priv + selfSignedCert = derBytes + }) + c.Convey("[Test]Setup http2 server", func(c C) { + listener, err := tls.Listen("tcp", "127.0.0.1:23802", &tls.Config{ + NextProtos: []string{http2.NextProtoTLS}, + Certificates: []tls.Certificate{ + tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, + }, + }) + c.So(err, ShouldBeNil) + s := http.Server{} + go s.Serve(listener) + go func() { + <-httpServerContext.Done() + s.Close() + }() + }) + c.Convey("[Test]Setup http1 server", func(c C) { + listener, err := tls.Listen("tcp", "127.0.0.1:443", &tls.Config{ + NextProtos: []string{"http/1.1"}, + Certificates: []tls.Certificate{ + tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, + }, + }) + c.So(err, ShouldBeNil) + s := http.Server{} + go s.Serve(listener) + go func() { + <-httpServerContext.Done() + s.Close() + }() + }) + }) + for _, v := range []struct { + id utls.ClientHelloID + name string + }{ + { + id: utls.HelloChrome_58, + name: "HelloChrome_58", + }, + { + id: utls.HelloChrome_62, + name: "HelloChrome_62", + }, + { + id: utls.HelloChrome_70, + name: "HelloChrome_70", + }, + { + id: utls.HelloChrome_72, + name: "HelloChrome_72", + }, + { + id: utls.HelloChrome_83, + name: "HelloChrome_83", + }, + { + id: utls.HelloFirefox_55, + name: "HelloFirefox_55", + }, + { + id: utls.HelloFirefox_55, + name: "HelloFirefox_55", + }, + { + id: utls.HelloFirefox_63, + name: "HelloFirefox_63", + }, + { + id: utls.HelloFirefox_65, + name: "HelloFirefox_65", + }, + { + id: utls.HelloIOS_11_1, + name: "HelloIOS_11_1", + }, + { + id: utls.HelloIOS_12_1, + name: "HelloIOS_12_1", + }, + } { + t.Run("Testing fingerprint for "+v.name, func(t *testing.T) { + rtter := NewUTLSHTTPRoundTripper(v.id, &utls.Config{ + InsecureSkipVerify: true, + }, http.DefaultTransport, false) + + for count := 0; count <= 10; count++ { + Convey("HTTP 1.1 Test", t, func(c C) { + { + req, err := http.NewRequest("GET", "https://127.0.0.1/", nil) + So(err, ShouldBeNil) + _, err = rtter.RoundTrip(req) + So(err, ShouldBeNil) + } + }) + + Convey("HTTP 2 Test", t, func(c C) { + { + req, err := http.NewRequest("GET", "https://127.0.0.1:23802/", nil) + So(err, ShouldBeNil) + _, err = rtter.RoundTrip(req) + So(err, ShouldBeNil) + } + }) + } + }) + } + + cancel() +} + +func TestRoundTripperOnH2DefaultPort(t *testing.T) { + if os.Getuid() != 0 { + t.SkipNow() + } + var selfSignedCert []byte + var selfSignedPrivateKey *rsa.PrivateKey + httpServerContext, cancel := stdcontext.WithCancel(stdcontext.Background()) + Convey("[Test]Set up http servers", t, func(c C) { + c.Convey("[Test]Generate Self-Signed Cert", func(c C) { + // Ported from https://gist.github.com/samuel/8b500ddd3f6118d052b5e6bc16bc4c09 + + // note that we use the insecure math/rand here because some platforms + // fail the test suite at build time in Debian, due to entropy starvation. + // since that's not a problem at test time, we do *not* use a secure + // mechanism for key generation. + // + // DO NOT REUSE THIS CODE IN PRODUCTION, IT IS DANGEROUS + insecureRandReader := rand.New(rand.NewSource(1337)) + priv, err := rsa.GenerateKey(insecureRandReader, 4096) + c.So(err, ShouldBeNil) + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Testing Certificate", + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour * 24 * 180), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + derBytes, err := x509.CreateCertificate(insecureRandReader, &template, &template, priv.Public(), priv) + c.So(err, ShouldBeNil) + selfSignedPrivateKey = priv + selfSignedCert = derBytes + }) + c.Convey("[Test]Setup http2 server", func(c C) { + listener, err := tls.Listen("tcp", "127.0.0.1:443", &tls.Config{ + NextProtos: []string{http2.NextProtoTLS}, + Certificates: []tls.Certificate{ + tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, + }, + }) + c.So(err, ShouldBeNil) + s := http.Server{} + go s.Serve(listener) + go func() { + <-httpServerContext.Done() + s.Close() + }() + }) + c.Convey("[Test]Setup http1 server", func(c C) { + listener, err := tls.Listen("tcp", "127.0.0.1:23801", &tls.Config{ + NextProtos: []string{"http/1.1"}, + Certificates: []tls.Certificate{ + tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, + }, + }) + c.So(err, ShouldBeNil) + s := http.Server{} + go s.Serve(listener) + go func() { + <-httpServerContext.Done() + s.Close() + }() + }) + }) + for _, v := range []struct { + id utls.ClientHelloID + name string + }{ + { + id: utls.HelloChrome_58, + name: "HelloChrome_58", + }, + { + id: utls.HelloChrome_62, + name: "HelloChrome_62", + }, + { + id: utls.HelloChrome_70, + name: "HelloChrome_70", + }, + { + id: utls.HelloChrome_72, + name: "HelloChrome_72", + }, + { + id: utls.HelloChrome_83, + name: "HelloChrome_83", + }, + { + id: utls.HelloFirefox_55, + name: "HelloFirefox_55", + }, + { + id: utls.HelloFirefox_55, + name: "HelloFirefox_55", + }, + { + id: utls.HelloFirefox_63, + name: "HelloFirefox_63", + }, + { + id: utls.HelloFirefox_65, + name: "HelloFirefox_65", + }, + { + id: utls.HelloIOS_11_1, + name: "HelloIOS_11_1", + }, + { + id: utls.HelloIOS_12_1, + name: "HelloIOS_12_1", + }, + } { + t.Run("Testing fingerprint for "+v.name, func(t *testing.T) { + rtter := NewUTLSHTTPRoundTripper(v.id, &utls.Config{ + InsecureSkipVerify: true, + }, http.DefaultTransport, false) + + for count := 0; count <= 10; count++ { + Convey("HTTP 1.1 Test", t, func(c C) { + { + req, err := http.NewRequest("GET", "https://127.0.0.1:23801/", nil) + So(err, ShouldBeNil) + _, err = rtter.RoundTrip(req) + So(err, ShouldBeNil) + } + }) + + Convey("HTTP 2 Test", t, func(c C) { + { + req, err := http.NewRequest("GET", "https://127.0.0.1/", nil) + So(err, ShouldBeNil) + _, err = rtter.RoundTrip(req) + So(err, ShouldBeNil) + } + }) + } + }) + } + + cancel() +} -- To stop receiving notification emails like this one, please contact the administrator of this repository.

This is an automated email from the git hooks/post-receive script. shelikhoo pushed a commit to branch main in repository pluggable-transports/snowflake. commit 788e3ae95604ea1ae21491e6ab3682cfbd4753ec Author: Shelikhoo <xiaokangwang@outlook.com> AuthorDate: Tue Nov 29 15:39:29 2022 +0000 Refactor utls roundtripper_test to deduplicate --- common/utls/roundtripper_test.go | 296 ++------------------------------------- 1 file changed, 10 insertions(+), 286 deletions(-) diff --git a/common/utls/roundtripper_test.go b/common/utls/roundtripper_test.go index d21df52..905b78e 100644 --- a/common/utls/roundtripper_test.go +++ b/common/utls/roundtripper_test.go @@ -21,300 +21,24 @@ import ( ) func TestRoundTripper(t *testing.T) { - var selfSignedCert []byte - var selfSignedPrivateKey *rsa.PrivateKey - httpServerContext, cancel := stdcontext.WithCancel(stdcontext.Background()) - Convey("[Test]Set up http servers", t, func(c C) { - c.Convey("[Test]Generate Self-Signed Cert", func(c C) { - // Ported from https://gist.github.com/samuel/8b500ddd3f6118d052b5e6bc16bc4c09 - - // note that we use the insecure math/rand here because some platforms - // fail the test suite at build time in Debian, due to entropy starvation. - // since that's not a problem at test time, we do *not* use a secure - // mechanism for key generation. - // - // DO NOT REUSE THIS CODE IN PRODUCTION, IT IS DANGEROUS - insecureRandReader := rand.New(rand.NewSource(1337)) - priv, err := rsa.GenerateKey(insecureRandReader, 4096) - c.So(err, ShouldBeNil) - template := x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - CommonName: "Testing Certificate", - }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 180), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - } - derBytes, err := x509.CreateCertificate(insecureRandReader, &template, &template, priv.Public(), priv) - c.So(err, ShouldBeNil) - selfSignedPrivateKey = priv - selfSignedCert = derBytes - }) - c.Convey("[Test]Setup http2 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:23802", &tls.Config{ - NextProtos: []string{http2.NextProtoTLS}, - Certificates: []tls.Certificate{ - tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, - }, - }) - c.So(err, ShouldBeNil) - s := http.Server{} - go s.Serve(listener) - go func() { - <-httpServerContext.Done() - s.Close() - }() - }) - c.Convey("[Test]Setup http1 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:23801", &tls.Config{ - NextProtos: []string{"http/1.1"}, - Certificates: []tls.Certificate{ - tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, - }, - }) - c.So(err, ShouldBeNil) - s := http.Server{} - go s.Serve(listener) - go func() { - <-httpServerContext.Done() - s.Close() - }() - }) - }) - for _, v := range []struct { - id utls.ClientHelloID - name string - }{ - { - id: utls.HelloChrome_58, - name: "HelloChrome_58", - }, - { - id: utls.HelloChrome_62, - name: "HelloChrome_62", - }, - { - id: utls.HelloChrome_70, - name: "HelloChrome_70", - }, - { - id: utls.HelloChrome_72, - name: "HelloChrome_72", - }, - { - id: utls.HelloChrome_83, - name: "HelloChrome_83", - }, - { - id: utls.HelloFirefox_55, - name: "HelloFirefox_55", - }, - { - id: utls.HelloFirefox_55, - name: "HelloFirefox_55", - }, - { - id: utls.HelloFirefox_63, - name: "HelloFirefox_63", - }, - { - id: utls.HelloFirefox_65, - name: "HelloFirefox_65", - }, - { - id: utls.HelloIOS_11_1, - name: "HelloIOS_11_1", - }, - { - id: utls.HelloIOS_12_1, - name: "HelloIOS_12_1", - }, - } { - t.Run("Testing fingerprint for "+v.name, func(t *testing.T) { - rtter := NewUTLSHTTPRoundTripper(v.id, &utls.Config{ - InsecureSkipVerify: true, - }, http.DefaultTransport, false) - - for count := 0; count <= 10; count++ { - Convey("HTTP 1.1 Test", t, func(c C) { - { - req, err := http.NewRequest("GET", "https://127.0.0.1:23801/", nil) - So(err, ShouldBeNil) - _, err = rtter.RoundTrip(req) - So(err, ShouldBeNil) - } - }) - - Convey("HTTP 2 Test", t, func(c C) { - { - req, err := http.NewRequest("GET", "https://127.0.0.1:23802/", nil) - So(err, ShouldBeNil) - _, err = rtter.RoundTrip(req) - So(err, ShouldBeNil) - } - }) - } - }) - } - - cancel() + runRoundTripperTest(t, "127.0.0.1:23802", "127.0.0.1:23801", "https://127.0.0.1:23802/", "https://127.0.0.1:23801/") } func TestRoundTripperOnH1DefaultPort(t *testing.T) { if os.Getuid() != 0 { t.SkipNow() } - var selfSignedCert []byte - var selfSignedPrivateKey *rsa.PrivateKey - httpServerContext, cancel := stdcontext.WithCancel(stdcontext.Background()) - Convey("[Test]Set up http servers", t, func(c C) { - c.Convey("[Test]Generate Self-Signed Cert", func(c C) { - // Ported from https://gist.github.com/samuel/8b500ddd3f6118d052b5e6bc16bc4c09 - - // note that we use the insecure math/rand here because some platforms - // fail the test suite at build time in Debian, due to entropy starvation. - // since that's not a problem at test time, we do *not* use a secure - // mechanism for key generation. - // - // DO NOT REUSE THIS CODE IN PRODUCTION, IT IS DANGEROUS - insecureRandReader := rand.New(rand.NewSource(1337)) - priv, err := rsa.GenerateKey(insecureRandReader, 4096) - c.So(err, ShouldBeNil) - template := x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - CommonName: "Testing Certificate", - }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 180), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - } - derBytes, err := x509.CreateCertificate(insecureRandReader, &template, &template, priv.Public(), priv) - c.So(err, ShouldBeNil) - selfSignedPrivateKey = priv - selfSignedCert = derBytes - }) - c.Convey("[Test]Setup http2 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:23802", &tls.Config{ - NextProtos: []string{http2.NextProtoTLS}, - Certificates: []tls.Certificate{ - tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, - }, - }) - c.So(err, ShouldBeNil) - s := http.Server{} - go s.Serve(listener) - go func() { - <-httpServerContext.Done() - s.Close() - }() - }) - c.Convey("[Test]Setup http1 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:443", &tls.Config{ - NextProtos: []string{"http/1.1"}, - Certificates: []tls.Certificate{ - tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, - }, - }) - c.So(err, ShouldBeNil) - s := http.Server{} - go s.Serve(listener) - go func() { - <-httpServerContext.Done() - s.Close() - }() - }) - }) - for _, v := range []struct { - id utls.ClientHelloID - name string - }{ - { - id: utls.HelloChrome_58, - name: "HelloChrome_58", - }, - { - id: utls.HelloChrome_62, - name: "HelloChrome_62", - }, - { - id: utls.HelloChrome_70, - name: "HelloChrome_70", - }, - { - id: utls.HelloChrome_72, - name: "HelloChrome_72", - }, - { - id: utls.HelloChrome_83, - name: "HelloChrome_83", - }, - { - id: utls.HelloFirefox_55, - name: "HelloFirefox_55", - }, - { - id: utls.HelloFirefox_55, - name: "HelloFirefox_55", - }, - { - id: utls.HelloFirefox_63, - name: "HelloFirefox_63", - }, - { - id: utls.HelloFirefox_65, - name: "HelloFirefox_65", - }, - { - id: utls.HelloIOS_11_1, - name: "HelloIOS_11_1", - }, - { - id: utls.HelloIOS_12_1, - name: "HelloIOS_12_1", - }, - } { - t.Run("Testing fingerprint for "+v.name, func(t *testing.T) { - rtter := NewUTLSHTTPRoundTripper(v.id, &utls.Config{ - InsecureSkipVerify: true, - }, http.DefaultTransport, false) - - for count := 0; count <= 10; count++ { - Convey("HTTP 1.1 Test", t, func(c C) { - { - req, err := http.NewRequest("GET", "https://127.0.0.1/", nil) - So(err, ShouldBeNil) - _, err = rtter.RoundTrip(req) - So(err, ShouldBeNil) - } - }) - - Convey("HTTP 2 Test", t, func(c C) { - { - req, err := http.NewRequest("GET", "https://127.0.0.1:23802/", nil) - So(err, ShouldBeNil) - _, err = rtter.RoundTrip(req) - So(err, ShouldBeNil) - } - }) - } - }) - } - - cancel() + runRoundTripperTest(t, "127.0.0.1:23802", "127.0.0.1:443", "https://127.0.0.1:23802/", "https://127.0.0.1/") } func TestRoundTripperOnH2DefaultPort(t *testing.T) { if os.Getuid() != 0 { t.SkipNow() } + runRoundTripperTest(t, "127.0.0.1:443", "127.0.0.1:23801", "https://127.0.0.1/", "https://127.0.0.1:23801/") +} + +func runRoundTripperTest(t *testing.T, h2listen, h1listen, h2addr, h1addr string) { var selfSignedCert []byte var selfSignedPrivateKey *rsa.PrivateKey httpServerContext, cancel := stdcontext.WithCancel(stdcontext.Background()) @@ -349,7 +73,7 @@ func TestRoundTripperOnH2DefaultPort(t *testing.T) { selfSignedCert = derBytes }) c.Convey("[Test]Setup http2 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:443", &tls.Config{ + listener, err := tls.Listen("tcp", h2listen, &tls.Config{ NextProtos: []string{http2.NextProtoTLS}, Certificates: []tls.Certificate{ tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, @@ -364,7 +88,7 @@ func TestRoundTripperOnH2DefaultPort(t *testing.T) { }() }) c.Convey("[Test]Setup http1 server", func(c C) { - listener, err := tls.Listen("tcp", "127.0.0.1:23801", &tls.Config{ + listener, err := tls.Listen("tcp", h1listen, &tls.Config{ NextProtos: []string{"http/1.1"}, Certificates: []tls.Certificate{ tls.Certificate{Certificate: [][]byte{selfSignedCert}, PrivateKey: selfSignedPrivateKey}, @@ -436,7 +160,7 @@ func TestRoundTripperOnH2DefaultPort(t *testing.T) { for count := 0; count <= 10; count++ { Convey("HTTP 1.1 Test", t, func(c C) { { - req, err := http.NewRequest("GET", "https://127.0.0.1:23801/", nil) + req, err := http.NewRequest("GET", h2addr, nil) So(err, ShouldBeNil) _, err = rtter.RoundTrip(req) So(err, ShouldBeNil) @@ -445,7 +169,7 @@ func TestRoundTripperOnH2DefaultPort(t *testing.T) { Convey("HTTP 2 Test", t, func(c C) { { - req, err := http.NewRequest("GET", "https://127.0.0.1/", nil) + req, err := http.NewRequest("GET", h1addr, nil) So(err, ShouldBeNil) _, err = rtter.RoundTrip(req) So(err, ShouldBeNil) -- To stop receiving notification emails like this one, please contact the administrator of this repository.
participants (1)
-
gitolite role