git.iko.soy/typeable/oauth2-proxy
on 0e4962a help sign in
1001 lines 30 kB history raw
1package http
3import (
4 "context"
5 "errors"
6 "fmt"
7 "io"
8 "net/http"
9 "os"
11 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
12 . "github.com/onsi/ginkgo/v2"
13 . "github.com/onsi/gomega"
14 . "github.com/onsi/gomega/gleak"
17const hello = "Hello World!"
19var _ = Describe("Server", func() {
20 handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
21 rw.Write([]byte(hello))
22 })
24 Context("NewServer", func() {
25 type newServerTableInput struct {
26 opts Opts
27 expectedErr error
28 expectHTTPListener bool
29 expectTLSListener bool
30 ipv6 bool
31 }
33 DescribeTable("When creating the new server from the options", func(in *newServerTableInput) {
34 if in.ipv6 {
35 skipDevContainer()
36 }
37 srv, err := NewServer(in.opts)
38 if in.expectedErr != nil {
39 Expect(err).To(MatchError(ContainSubstring(in.expectedErr.Error())))
40 Expect(srv).To(BeNil())
41 return
42 }
44 Expect(err).ToNot(HaveOccurred())
46 s, ok := srv.(*server)
47 Expect(ok).To(BeTrue())
49 Expect(s.listener != nil).To(Equal(in.expectHTTPListener))
50 if in.expectHTTPListener {
51 Expect(s.listener.Close()).To(Succeed())
52 }
53 Expect(s.tlsListener != nil).To(Equal(in.expectTLSListener))
54 if in.expectTLSListener {
55 Expect(s.tlsListener.Close()).To(Succeed())
56 }
57 },
58 Entry("with an ipv4 valid http bind address", &newServerTableInput{
59 opts: Opts{
60 Handler: handler,
61 BindAddress: "127.0.0.1:0",
62 },
63 expectedErr: nil,
64 expectHTTPListener: true,
65 expectTLSListener: false,
66 }),
67 Entry("with an ipv4 valid https bind address, with no TLS config", &newServerTableInput{
68 opts: Opts{
69 Handler: handler,
70 SecureBindAddress: "127.0.0.1:0",
71 },
72 expectedErr: errors.New("error setting up TLS listener: no TLS config provided"),
73 expectHTTPListener: false,
74 expectTLSListener: false,
75 }),
76 Entry("with an ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
77 opts: Opts{
78 Handler: handler,
79 SecureBindAddress: "127.0.0.1:0",
80 TLS: &options.TLS{
81 Key: &ipv4KeyDataSource,
82 Cert: &ipv4CertDataSource,
83 },
84 },
85 expectedErr: nil,
86 expectHTTPListener: false,
87 expectTLSListener: true,
88 }),
89 Entry("with a both a ipv4 valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
90 opts: Opts{
91 Handler: handler,
92 BindAddress: "127.0.0.1:0",
93 SecureBindAddress: "127.0.0.1:0",
94 TLS: &options.TLS{
95 Key: &ipv4KeyDataSource,
96 Cert: &ipv4CertDataSource,
97 },
98 },
99 expectedErr: nil,
100 expectHTTPListener: true,
101 expectTLSListener: true,
102 }),
103 Entry("with a \"-\" for the bind address", &newServerTableInput{
104 opts: Opts{
105 Handler: handler,
106 BindAddress: "-",
107 },
108 expectedErr: nil,
109 expectHTTPListener: false,
110 expectTLSListener: false,
111 }),
112 Entry("with a \"-\" for the secure bind address", &newServerTableInput{
113 opts: Opts{
114 Handler: handler,
115 SecureBindAddress: "-",
116 },
117 expectedErr: nil,
118 expectHTTPListener: false,
119 expectTLSListener: false,
120 }),
121 Entry("with an ipv4 invalid bind address scheme", &newServerTableInput{
122 opts: Opts{
123 Handler: handler,
124 BindAddress: "invalid://127.0.0.1:0",
125 },
126 expectedErr: errors.New("error setting up listener: listen (invalid, 127.0.0.1:0) failed: listen invalid: unknown network invalid"),
127 expectHTTPListener: false,
128 expectTLSListener: false,
129 }),
130 Entry("with an ipv4 invalid secure bind address scheme", &newServerTableInput{
131 opts: Opts{
132 Handler: handler,
133 SecureBindAddress: "invalid://127.0.0.1:0",
134 TLS: &options.TLS{
135 Key: &ipv4KeyDataSource,
136 Cert: &ipv4CertDataSource,
137 },
138 },
139 expectedErr: nil,
140 expectHTTPListener: false,
141 expectTLSListener: true,
142 }),
143 Entry("with an ipv4 invalid bind address port", &newServerTableInput{
144 opts: Opts{
145 Handler: handler,
146 BindAddress: "127.0.0.1:a",
147 },
148 expectedErr: errors.New("error setting up listener: listen (tcp, 127.0.0.1:a) failed: listen tcp: "),
149 expectHTTPListener: false,
150 expectTLSListener: false,
151 }),
152 Entry("with an ipv4 invalid secure bind address port", &newServerTableInput{
153 opts: Opts{
154 Handler: handler,
155 SecureBindAddress: "127.0.0.1:a",
156 TLS: &options.TLS{
157 Key: &ipv4KeyDataSource,
158 Cert: &ipv4CertDataSource,
159 },
160 },
161 expectedErr: errors.New("error setting up TLS listener: listen (127.0.0.1:a) failed: listen tcp: "),
162 expectHTTPListener: false,
163 expectTLSListener: false,
164 }),
165 Entry("with an ipv4 invalid TLS key", &newServerTableInput{
166 opts: Opts{
167 Handler: handler,
168 SecureBindAddress: "127.0.0.1:0",
169 TLS: &options.TLS{
170 Key: &options.SecretSource{
171 Value: []byte("invalid"),
172 },
173 Cert: &ipv4CertDataSource,
174 },
175 },
176 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
177 expectHTTPListener: false,
178 expectTLSListener: false,
179 }),
180 Entry("with an ipv4 invalid TLS cert", &newServerTableInput{
181 opts: Opts{
182 Handler: handler,
183 SecureBindAddress: "127.0.0.1:0",
184 TLS: &options.TLS{
185 Key: &ipv4KeyDataSource,
186 Cert: &options.SecretSource{
187 Value: []byte("invalid"),
188 },
189 },
190 },
191 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in certificate input"),
192 expectHTTPListener: false,
193 expectTLSListener: false,
194 }),
195 Entry("with an ipv4 address, with no TLS key", &newServerTableInput{
196 opts: Opts{
197 Handler: handler,
198 SecureBindAddress: "127.0.0.1:0",
199 TLS: &options.TLS{
200 Cert: &ipv4CertDataSource,
201 },
202 },
203 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
204 expectHTTPListener: false,
205 expectTLSListener: false,
206 }),
207 Entry("with an ipv4 address, with no TLS cert", &newServerTableInput{
208 opts: Opts{
209 Handler: handler,
210 SecureBindAddress: "127.0.0.1:0",
211 TLS: &options.TLS{
212 Key: &ipv4KeyDataSource,
213 },
214 },
215 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
216 expectHTTPListener: false,
217 expectTLSListener: false,
218 }),
219 Entry("when the ipv4 bind address is prefixed with the http scheme", &newServerTableInput{
220 opts: Opts{
221 Handler: handler,
222 BindAddress: "http://127.0.0.1:0",
223 },
224 expectedErr: nil,
225 expectHTTPListener: true,
226 expectTLSListener: false,
227 }),
228 Entry("when the ipv4 secure bind address is prefixed with the https scheme", &newServerTableInput{
229 opts: Opts{
230 Handler: handler,
231 SecureBindAddress: "https://127.0.0.1:0",
232 TLS: &options.TLS{
233 Key: &ipv4KeyDataSource,
234 Cert: &ipv4CertDataSource,
235 },
236 },
237 expectedErr: nil,
238 expectHTTPListener: false,
239 expectTLSListener: true,
240 }),
241 Entry("with an ipv4 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
242 opts: Opts{
243 Handler: handler,
244 SecureBindAddress: "127.0.0.1:0",
245 TLS: &options.TLS{
246 Key: &ipv4KeyDataSource,
247 Cert: &ipv4CertDataSource,
248 MinVersion: "TLS1.3",
249 },
250 },
251 expectedErr: nil,
252 expectHTTPListener: false,
253 expectTLSListener: true,
254 }),
255 Entry("with an ipv4 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
256 opts: Opts{
257 Handler: handler,
258 SecureBindAddress: "127.0.0.1:0",
259 TLS: &options.TLS{
260 Key: &ipv4KeyDataSource,
261 Cert: &ipv4CertDataSource,
262 MinVersion: "TLS1.42",
263 },
264 },
265 expectedErr: errors.New("error setting up TLS listener: unknown TLS MinVersion config provided"),
266 expectHTTPListener: false,
267 expectTLSListener: true,
268 }),
269 Entry("with an ipv4 valid https bind address, and valid TLS config with CipherSuites", &newServerTableInput{
270 opts: Opts{
271 Handler: handler,
272 SecureBindAddress: "127.0.0.1:0",
273 TLS: &options.TLS{
274 Key: &ipv4KeyDataSource,
275 Cert: &ipv4CertDataSource,
276 CipherSuites: []string{
277 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
278 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
279 },
280 },
281 },
282 expectedErr: nil,
283 expectHTTPListener: false,
284 expectTLSListener: true,
285 }),
286 Entry("with an ipv4 valid https bind address, and invalid TLS config with unknown CipherSuites", &newServerTableInput{
287 opts: Opts{
288 Handler: handler,
289 SecureBindAddress: "127.0.0.1:0",
290 TLS: &options.TLS{
291 Key: &ipv4KeyDataSource,
292 Cert: &ipv4CertDataSource,
293 CipherSuites: []string{
294 "TLS_RSA_WITH_RC4_64_SHA",
295 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
296 },
297 },
298 },
299 expectedErr: errors.New("error setting up TLS listener: could not parse cipher suites: unknown TLS cipher suite name specified \"TLS_RSA_WITH_RC4_64_SHA\""),
300 expectHTTPListener: false,
301 expectTLSListener: true,
302 }),
303 Entry("with an ipv6 valid http bind address", &newServerTableInput{
304 opts: Opts{
305 Handler: handler,
306 BindAddress: "[::1]:0",
307 },
308 expectedErr: nil,
309 expectHTTPListener: true,
310 expectTLSListener: false,
311 ipv6: true,
312 }),
313 Entry("with an ipv6 valid https bind address, with no TLS config", &newServerTableInput{
314 opts: Opts{
315 Handler: handler,
316 SecureBindAddress: "[::1]:0",
317 },
318 expectedErr: errors.New("error setting up TLS listener: no TLS config provided"),
319 expectHTTPListener: false,
320 expectTLSListener: false,
321 ipv6: true,
322 }),
323 Entry("with an ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
324 opts: Opts{
325 Handler: handler,
326 SecureBindAddress: "[::1]:0",
327 TLS: &options.TLS{
328 Key: &ipv6KeyDataSource,
329 Cert: &ipv6CertDataSource,
330 },
331 },
332 expectedErr: nil,
333 expectHTTPListener: false,
334 expectTLSListener: true,
335 ipv6: true,
336 }),
337 Entry("with a both a ipv6 valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
338 opts: Opts{
339 Handler: handler,
340 BindAddress: "[::1]:0",
341 SecureBindAddress: "[::1]:0",
342 TLS: &options.TLS{
343 Key: &ipv6KeyDataSource,
344 Cert: &ipv6CertDataSource,
345 },
346 },
347 expectedErr: nil,
348 expectHTTPListener: true,
349 expectTLSListener: true,
350 ipv6: true,
351 }),
352 Entry("with an ipv6 invalid bind address scheme", &newServerTableInput{
353 opts: Opts{
354 Handler: handler,
355 BindAddress: "invalid://[::1]:0",
356 },
357 expectedErr: errors.New("error setting up listener: listen (invalid, [::1]:0) failed: listen invalid: unknown network invalid"),
358 expectHTTPListener: false,
359 expectTLSListener: false,
360 ipv6: true,
361 }),
362 Entry("with an ipv6 invalid secure bind address scheme", &newServerTableInput{
363 opts: Opts{
364 Handler: handler,
365 SecureBindAddress: "invalid://[::1]:0",
366 TLS: &options.TLS{
367 Key: &ipv6KeyDataSource,
368 Cert: &ipv6CertDataSource,
369 },
370 },
371 expectedErr: nil,
372 expectHTTPListener: false,
373 expectTLSListener: true,
374 ipv6: true,
375 }),
376 Entry("with an ipv6 invalid bind address port", &newServerTableInput{
377 opts: Opts{
378 Handler: handler,
379 BindAddress: "[::1]:a",
380 },
381 expectedErr: errors.New("error setting up listener: listen (tcp, [::1]:a) failed: listen tcp: "),
382 expectHTTPListener: false,
383 expectTLSListener: false,
384 ipv6: true,
385 }),
386 Entry("with an ipv6 invalid secure bind address port", &newServerTableInput{
387 opts: Opts{
388 Handler: handler,
389 SecureBindAddress: "[::1]:a",
390 TLS: &options.TLS{
391 Key: &ipv6KeyDataSource,
392 Cert: &ipv6CertDataSource,
393 },
394 },
395 expectedErr: errors.New("error setting up TLS listener: listen ([::1]:a) failed: listen tcp: "),
396 expectHTTPListener: false,
397 expectTLSListener: false,
398 ipv6: true,
399 }),
400 Entry("with an ipv6 invalid TLS key", &newServerTableInput{
401 opts: Opts{
402 Handler: handler,
403 SecureBindAddress: "[::1]:0",
404 TLS: &options.TLS{
405 Key: &options.SecretSource{
406 Value: []byte("invalid"),
407 },
408 Cert: &ipv6CertDataSource,
409 },
410 },
411 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
412 expectHTTPListener: false,
413 expectTLSListener: false,
414 ipv6: true,
415 }),
416 Entry("with an ipv6 invalid TLS cert", &newServerTableInput{
417 opts: Opts{
418 Handler: handler,
419 SecureBindAddress: "[::1]:0",
420 TLS: &options.TLS{
421 Key: &ipv6KeyDataSource,
422 Cert: &options.SecretSource{
423 Value: []byte("invalid"),
424 },
425 },
426 },
427 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in certificate input"),
428 expectHTTPListener: false,
429 expectTLSListener: false,
430 ipv6: true,
431 }),
432 Entry("with an ipv6 address, with no TLS key", &newServerTableInput{
433 opts: Opts{
434 Handler: handler,
435 SecureBindAddress: "[::1]:0",
436 TLS: &options.TLS{
437 Cert: &ipv6CertDataSource,
438 },
439 },
440 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
441 expectHTTPListener: false,
442 expectTLSListener: false,
443 ipv6: true,
444 }),
445 Entry("with an ipv6 address, with no TLS cert", &newServerTableInput{
446 opts: Opts{
447 Handler: handler,
448 SecureBindAddress: "[::1]:0",
449 TLS: &options.TLS{
450 Key: &ipv6KeyDataSource,
451 },
452 },
453 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
454 expectHTTPListener: false,
455 expectTLSListener: false,
456 ipv6: true,
457 }),
458 Entry("when the ipv6 bind address is prefixed with the http scheme", &newServerTableInput{
459 opts: Opts{
460 Handler: handler,
461 BindAddress: "http://[::1]:0",
462 },
463 expectedErr: nil,
464 expectHTTPListener: true,
465 expectTLSListener: false,
466 ipv6: true,
467 }),
468 Entry("when the ipv6 secure bind address is prefixed with the https scheme", &newServerTableInput{
469 opts: Opts{
470 Handler: handler,
471 SecureBindAddress: "https://[::1]:0",
472 TLS: &options.TLS{
473 Key: &ipv6KeyDataSource,
474 Cert: &ipv6CertDataSource,
475 },
476 },
477 expectedErr: nil,
478 expectHTTPListener: false,
479 expectTLSListener: true,
480 ipv6: true,
481 }),
482 Entry("with an ipv6 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
483 opts: Opts{
484 Handler: handler,
485 SecureBindAddress: "[::1]:0",
486 TLS: &options.TLS{
487 Key: &ipv6KeyDataSource,
488 Cert: &ipv6CertDataSource,
489 MinVersion: "TLS1.3",
490 },
491 },
492 expectedErr: nil,
493 expectHTTPListener: false,
494 expectTLSListener: true,
495 ipv6: true,
496 }),
497 Entry("with an ipv6 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
498 opts: Opts{
499 Handler: handler,
500 SecureBindAddress: "[::1]:0",
501 TLS: &options.TLS{
502 Key: &ipv6KeyDataSource,
503 Cert: &ipv6CertDataSource,
504 MinVersion: "TLS1.42",
505 },
506 },
507 expectedErr: errors.New("error setting up TLS listener: unknown TLS MinVersion config provided"),
508 expectHTTPListener: false,
509 expectTLSListener: true,
510 ipv6: true,
511 }),
512 Entry("with an ipv6 valid https bind address, and valid TLS config with CipherSuites", &newServerTableInput{
513 opts: Opts{
514 Handler: handler,
515 SecureBindAddress: "[::1]:0",
516 TLS: &options.TLS{
517 Key: &ipv4KeyDataSource,
518 Cert: &ipv4CertDataSource,
519 CipherSuites: []string{
520 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
521 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
522 },
523 },
524 },
525 expectedErr: nil,
526 expectHTTPListener: false,
527 expectTLSListener: true,
528 ipv6: true,
529 }),
530 Entry("with an ipv6 valid https bind address, and invalid TLS config with unknown CipherSuites", &newServerTableInput{
531 opts: Opts{
532 Handler: handler,
533 SecureBindAddress: "[::1]:0",
534 TLS: &options.TLS{
535 Key: &ipv4KeyDataSource,
536 Cert: &ipv4CertDataSource,
537 CipherSuites: []string{
538 "TLS_RSA_WITH_RC4_64_SHA",
539 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
540 },
541 },
542 },
543 expectedErr: errors.New("error setting up TLS listener: could not parse cipher suites: unknown TLS cipher suite name specified \"TLS_RSA_WITH_RC4_64_SHA\""),
544 expectHTTPListener: false,
545 expectTLSListener: true,
546 ipv6: true,
547 }),
548 )
549 })
551 Context("Start", func() {
552 var srv Server
553 var ctx context.Context
554 var cancel context.CancelFunc
556 BeforeEach(func() {
557 ctx, cancel = context.WithCancel(context.Background())
558 })
560 AfterEach(func() {
561 cancel()
562 Eventually(Goroutines).ShouldNot(HaveLeaked())
564 })
566 Context("with an ipv4 http server", func() {
567 var listenAddr string
569 BeforeEach(func() {
570 var err error
571 srv, err = NewServer(Opts{
572 Handler: handler,
573 BindAddress: "127.0.0.1:0",
574 })
575 Expect(err).ToNot(HaveOccurred())
577 s, ok := srv.(*server)
578 Expect(ok).To(BeTrue())
580 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
581 })
583 It("Starts the server and serves the handler", func() {
584 go func() {
585 defer GinkgoRecover()
586 Expect(srv.Start(ctx)).To(Succeed())
587 }()
589 resp, err := httpGet(ctx, listenAddr)
590 Expect(err).ToNot(HaveOccurred())
591 Expect(resp.StatusCode).To(Equal(http.StatusOK))
593 body, err := io.ReadAll(resp.Body)
594 Expect(err).ToNot(HaveOccurred())
595 Expect(string(body)).To(Equal(hello))
596 })
598 It("Stops the server when the context is cancelled", func() {
599 go func() {
600 defer GinkgoRecover()
601 Expect(srv.Start(ctx)).To(Succeed())
602 }()
604 _, err := httpGet(ctx, listenAddr)
605 Expect(err).ToNot(HaveOccurred())
607 cancel()
609 Eventually(func() error {
610 _, err := httpGet(ctx, listenAddr)
611 return err
612 }).Should(HaveOccurred())
613 })
614 })
616 Context("with an ipv4 https server", func() {
617 var secureListenAddr string
619 BeforeEach(func() {
620 var err error
621 srv, err = NewServer(Opts{
622 Handler: handler,
623 SecureBindAddress: "127.0.0.1:0",
624 TLS: &options.TLS{
625 Key: &ipv4KeyDataSource,
626 Cert: &ipv4CertDataSource,
627 },
628 })
629 Expect(err).ToNot(HaveOccurred())
631 s, ok := srv.(*server)
632 Expect(ok).To(BeTrue())
634 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
635 })
637 It("Starts the server and serves the handler", func() {
638 go func() {
639 defer GinkgoRecover()
640 Expect(srv.Start(ctx)).To(Succeed())
641 }()
643 resp, err := httpGet(ctx, secureListenAddr)
644 Expect(err).ToNot(HaveOccurred())
645 Expect(resp.StatusCode).To(Equal(http.StatusOK))
647 body, err := io.ReadAll(resp.Body)
648 Expect(err).ToNot(HaveOccurred())
649 Expect(string(body)).To(Equal(hello))
650 })
652 It("Stops the server when the context is cancelled", func() {
653 go func() {
654 defer GinkgoRecover()
655 Expect(srv.Start(ctx)).To(Succeed())
656 }()
658 _, err := httpGet(ctx, secureListenAddr)
659 Expect(err).ToNot(HaveOccurred())
661 cancel()
663 Eventually(func() error {
664 _, err := httpGet(ctx, secureListenAddr)
665 return err
666 }).Should(HaveOccurred())
667 })
669 It("Serves the certificate provided", func() {
670 go func() {
671 defer GinkgoRecover()
672 Expect(srv.Start(ctx)).To(Succeed())
673 }()
675 resp, err := httpGet(ctx, secureListenAddr)
676 Expect(err).ToNot(HaveOccurred())
677 Expect(resp.StatusCode).To(Equal(http.StatusOK))
679 Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
680 Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
681 Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv4CertData))
682 })
683 })
685 Context("with both an ipv4 http and an ipv4 https server", func() {
686 var listenAddr, secureListenAddr string
688 BeforeEach(func() {
689 var err error
690 srv, err = NewServer(Opts{
691 Handler: handler,
692 BindAddress: "127.0.0.1:0",
693 SecureBindAddress: "127.0.0.1:0",
694 TLS: &options.TLS{
695 Key: &ipv4KeyDataSource,
696 Cert: &ipv4CertDataSource,
697 },
698 })
699 Expect(err).ToNot(HaveOccurred())
701 s, ok := srv.(*server)
702 Expect(ok).To(BeTrue())
704 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
705 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
706 })
708 It("Starts the server and serves the handler on http", func() {
709 go func() {
710 defer GinkgoRecover()
711 Expect(srv.Start(ctx)).To(Succeed())
712 }()
714 resp, err := httpGet(ctx, listenAddr)
715 Expect(err).ToNot(HaveOccurred())
716 Expect(resp.StatusCode).To(Equal(http.StatusOK))
718 body, err := io.ReadAll(resp.Body)
719 Expect(err).ToNot(HaveOccurred())
720 Expect(string(body)).To(Equal(hello))
721 })
723 It("Starts the server and serves the handler on https", func() {
724 go func() {
725 defer GinkgoRecover()
726 Expect(srv.Start(ctx)).To(Succeed())
727 }()
729 resp, err := httpGet(ctx, secureListenAddr)
730 Expect(err).ToNot(HaveOccurred())
731 Expect(resp.StatusCode).To(Equal(http.StatusOK))
733 body, err := io.ReadAll(resp.Body)
734 Expect(err).ToNot(HaveOccurred())
735 Expect(string(body)).To(Equal(hello))
736 })
738 It("Stops both servers when the context is cancelled", func() {
739 go func() {
740 defer GinkgoRecover()
741 Expect(srv.Start(ctx)).To(Succeed())
742 }()
744 _, err := httpGet(ctx, listenAddr)
745 Expect(err).ToNot(HaveOccurred())
746 _, err = httpGet(ctx, secureListenAddr)
747 Expect(err).ToNot(HaveOccurred())
749 cancel()
751 Eventually(func() error {
752 _, err := httpGet(ctx, listenAddr)
753 return err
754 }).Should(HaveOccurred())
755 Eventually(func() error {
756 _, err := httpGet(ctx, secureListenAddr)
757 return err
758 }).Should(HaveOccurred())
759 })
760 })
762 Context("with an ipv6 http server", func() {
763 var listenAddr string
765 BeforeEach(func() {
766 skipDevContainer()
767 var err error
768 srv, err = NewServer(Opts{
769 Handler: handler,
770 BindAddress: "[::1]:0",
771 })
772 Expect(err).ToNot(HaveOccurred())
774 s, ok := srv.(*server)
775 Expect(ok).To(BeTrue())
777 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
778 })
780 It("Starts the server and serves the handler", func() {
781 go func() {
782 defer GinkgoRecover()
783 Expect(srv.Start(ctx)).To(Succeed())
784 }()
786 resp, err := httpGet(ctx, listenAddr)
787 Expect(err).ToNot(HaveOccurred())
788 Expect(resp.StatusCode).To(Equal(http.StatusOK))
790 body, err := io.ReadAll(resp.Body)
791 Expect(err).ToNot(HaveOccurred())
792 Expect(string(body)).To(Equal(hello))
793 })
795 It("Stops the server when the context is cancelled", func() {
796 go func() {
797 defer GinkgoRecover()
798 Expect(srv.Start(ctx)).To(Succeed())
799 }()
801 _, err := httpGet(ctx, listenAddr)
802 Expect(err).ToNot(HaveOccurred())
804 cancel()
806 Eventually(func() error {
807 _, err := httpGet(ctx, listenAddr)
808 return err
809 }).Should(HaveOccurred())
810 })
811 })
813 Context("with an ipv6 https server", func() {
814 var secureListenAddr string
816 BeforeEach(func() {
817 skipDevContainer()
818 var err error
819 srv, err = NewServer(Opts{
820 Handler: handler,
821 SecureBindAddress: "[::1]:0",
822 TLS: &options.TLS{
823 Key: &ipv6KeyDataSource,
824 Cert: &ipv6CertDataSource,
825 },
826 })
827 Expect(err).ToNot(HaveOccurred())
829 s, ok := srv.(*server)
830 Expect(ok).To(BeTrue())
832 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
833 })
835 It("Starts the server and serves the handler", func() {
836 go func() {
837 defer GinkgoRecover()
838 Expect(srv.Start(ctx)).To(Succeed())
839 }()
841 resp, err := httpGet(ctx, secureListenAddr)
842 Expect(err).ToNot(HaveOccurred())
843 Expect(resp.StatusCode).To(Equal(http.StatusOK))
845 body, err := io.ReadAll(resp.Body)
846 Expect(err).ToNot(HaveOccurred())
847 Expect(string(body)).To(Equal(hello))
848 })
850 It("Stops the server when the context is cancelled", func() {
851 go func() {
852 defer GinkgoRecover()
853 Expect(srv.Start(ctx)).To(Succeed())
854 }()
856 _, err := httpGet(ctx, secureListenAddr)
857 Expect(err).ToNot(HaveOccurred())
859 cancel()
861 Eventually(func() error {
862 _, err := httpGet(ctx, secureListenAddr)
863 return err
864 }).Should(HaveOccurred())
865 })
867 It("Serves the certificate provided", func() {
868 go func() {
869 defer GinkgoRecover()
870 Expect(srv.Start(ctx)).To(Succeed())
871 }()
873 resp, err := httpGet(ctx, secureListenAddr)
874 Expect(err).ToNot(HaveOccurred())
875 Expect(resp.StatusCode).To(Equal(http.StatusOK))
877 Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
878 Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
879 Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv6CertData))
880 })
881 })
883 Context("with both an ipv6 http and an ipv6 https server", func() {
884 var listenAddr, secureListenAddr string
886 BeforeEach(func() {
887 skipDevContainer()
888 var err error
889 srv, err = NewServer(Opts{
890 Handler: handler,
891 BindAddress: "[::1]:0",
892 SecureBindAddress: "[::1]:0",
893 TLS: &options.TLS{
894 Key: &ipv6KeyDataSource,
895 Cert: &ipv6CertDataSource,
896 },
897 })
898 Expect(err).ToNot(HaveOccurred())
900 s, ok := srv.(*server)
901 Expect(ok).To(BeTrue())
903 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
904 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
905 })
907 It("Starts the server and serves the handler on http", func() {
908 go func() {
909 defer GinkgoRecover()
910 Expect(srv.Start(ctx)).To(Succeed())
911 }()
913 resp, err := httpGet(ctx, listenAddr)
914 Expect(err).ToNot(HaveOccurred())
915 Expect(resp.StatusCode).To(Equal(http.StatusOK))
917 body, err := io.ReadAll(resp.Body)
918 Expect(err).ToNot(HaveOccurred())
919 Expect(string(body)).To(Equal(hello))
920 })
922 It("Starts the server and serves the handler on https", func() {
923 go func() {
924 defer GinkgoRecover()
925 Expect(srv.Start(ctx)).To(Succeed())
926 }()
928 resp, err := httpGet(ctx, secureListenAddr)
929 Expect(err).ToNot(HaveOccurred())
930 Expect(resp.StatusCode).To(Equal(http.StatusOK))
932 body, err := io.ReadAll(resp.Body)
933 Expect(err).ToNot(HaveOccurred())
934 Expect(string(body)).To(Equal(hello))
935 })
937 It("Stops both servers when the context is cancelled", func() {
938 go func() {
939 defer GinkgoRecover()
940 Expect(srv.Start(ctx)).To(Succeed())
941 }()
943 _, err := httpGet(ctx, listenAddr)
944 Expect(err).ToNot(HaveOccurred())
945 _, err = httpGet(ctx, secureListenAddr)
946 Expect(err).ToNot(HaveOccurred())
948 cancel()
950 Eventually(func() error {
951 _, err := httpGet(ctx, listenAddr)
952 return err
953 }).Should(HaveOccurred())
954 Eventually(func() error {
955 _, err := httpGet(ctx, secureListenAddr)
956 return err
957 }).Should(HaveOccurred())
958 })
959 })
960 })
962 Context("getNetworkScheme", func() {
963 DescribeTable("should return the scheme", func(in, expected string) {
964 Expect(getNetworkScheme(in)).To(Equal(expected))
965 },
966 Entry("ipv4 address with no scheme", "127.0.0.1:0", "tcp"),
967 Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "tcp"),
968 Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "tcp"),
969 Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "unix"),
970 Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "random"),
971 Entry("ipv6 address with no scheme", "[::1]:0", "tcp"),
972 Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "tcp"),
973 Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "tcp"),
974 Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "unix"),
975 Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "random"),
976 )
977 })
979 Context("getListenAddress", func() {
980 DescribeTable("should remove the scheme", func(in, expected string) {
981 Expect(getListenAddress(in)).To(Equal(expected))
982 },
983 Entry("ipv4 address with no scheme", "127.0.0.1:0", "127.0.0.1:0"),
984 Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "127.0.0.1:0"),
985 Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "192.168.0.1:1"),
986 Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "172.168.16.2:2"),
987 Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "10.10.10.10:10"),
988 Entry("ipv6 address with no scheme", "[::1]:0", "[::1]:0"),
989 Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "[::1]:0"),
990 Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "[::ffff:c0a8:1]:1"),
991 Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "[::ffff:aca8:1002]:2"),
992 Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "[::ffff:a0a:a0a]:10"),
993 )
994 })
995})
997func skipDevContainer() {
998 if os.Getenv("DEVCONTAINER") != "" {
999 Skip("Skipping testing in DevContainer environment")