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