Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
Experimental IETF-standard HTTP/3 support (known issue exists) (#2727)
* Begin WIP integration of HTTP/3 support * http3: Set actual Handler, make fakeClosePacketConn type for UDP sockets Also use latest quic-go for ALPN fix * Manually keep track of and close HTTP/3 listeners * Update quic-go after working through some http3 bugs * Fix go mod * Make http3 optional for now
Matt Holt committed
Sep 10, 2019 at 08:03 UTC
0c8ad52be127add6f2c050230f1f166ecbde813c
6 files changed
+153
-6
cmd/main.go
+1
-1
@@ -33,7 +33,7 @@ import (
33
func Main() {
34
caddy.TrapSignals()
35
36
- if len(os.Args) <= 1 {
36
+ if len(os.Args) < 2 {
37
fmt.Println(usageString())
38
return
39
}
go.mod
+1
-1
@@ -17,6 +17,7 @@ require (
17
github.com/imdario/mergo v0.3.7 // indirect
18
github.com/klauspost/compress v1.7.1-0.20190613161414-0b31f265a57b
19
github.com/klauspost/cpuid v1.2.1
20
+ github.com/lucas-clemente/quic-go v0.7.1-0.20190908032346-fc962d18373a
21
github.com/mholt/certmagic v0.6.2
22
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
23
github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48
@@ -26,7 +27,6 @@ require (
27
github.com/starlight-go/starlight v0.0.0-20181207205707-b06f321544f3
28
go.starlark.net v0.0.0-20190604130855-6ddc71c0ba77
29
golang.org/x/net v0.0.0-20190603091049-60506f45cf65
29
- golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e // indirect
30
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
31
gopkg.in/yaml.v2 v2.2.2 // indirect
32
)
go.sum
+42
-2
@@ -6,23 +6,36 @@ github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITg
6
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
7
github.com/Masterminds/sprig v2.20.0+incompatible h1:dJTKKuUkYW3RMFdQFXPU/s6hg10RgctmTjRcbZ98Ap8=
8
github.com/Masterminds/sprig v2.20.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
9
+github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY=
10
+github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE=
11
github.com/andybalholm/brotli v0.0.0-20190704151324-71eb68cc467c h1:pBKtfXLqKZ+GPHGjlBheGaXK2lddydUG3XhWGrYjxOA=
12
github.com/andybalholm/brotli v0.0.0-20190704151324-71eb68cc467c/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
13
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
14
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
15
+github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
16
+github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
17
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
18
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
19
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
20
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
21
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
22
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
23
github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M=
24
github.com/go-acme/lego v2.6.0+incompatible h1:KxcEWOF5hKtgou4xIqPaXSRF9DoO4OJ90ndwdK6YH/k=
25
github.com/go-acme/lego v2.6.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M=
26
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
27
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
28
+github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
29
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
30
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
31
+github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
32
+github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
33
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
34
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
35
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
36
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
37
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
38
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
39
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
40
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
41
github.com/ilibs/json5 v1.0.1 h1:3e14wUQM8PyK6Hf1bM+zAQFxfG+N5oZj35x5vCNeQ58=
@@ -34,6 +47,14 @@ github.com/klauspost/compress v1.7.1-0.20190613161414-0b31f265a57b/go.mod h1:RyI
47
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
48
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
49
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
50
+github.com/lucas-clemente/quic-go v0.7.1-0.20190908032346-fc962d18373a h1:4NDhBYEqjdNTQhlkLK8u4FGq1mMDQv4V4MLDSS5oCS0=
51
+github.com/lucas-clemente/quic-go v0.7.1-0.20190908032346-fc962d18373a/go.mod h1:iP3S21xvg0qlsEAz+goZ/qfptsfhshjzkbhEK6Ka3Fg=
52
+github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFFIO5Gh4hQ=
53
+github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE=
54
+github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg=
55
+github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
56
+github.com/marten-seemann/qtls v0.4.0 h1:HM9ftULNeuhGiCliIfPKvp5VDJw6pvi/Ghq6PYf7B0E=
57
+github.com/marten-seemann/qtls v0.4.0/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc=
58
github.com/mholt/certmagic v0.6.2 h1:yy9cKm3rtxdh12SW4E51lzG3Eo6N59LEOfBQ0CTnMms=
59
github.com/mholt/certmagic v0.6.2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY=
60
github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM=
@@ -42,6 +63,11 @@ github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8
63
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
64
github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48 h1:BM/fjd7MfvZuyoHXLv3YlWNIuNb47PLp6EyFBL1KIMg=
65
github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190902132743-e4903c4dea48/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU=
66
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
67
+github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
68
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
69
+github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
70
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
71
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
72
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
73
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
@@ -60,23 +86,37 @@ go.starlark.net v0.0.0-20190604130855-6ddc71c0ba77/go.mod h1:c1/X6cHgvdXj6pUlmWK
86
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
87
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
88
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
89
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
90
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
91
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
92
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
93
+golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
94
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
95
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
96
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
97
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
98
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
99
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
100
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
101
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
102
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
103
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
71
-golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c=
72
-golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
104
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
105
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
106
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
107
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
108
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
109
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
110
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
111
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
112
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
113
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
114
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
115
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
116
gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA=
117
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
118
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
119
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
120
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
121
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
122
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
listeners.go
+59
-1
@@ -16,6 +16,7 @@ package caddy
16
17
import (
18
"fmt"
19
+ "log"
20
"net"
21
"strconv"
22
"strings"
@@ -53,13 +54,41 @@ func Listen(network, addr string) (net.Listener, error) {
54
return &fakeCloseListener{usage: &lnUsage.usage, key: lnKey, Listener: ln}, nil
55
}
56
57
+// ListenPacket returns a net.PacketConn suitable for use in a Caddy module.
58
+// Always be sure to close the PacketConn when you are done.
59
+func ListenPacket(network, addr string) (net.PacketConn, error) {
60
+ lnKey := network + "/" + addr
61
+
62
+ listenersMu.Lock()
63
+ defer listenersMu.Unlock()
64
+
65
+ // if listener already exists, increment usage counter, then return listener
66
+ if lnUsage, ok := listeners[lnKey]; ok {
67
+ atomic.AddInt32(&lnUsage.usage, 1)
68
+ log.Printf("[DEBUG] %s: Usage counter should not go above 2 or maybe 3, is now: %d", lnKey, atomic.LoadInt32(&lnUsage.usage)) // TODO: remove
69
+ return &fakeClosePacketConn{usage: &lnUsage.usage, key: lnKey, PacketConn: lnUsage.pc}, nil
70
+ }
71
+
72
+ // or, create new one and save it
73
+ pc, err := net.ListenPacket(network, addr)
74
+ if err != nil {
75
+ return nil, err
76
+ }
77
+
78
+ // make sure to start its usage counter at 1
79
+ lnUsage := &listenerUsage{usage: 1, pc: pc}
80
+ listeners[lnKey] = lnUsage
81
+
82
+ return &fakeClosePacketConn{usage: &lnUsage.usage, key: lnKey, PacketConn: pc}, nil
83
+}
84
+
85
// fakeCloseListener's Close() method is a no-op. This allows
86
// stopping servers that are using the listener without giving
87
// up the socket; thus, servers become hot-swappable while the
88
// listener remains running. Listeners should be re-wrapped in
89
// a new fakeCloseListener each time the listener is reused.
90
type fakeCloseListener struct {
62
- closed int32 // accessed atomically
91
+ closed int32 // accessed atomically - TODO: this needs to be shared across the whole app instance, not to cross instance boundaries... hmmm... see #2658 (still relevant?)
92
usage *int32 // accessed atomically
93
key string
94
net.Listener
@@ -146,6 +175,34 @@ func (fcl *fakeCloseListener) fakeClosedErr() error {
175
}
176
}
177
178
+type fakeClosePacketConn struct {
179
+ closed int32 // accessed atomically - TODO: this needs to be shared across the whole app instance, not to cross instance boundaries... hmmm... see #2658 (still relevant?)
180
+ usage *int32 // accessed atomically
181
+ key string
182
+ net.PacketConn
183
+}
184
+
185
+func (fcpc *fakeClosePacketConn) Close() error {
186
+ log.Println("[DEBUG] Fake-closing underlying packet conn") // TODO: remove this
187
+
188
+ if atomic.CompareAndSwapInt32(&fcpc.closed, 0, 1) {
189
+ // since we're no longer using this listener,
190
+ // decrement the usage counter and, if no one
191
+ // else is using it, close underlying listener
192
+ if atomic.AddInt32(fcpc.usage, -1) == 0 {
193
+ listenersMu.Lock()
194
+ delete(listeners, fcpc.key)
195
+ listenersMu.Unlock()
196
+ err := fcpc.PacketConn.Close()
197
+ if err != nil {
198
+ return err
199
+ }
200
+ }
201
+ }
202
+
203
+ return nil
204
+}
205
+
206
// ErrFakeClosed is the underlying error value returned by
207
// fakeCloseListener.Accept() after Close() has been called,
208
// indicating that it is pretending to be closed so that the
@@ -158,6 +215,7 @@ var errFakeClosed = fmt.Errorf("listener 'closed' 😉")
215
type listenerUsage struct {
216
usage int32 // accessed atomically
217
ln net.Listener
218
+ pc net.PacketConn
219
}
220
221
var (
modules/caddyhttp/caddyhttp.go
+47
-1
@@ -31,6 +31,7 @@ import (
31
32
"github.com/caddyserver/caddy/v2"
33
"github.com/caddyserver/caddy/v2/modules/caddytls"
34
+ "github.com/lucas-clemente/quic-go/http3"
35
"github.com/mholt/certmagic"
36
)
37
@@ -50,7 +51,9 @@ type App struct {
51
GracePeriod caddy.Duration `json:"grace_period,omitempty"`
52
Servers map[string]*Server `json:"servers,omitempty"`
53
53
- servers []*http.Server
54
+ servers []*http.Server
55
+ h3servers []*http3.Server
56
+ h3listeners []net.PacketConn
57
58
ctx caddy.Context
59
}
@@ -187,6 +190,27 @@ func (app *App) Start() error {
190
return fmt.Errorf("%s/%s: making TLS configuration: %v", network, addr, err)
191
}
192
ln = tls.NewListener(ln, tlsCfg)
193
+
194
+ /////////
195
+ // TODO: HTTP/3 support is experimental for now
196
+ if srv.ExperimentalHTTP3 {
197
+ log.Printf("[INFO] Enabling experimental HTTP/3 listener on %s", addr)
198
+ h3ln, err := caddy.ListenPacket("udp", addr)
199
+ if err != nil {
200
+ return fmt.Errorf("getting HTTP/3 UDP listener: %v", err)
201
+ }
202
+ h3srv := &http3.Server{
203
+ Server: &http.Server{
204
+ Addr: addr,
205
+ Handler: srv,
206
+ TLSConfig: tlsCfg,
207
+ },
208
+ }
209
+ go h3srv.Serve(h3ln)
210
+ app.h3servers = append(app.h3servers, h3srv)
211
+ app.h3listeners = append(app.h3listeners, h3ln)
212
+ }
213
+ /////////
214
}
215
216
go s.Serve(ln)
@@ -212,6 +236,28 @@ func (app *App) Stop() error {
236
return err
237
}
238
}
239
+ // TODO: Closing the http3.Server is the right thing to do,
240
+ // however, doing so sometimes causes connections from clients
241
+ // to fail after config reloads due to a bug that is yet
242
+ // unsolved: https://github.com/caddyserver/caddy/pull/2727
243
+ // for _, s := range app.h3servers {
244
+ // // TODO: CloseGracefully, once implemented upstream
245
+ // // (see https://github.com/lucas-clemente/quic-go/issues/2103)
246
+ // err := s.Close()
247
+ // if err != nil {
248
+ // return err
249
+ // }
250
+ // }
251
+ // as of September 2019, closing the http3.Server
252
+ // instances doesn't close their underlying listeners
253
+ // so we have todo that ourselves
254
+ // (see https://github.com/lucas-clemente/quic-go/issues/2103)
255
+ for _, pc := range app.h3listeners {
256
+ err := pc.Close()
257
+ if err != nil {
258
+ return err
259
+ }
260
+ }
261
return nil
262
}
263
modules/caddyhttp/server.go
+3
@@ -43,6 +43,9 @@ type Server struct {
43
MaxRehandles *int `json:"max_rehandles,omitempty"`
44
StrictSNIHost bool `json:"strict_sni_host,omitempty"`
45
46
+ // This field is not subject to compatibility promises
47
+ ExperimentalHTTP3 bool `json:"experimental_http3,omitempty"`
48
+
49
tlsApp *caddytls.TLS
50
}
51