@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 01:00 UTC

master
go 112 lines 3.51 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddyevents
16
17 import (
18 "context"
19 "crypto/ecdsa"
20 "crypto/elliptic"
21 "crypto/rand"
22 "crypto/tls"
23 "crypto/x509"
24 "crypto/x509/pkix"
25 "math/big"
26 "testing"
27 "time"
28
29 "github.com/caddyserver/certmagic"
30 "go.uber.org/zap"
31 )
32
33 func benchCert(tb testing.TB) tls.Certificate {
34 tb.Helper()
35 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
36 if err != nil {
37 tb.Fatal(err)
38 }
39 tmpl := &x509.Certificate{
40 SerialNumber: big.NewInt(1),
41 Subject: pkix.Name{CommonName: "example.com"},
42 DNSNames: []string{"example.com"},
43 NotBefore: time.Now().Add(-time.Hour),
44 NotAfter: time.Now().Add(24 * time.Hour),
45 }
46 der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
47 if err != nil {
48 tb.Fatal(err)
49 }
50 leaf, err := x509.ParseCertificate(der)
51 if err != nil {
52 tb.Fatal(err)
53 }
54 return tls.Certificate{Certificate: [][]byte{der}, PrivateKey: key, Leaf: leaf}
55 }
56
57 // benchmarkCertLookup measures CertMagic's GetCertificate, which Caddy calls
58 // once per TLS handshake. CertMagic emits "tls_get_certificate" there, so this
59 // shows what the events app costs a handshake when nothing is subscribed.
60 func benchmarkCertLookup(b *testing.B, onEvent func(context.Context, string, map[string]any) error, shouldEmit func(string) bool) {
61 b.Helper()
62
63 var cfg *certmagic.Config
64 cache := certmagic.NewCache(certmagic.CacheOptions{
65 GetConfigForCert: func(certmagic.Certificate) (*certmagic.Config, error) { return cfg, nil },
66 Logger: zap.NewNop(),
67 })
68 b.Cleanup(cache.Stop)
69
70 cfg = certmagic.New(cache, certmagic.Config{
71 Storage: &certmagic.FileStorage{Path: b.TempDir()},
72 Logger: zap.NewNop(),
73 OnEvent: onEvent,
74 ShouldEmitFunc: shouldEmit,
75 })
76 if _, err := cfg.CacheUnmanagedTLSCertificate(context.Background(), benchCert(b), nil); err != nil {
77 b.Fatal(err)
78 }
79
80 hello := &tls.ClientHelloInfo{
81 ServerName: "example.com",
82 CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
83 SupportedCurves: []tls.CurveID{tls.CurveP256},
84 SupportedPoints: []uint8{0},
85 SupportedVersions: []uint16{tls.VersionTLS13, tls.VersionTLS12},
86 SignatureSchemes: []tls.SignatureScheme{tls.ECDSAWithP256AndSHA256},
87 }
88 if _, err := cfg.GetCertificate(hello); err != nil {
89 b.Fatal(err)
90 }
91
92 b.ReportAllocs()
93 b.ResetTimer()
94 for i := 0; i < b.N; i++ {
95 if _, err := cfg.GetCertificate(hello); err != nil {
96 b.Fatal(err)
97 }
98 }
99 }
100
101 // Caddy always binds the TLS app to the events app, so this is what a
102 // handshake pays for the tls_get_certificate event in a config that has no
103 // subscriptions at all -- which is every config that does not use the events
104 // app. The hook body is what (*caddytls.TLS).onEvent does.
105 func BenchmarkCertLookupWithEventsApp(b *testing.B) {
106 app, ctx, cancel := testApp(b)
107 defer cancel()
108
109 benchmarkCertLookup(b, func(_ context.Context, name string, data map[string]any) error {
110 return app.Emit(ctx, name, data).Aborted
111 }, app.ShouldEmit)
112 }