github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/server/controller_https_test.go (about)

     1  package server
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"net/http"
     7  	"path/filepath"
     8  	"time"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/sirupsen/logrus"
    14  
    15  	"github.com/pyroscope-io/pyroscope/pkg/config"
    16  	"github.com/pyroscope-io/pyroscope/pkg/exporter"
    17  	"github.com/pyroscope-io/pyroscope/pkg/health"
    18  	"github.com/pyroscope-io/pyroscope/pkg/parser"
    19  	"github.com/pyroscope-io/pyroscope/pkg/storage"
    20  	"github.com/pyroscope-io/pyroscope/pkg/testing"
    21  )
    22  
    23  var _ = Describe("server", func() {
    24  	testing.WithConfig(func(cfg **config.Config) {
    25  		const testDataDir string = "testdata"
    26  		const tlsCertificateFile string = "cert.pem"
    27  		const tlsKeyFile string = "key.pem"
    28  		Describe("HTTPS", func() {
    29  			It("Should serve HTTPS when TLSCertificateFile and TLSKeyFile is defined",
    30  				func() {
    31  					defer GinkgoRecover()
    32  					const addr = ":10046"
    33  					(*cfg).Server.APIBindAddr = addr
    34  					(*cfg).Server.TLSCertificateFile = filepath.Join(testDataDir, tlsCertificateFile)
    35  					(*cfg).Server.TLSKeyFile = filepath.Join(testDataDir, tlsKeyFile)
    36  
    37  					s, err := storage.New(
    38  						storage.NewConfig(&(*cfg).Server),
    39  						logrus.StandardLogger(),
    40  						prometheus.NewRegistry(),
    41  						new(health.Controller),
    42  						storage.NoopApplicationMetadataService{},
    43  					)
    44  					Expect(err).ToNot(HaveOccurred())
    45  					defer s.Close()
    46  					e, _ := exporter.NewExporter(nil, nil)
    47  					c, _ := New(Config{
    48  						Configuration:           &(*cfg).Server,
    49  						Storage:                 s,
    50  						Ingester:                parser.New(logrus.StandardLogger(), s, e),
    51  						Logger:                  logrus.New(),
    52  						MetricsRegisterer:       prometheus.NewRegistry(),
    53  						ExportedMetricsRegistry: prometheus.NewRegistry(),
    54  						Notifier:                mockNotifier{},
    55  					})
    56  					c.dir = http.Dir(testDataDir)
    57  
    58  					startController(c, "https", addr)
    59  
    60  					tr := &http.Transport{
    61  						TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    62  					}
    63  
    64  					client := &http.Client{Transport: tr}
    65  					resHTTPS, _ := client.Get(fmt.Sprintf("https://localhost%s", addr))
    66  					resHTTP, _ := client.Get(fmt.Sprintf("http://localhost%s", addr))
    67  
    68  					defer resHTTPS.Body.Close()
    69  					defer resHTTP.Body.Close()
    70  					defer c.Stop()
    71  
    72  					Expect(resHTTPS.StatusCode).To(Equal(http.StatusOK))
    73  					Expect(resHTTP.StatusCode).To(Equal(http.StatusBadRequest))
    74  				},
    75  			)
    76  			It("Should serve HTTP when TLSCertificateFile & TLSKeyFile is undefined",
    77  				func() {
    78  					defer GinkgoRecover()
    79  					const addr = ":10046"
    80  					(*cfg).Server.APIBindAddr = addr
    81  
    82  					s, err := storage.New(
    83  						storage.NewConfig(&(*cfg).Server),
    84  						logrus.StandardLogger(),
    85  						prometheus.NewRegistry(),
    86  						new(health.Controller),
    87  						storage.NoopApplicationMetadataService{},
    88  					)
    89  					Expect(err).ToNot(HaveOccurred())
    90  					defer s.Close()
    91  					e, _ := exporter.NewExporter(nil, nil)
    92  					c, _ := New(Config{
    93  						Configuration:           &(*cfg).Server,
    94  						Storage:                 s,
    95  						Ingester:                parser.New(logrus.StandardLogger(), s, e),
    96  						Logger:                  logrus.New(),
    97  						MetricsRegisterer:       prometheus.NewRegistry(),
    98  						ExportedMetricsRegistry: prometheus.NewRegistry(),
    99  						Notifier:                mockNotifier{},
   100  					})
   101  					c.dir = http.Dir(testDataDir)
   102  
   103  					startController(c, "http", addr)
   104  
   105  					tr := &http.Transport{
   106  						TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   107  					}
   108  
   109  					client := &http.Client{Transport: tr}
   110  					resHTTP, _ := client.Get(fmt.Sprintf("http://localhost%s", addr))
   111  					_, errHTTPS := client.Get(fmt.Sprintf("https://localhost%s", addr))
   112  
   113  					defer resHTTP.Body.Close()
   114  					defer c.Stop()
   115  
   116  					Expect(resHTTP.StatusCode).To(Equal(http.StatusOK))
   117  					Expect(errHTTPS).To(HaveOccurred())
   118  				},
   119  			)
   120  		})
   121  	})
   122  })
   123  
   124  func startController(c *Controller, protocol string, addr string) {
   125  	startSync := make(chan struct{})
   126  	go func() {
   127  		defer GinkgoRecover()
   128  		err := c.startSync(startSync)
   129  		Expect(err).ToNot(HaveOccurred())
   130  	}()
   131  	<-startSync
   132  	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
   133  	httpClient := &http.Client{Transport: tr}
   134  	var err error
   135  	var res *http.Response
   136  	for i := 0; i < 100; i++ {
   137  		res, err = httpClient.Get(fmt.Sprintf("%s://localhost%s", protocol, addr))
   138  		if err == nil && res.StatusCode == http.StatusOK {
   139  			return
   140  		}
   141  		time.Sleep(50 * time.Millisecond)
   142  	}
   143  	err = fmt.Errorf("failed to wait for server startup %v %v", err, res)
   144  	Expect(err).ToNot(HaveOccurred())
   145  }