diff --git a/app/main_test.go b/app/main_test.go index b50286c..9e1d0c1 100644 --- a/app/main_test.go +++ b/app/main_test.go @@ -1,6 +1,7 @@ package main import ( + "crypto/tls" "fmt" "io/ioutil" "math/rand" @@ -86,6 +87,66 @@ func Test_Main(t *testing.T) { } } +func Test_MainWithSSL(t *testing.T) { + port := chooseRandomUnusedPort() + os.Args = []string{"test", "--static.enabled", + "--static.rule=*,/svc1, https://httpbin.org/get,https://feedmaster.umputun.com/ping", + "--static.rule=*,/svc2/(.*), https://echo.umputun.com/$1,https://feedmaster.umputun.com/ping", + "--file.enabled", "--file.name=discovery/provider/testdata/config.yml", + "--dbg", "--logger.enabled", "--logger.stdout", "--logger.file=/tmp/reproxy.log", + "--listen=127.0.0.1:" + strconv.Itoa(port), "--signature", "--ssl.type=static", + "--ssl.cert=proxy/testdata/localhost.crt", "--ssl.key=proxy/testdata/localhost.key"} + defer os.Remove("/tmp/reproxy.log") + done := make(chan struct{}) + go func() { + <-done + e := syscall.Kill(syscall.Getpid(), syscall.SIGTERM) + require.NoError(t, e) + }() + + finished := make(chan struct{}) + go func() { + main() + close(finished) + }() + + // defer cleanup because require check below can fail + defer func() { + close(done) + <-finished + }() + + waitForHTTPServerStart(port) + time.Sleep(time.Second) + + client := http.Client{ + // allow self-signed certificate + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + Timeout: 10 * time.Second, + } + { + resp, err := client.Get(fmt.Sprintf("https://127.0.0.1:%d/ping", port)) + require.NoError(t, err) + defer resp.Body.Close() + assert.Equal(t, 200, resp.StatusCode) + body, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + assert.Equal(t, "pong", string(body)) + } + + { + resp, err := client.Get(fmt.Sprintf("https://127.0.0.1:%d/svc1", port)) + require.NoError(t, err) + defer resp.Body.Close() + assert.Equal(t, 200, resp.StatusCode) + body, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + assert.Contains(t, string(body), `"Host": "httpbin.org"`) + } +} + func chooseRandomUnusedPort() (port int) { for i := 0; i < 10; i++ { port = 40000 + int(rand.Int31n(10000)) diff --git a/app/proxy/proxy.go b/app/proxy/proxy.go index c5b538b..c377534 100644 --- a/app/proxy/proxy.go +++ b/app/proxy/proxy.go @@ -310,18 +310,6 @@ func (h *Http) stdoutLogHandler(enable bool, lh func(next http.Handler) http.Han } } -// func (h *Http) cachingHandler(next http.Handler) http.Handler { -// -// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// mt := mime.TypeByExtension(path.Ext(r.URL.Path)) -// log.Printf("tt: %s", mt) -// if h.AssetsCacheDuration > 0 { -// w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(h.AssetsCacheDuration.Seconds()))) -// } -// next.ServeHTTP(w, r) -// }) -// } - func (h *Http) makeHTTPServer(addr string, router http.Handler) *http.Server { return &http.Server{ Addr: addr, diff --git a/app/proxy/proxy_test.go b/app/proxy/proxy_test.go index efb89ec..bb590bd 100644 --- a/app/proxy/proxy_test.go +++ b/app/proxy/proxy_test.go @@ -256,48 +256,3 @@ func TestHttp_toHttp(t *testing.T) { } } - -// func TestHttp_cachingHandler(t *testing.T) { -// -// dir, e := ioutil.TempDir(os.TempDir(), "reproxy") -// require.NoError(t, e) -// e = ioutil.WriteFile(path.Join(dir, "1.html"), []byte("1.htm"), 0600) -// assert.NoError(t, e) -// e = ioutil.WriteFile(path.Join(dir, "2.html"), []byte("2.htm"), 0600) -// assert.NoError(t, e) -// -// defer os.RemoveAll(dir) -// -// fh, e := R.FileServer("/static", dir) -// require.NoError(t, e) -// h := Http{AssetsCacheDuration: 10 * time.Second, AssetsLocation: dir, AssetsWebRoot: "/static"} -// hh := R.Wrap(fh, h.cachingHandler) -// ts := httptest.NewServer(hh) -// defer ts.Close() -// client := http.Client{Timeout: 599 * time.Second} -// -// { -// resp, err := client.Get(ts.URL + "/static/1.html") -// require.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) -// t.Logf("headers: %+v", resp.Header) -// assert.Equal(t, "public, max-age=10", resp.Header.Get("Cache-Control")) -// assert.NotEqual(t, "", resp.Header.Get("Last-Modified")) -// } -// { -// resp, err := client.Get(ts.URL + "/static/bad.html") -// require.NoError(t, err) -// assert.Equal(t, http.StatusNotFound, resp.StatusCode) -// t.Logf("headers: %+v", resp.Header) -// assert.Equal(t, "public, max-age=10", resp.Header.Get("Cache-Control")) -// assert.Equal(t, "", resp.Header.Get("Last-Modified")) -// } -// { -// resp, err := client.Get(ts.URL + "/%2e%2e%2f%2e%2e%2f%2e%2e%2f/etc/passwd") -// require.NoError(t, err) -// assert.Equal(t, http.StatusNotFound, resp.StatusCode) -// t.Logf("headers: %+v", resp.Header) -// assert.Equal(t, "public, max-age=10", resp.Header.Get("Cache-Control")) -// assert.Equal(t, "", resp.Header.Get("Last-Modified")) -// } -// } diff --git a/app/proxy/testdata/localhost.crt b/app/proxy/testdata/localhost.crt new file mode 100644 index 0000000..2881df9 --- /dev/null +++ b/app/proxy/testdata/localhost.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC5TCCAc2gAwIBAgIJALiRj0+veRc9MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAeFw0yMTA0MjcwNzQ1MzlaFw0yMTA1MjcwNzQ1MzlaMBQx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKku5qZGexf0uvgVY+u8DOSnq8W10w+yQ1wSkMR5T0ag3hyimIDmDhNB3dI0 +5/B9IsIC9ZwUxOGHVCjP+TODXAGYIGYRx3BQb8si2369UXTQYNvVNQzPFdThjdcN +gXUmLN08a3ZMdXDC62DcOcVv1+oHd1qbuugkHqwA9CEn/aMJeYPso/4cfbgXX0WD +LEYkzgYwkyVf4JxyDWjm5d5fh/Tgpuu3lgH8qgKi51BmuSdiMiWsZ+AZykjpwAY6 +FsNHHmi1NZ1gLj/bzXNjziK50SIgIBiqTIxYdQBrYliRYC3RD252M4Sjk+WAOkVs +RvLDvYLcl0kqclayzBr2qI/2RkECAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo +b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B +AQsFAAOCAQEARvUEtFQC/l73/cTyEy24Om3t7uwHWzYRBQDz2dkj2V+OHuXaXKQW +9ucv9DupNYxuXLVg93IPZgDGlFUZMlNnTvP5APBdQZyuoyZER7pqlJg8Sfo1BO5P +KUqaspgdIzd8BmIYMkOaDgd/kOgqjGKjXJwHVvSl7oBcZ8WrxDBMuopXuFosYHVK +z9ZsknqbxibgWBhwLKgDSOwLwVRIPIXlgJpSIyfDpQt0D3PbiFfcXYHqZ09ocZ/b +mIRqF7/OpWW/15Zdo3+gqohWr5qoDZIH8gtBWRs6Ai3cbE/D5jSNdfDrrjRs0HkN +GHmkcX4ABMze6SN7cWFpgeIvy1mxKfMoZw== +-----END CERTIFICATE----- diff --git a/app/proxy/testdata/localhost.key b/app/proxy/testdata/localhost.key new file mode 100644 index 0000000..4fed723 --- /dev/null +++ b/app/proxy/testdata/localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCpLuamRnsX9Lr4 +FWPrvAzkp6vFtdMPskNcEpDEeU9GoN4copiA5g4TQd3SNOfwfSLCAvWcFMThh1Qo +z/kzg1wBmCBmEcdwUG/LItt+vVF00GDb1TUMzxXU4Y3XDYF1JizdPGt2THVwwutg +3DnFb9fqB3dam7roJB6sAPQhJ/2jCXmD7KP+HH24F19FgyxGJM4GMJMlX+Cccg1o +5uXeX4f04Kbrt5YB/KoCoudQZrknYjIlrGfgGcpI6cAGOhbDRx5otTWdYC4/281z +Y84iudEiICAYqkyMWHUAa2JYkWAt0Q9udjOEo5PlgDpFbEbyw72C3JdJKnJWsswa +9qiP9kZBAgMBAAECggEAcCZ7F3ZZWwQMfTAQ0NAT6++KWsGxbBJLvNlBxjx0ZOl2 +05ylY60dX36mQRZ5Ol55kArOLe1GpgpDq9pR4+gMMbJap87ZWoa31P0Ca/2r5bfM +vW2UgS0116y9jfWR/8qSqwXGZuFAaMONrOPQGCWQB79zS0k4mXJ4MqVfMCuGY3Bs +IkeyT96/pcYg36KeTGfvZOrX1GvH3udht5x2BxwuWdNjLEqL391OetnZe1H3NArs +fklboxgc/G0kRfx6X9/pqB+zytqeYec1nqc13I+3z6xjD1a2dK7rldY6CAp0IhwU +54hmu8MO/Laq3159xbB0BR48ClIwox+4z0pT5hDtEQKBgQDbfVMOma9TYmWGd7Or +/iuOVS64Jm2vrGySg/JlSBFskogy1vTtzwuAWe/3NLy5FVt1W7WC2Wt8OM1LIsh1 +lBiWM4Fz2bqLAgu1Y48Y0DsNVtckgo1jmwT4i1Ub664NMVvsaXLNtiSWzf53Jmh9 +J5zyg9ZiLXA7q+P5QDpZdskmowKBgQDFU1jC0LoaQaw+vH06eIoXVWYYwU+xpAK+ +AXZv7N3nBafhYTaTfWT/j54xoJr4kCnavXADMZq3oeHzR20B9oc4F1qT/6rEzYlu +pi7EtxXHf406Huf1uLOU8VckYEZd31i9dM0By7RD+EopYcI1TEIN1UR5XYv/bwHa +tZHjAFoBywKBgQCjnrZG4QxRFb3nUt6OrYgcr6WHQ6Zq2heJ1XDiTaonjMiZVaL6 +kGjbgrAfUaIKO0CVqQsTgy7cSJ/JjiFvfToi5jxvd3TXYWwHCTPIZJpQ5Fa3cdci +1JINEhkdGkECtrP29djOPyThgqhafDhSbDBUnTE4uPS8lvP4gAe/X4yuDwKBgQC6 +AGaavMWwGleSi3o/s3/3nrgufYnxmPg8woQx3MUPD3XALTKUtI6Pl4E2pn1t7/aE +Ci2b1RZSInYqLBnEz+2GIf1vpIAEIvp5IozTQQF2m/Uz5A4iwYgFzbimwVmTAwVT +ENZt6uZxa4n8l/nI46kgAPgaruNYU/sbfiuWHq65IQKBgCMYfLML4oeRt+Xm5wcy +T+PrP0qKt20wW/nqn4TVjuO606ywD2aLS/AJ96k04maEEAebahy6ODoEjNb3erQW +VGsMydDBZ0QlMs6x7LDh3JLP0+JNETCezd1Nl20ykjpaoZ8Unzf/gpgaVjZON+wF +ON1xMW7NBrs9xvcjhBVgtn6r +-----END PRIVATE KEY-----