github.com/symfony-cli/symfony-cli@v0.0.0-20240514161054-ece2df437dfa/local/proxy/proxy_test.go (about) 1 /* 2 * Copyright (c) 2021-present Fabien Potencier <fabien@symfony.com> 3 * 4 * This file is part of Symfony CLI project 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Affero General Public License as 8 * published by the Free Software Foundation, either version 3 of the 9 * License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Affero General Public License for more details. 15 * 16 * You should have received a copy of the GNU Affero General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package proxy 21 22 import ( 23 "crypto/tls" 24 "crypto/x509" 25 "io" 26 "log" 27 "net/http" 28 "net/http/httptest" 29 "net/url" 30 "os" 31 "path/filepath" 32 "strconv" 33 "strings" 34 "time" 35 36 "github.com/mitchellh/go-homedir" 37 "github.com/rs/zerolog" 38 "github.com/symfony-cli/cert" 39 "github.com/symfony-cli/symfony-cli/local/pid" 40 . "gopkg.in/check.v1" 41 ) 42 43 func (s *ProxySuite) TestProxy(c *C) { 44 ca, err := cert.NewCA(filepath.Join("testdata/certs")) 45 c.Assert(err, IsNil) 46 c.Assert(ca.LoadCA(), IsNil) 47 48 homedir.Reset() 49 os.Setenv("HOME", "testdata") 50 defer homedir.Reset() 51 defer os.RemoveAll("testdata/.symfony5") 52 53 p := New(&Config{ 54 domains: map[string]string{ 55 "symfony": "symfony_com", 56 "symfony-no-tls": "symfony_com_no_tls", 57 "symfony2": "symfony_com2", 58 }, 59 TLD: "wip", 60 path: "testdata/.symfony5/proxy.json", 61 }, ca, log.New(zerolog.New(os.Stderr), "", 0), true) 62 os.MkdirAll("testdata/.symfony5", 0755) 63 err = p.Save() 64 c.Assert(err, IsNil) 65 66 // Test the 404 fallback 67 { 68 rr := httptest.NewRecorder() 69 req, err := http.NewRequest("GET", "/foo", nil) 70 req.Host = "localhost" 71 c.Assert(err, IsNil) 72 p.proxy.ServeHTTP(rr, req) 73 c.Check(rr.Code, Equals, http.StatusNotFound) 74 } 75 76 // Test serving the proxy.pac 77 { 78 rr := httptest.NewRecorder() 79 req, err := http.NewRequest("GET", "/proxy.pac", nil) 80 req.Host = "localhost" 81 c.Assert(err, IsNil) 82 p.proxy.ServeHTTP(rr, req) 83 c.Assert(rr.Code, Equals, http.StatusOK) 84 c.Check(rr.Header().Get("Content-type"), Equals, "application/x-ns-proxy-autoconfig") 85 } 86 87 // Test serving the index 88 { 89 rr := httptest.NewRecorder() 90 req, err := http.NewRequest("GET", "/", nil) 91 req.Host = "localhost" 92 c.Assert(err, IsNil) 93 p.proxy.ServeHTTP(rr, req) 94 c.Assert(rr.Code, Equals, http.StatusOK) 95 c.Check(strings.Contains(rr.Body.String(), "symfony.wip"), Equals, true) 96 } 97 98 // Test the proxy 99 frontend := httptest.NewServer(p.proxy) 100 defer frontend.Close() 101 frontendUrl, _ := url.Parse(frontend.URL) 102 cert, err := x509.ParseCertificate(ca.AsTLS().Certificate[0]) 103 c.Assert(err, IsNil) 104 certpool := x509.NewCertPool() 105 certpool.AddCert(cert) 106 transport := &http.Transport{ 107 Proxy: http.ProxyURL(frontendUrl), 108 TLSClientConfig: &tls.Config{ 109 RootCAs: certpool, 110 }, 111 } 112 client := &http.Client{ 113 Transport: transport, 114 Timeout: 1 * time.Second, 115 } 116 117 // Test proxying a request to a non-registered project 118 { 119 req, _ := http.NewRequest("GET", "https://foo.wip/", nil) 120 req.Close = true 121 122 res, err := client.Do(req) 123 c.Assert(err, IsNil) 124 c.Assert(res.StatusCode, Equals, http.StatusNotFound) 125 body, _ := io.ReadAll(res.Body) 126 c.Check(strings.Contains(string(body), "not linked"), Equals, true) 127 } 128 129 // Test proxying a request to a registered project but not started 130 { 131 req, _ := http.NewRequest("GET", "https://symfony.wip/", nil) 132 req.Close = true 133 134 res, err := client.Do(req) 135 c.Assert(err, IsNil) 136 c.Assert(res.StatusCode, Equals, http.StatusNotFound) 137 body, _ := io.ReadAll(res.Body) 138 c.Check(strings.Contains(string(body), "not started"), Equals, true) 139 } 140 /* 141 // Test proxying a request to a registered project and started 142 { 143 backend := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 144 w.WriteHeader(200) 145 w.Write([]byte(`symfony.wip`)) 146 })) 147 cert, err := ca.CreateCert([]string{"localhost", "127.0.0.1"}) 148 c.Assert(err, IsNil) 149 backend.TLS = &tls.Config{ 150 Certificates: []tls.Certificate{cert}, 151 } 152 backend.StartTLS() 153 defer backend.Close() 154 backendURL, err := url.Parse(backend.URL) 155 c.Assert(err, IsNil) 156 157 p := pid.New("symfony_com", nil) 158 port, _ := strconv.Atoi(backendURL.Port()) 159 p.Write(os.Getpid(), port, "https") 160 161 req, _ := http.NewRequest("GET", "https://symfony.wip/", nil) 162 req.Close = true 163 164 res, err := client.Do(req) 165 c.Assert(err, IsNil) 166 c.Assert(res.StatusCode, Equals, http.StatusOK) 167 body, _ := io.ReadAll(res.Body) 168 c.Check(string(body), Equals, "symfony.wip") 169 } 170 */ 171 // Test proxying a request to a registered project but no TLS 172 { 173 backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 174 w.WriteHeader(200) 175 w.Write([]byte(`http://symfony-no-tls.wip`)) 176 })) 177 defer backend.Close() 178 backendURL, err := url.Parse(backend.URL) 179 c.Assert(err, IsNil) 180 181 p := pid.New("symfony_com_no_tls", nil) 182 port, _ := strconv.Atoi(backendURL.Port()) 183 p.Write(os.Getpid(), port, "http") 184 185 req, _ := http.NewRequest("GET", "http://symfony-no-tls.wip/", nil) 186 req.Close = true 187 188 res, err := client.Do(req) 189 c.Assert(err, IsNil) 190 body, _ := io.ReadAll(res.Body) 191 c.Assert(res.StatusCode, Equals, http.StatusOK) 192 c.Assert(string(body), Equals, "http://symfony-no-tls.wip") 193 } 194 195 // Test proxying a request to an outside backend 196 { 197 backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 198 w.WriteHeader(200) 199 })) 200 defer backend.Close() 201 req, _ := http.NewRequest("GET", backend.URL, nil) 202 req.Close = true 203 204 res, err := client.Do(req) 205 c.Assert(err, IsNil) 206 c.Assert(res.StatusCode, Equals, http.StatusOK) 207 } 208 /* 209 // Test proxying a request over HTTP2 210 http2.ConfigureTransport(transport) 211 { 212 backend := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 213 w.WriteHeader(200) 214 if r.Proto == "HTTP/2.0" { 215 w.Write([]byte(`http2`)) 216 return 217 } 218 w.Write([]byte(`symfony.wip`)) 219 })) 220 cert, err := ca.CreateCert([]string{"localhost", "127.0.0.1"}) 221 c.Assert(err, IsNil) 222 backend.TLS = &tls.Config{ 223 Certificates: []tls.Certificate{cert}, 224 NextProtos: []string{"h2", "http/1.1"}, 225 } 226 backend.StartTLS() 227 defer backend.Close() 228 backendURL, err := url.Parse(backend.URL) 229 c.Assert(err, IsNil) 230 231 p := pid.New("symfony_com2", nil) 232 port, _ := strconv.Atoi(backendURL.Port()) 233 p.Write(os.Getpid(), port, "https") 234 235 req, _ := http.NewRequest("GET", "https://symfony2.wip/", nil) 236 req.Close = true 237 238 res, err := client.Do(req) 239 c.Assert(err, IsNil) 240 c.Assert(res.StatusCode, Equals, http.StatusOK) 241 body, _ := ioutil.ReadAll(res.Body) 242 c.Check(string(body), Equals, "http2") 243 } 244 */ 245 }