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
Move listen address functions into caddy package; fix unix bug
Matthew Holt committed
Jul 8, 2019 at 16:46 UTC
d25008d2c8e2eb5f96b2b37a1cca5b4e140cfe8d
4 files changed
+94
-66
listeners.go
+72
@@ -17,6 +17,8 @@ package caddy
17
import (
18
"fmt"
19
"net"
20
+ "strconv"
21
+ "strings"
22
"sync"
23
"sync/atomic"
24
"time"
@@ -160,3 +162,73 @@ var (
162
listeners = make(map[string]*listenerUsage)
163
listenersMu sync.Mutex
164
)
165
+
166
+// ParseListenAddr parses addr, a string of the form "network/host:port"
167
+// (with any part optional) into its component parts. Because a port can
168
+// also be a port range, there may be multiple addresses returned.
169
+func ParseListenAddr(addr string) (network string, addrs []string, err error) {
170
+ var host, port string
171
+ network, host, port, err = SplitListenAddr(addr)
172
+ if network == "" {
173
+ network = "tcp"
174
+ }
175
+ if err != nil {
176
+ return
177
+ }
178
+ if network == "unix" {
179
+ addrs = []string{host}
180
+ return
181
+ }
182
+ ports := strings.SplitN(port, "-", 2)
183
+ if len(ports) == 1 {
184
+ ports = append(ports, ports[0])
185
+ }
186
+ var start, end int
187
+ start, err = strconv.Atoi(ports[0])
188
+ if err != nil {
189
+ return
190
+ }
191
+ end, err = strconv.Atoi(ports[1])
192
+ if err != nil {
193
+ return
194
+ }
195
+ if end < start {
196
+ err = fmt.Errorf("end port must be greater than start port")
197
+ return
198
+ }
199
+ for p := start; p <= end; p++ {
200
+ addrs = append(addrs, net.JoinHostPort(host, fmt.Sprintf("%d", p)))
201
+ }
202
+ return
203
+}
204
+
205
+// SplitListenAddr splits a into its network, host, and port components.
206
+// Note that port may be a port range, or omitted for unix sockets.
207
+func SplitListenAddr(a string) (network, host, port string, err error) {
208
+ if idx := strings.Index(a, "/"); idx >= 0 {
209
+ network = strings.ToLower(strings.TrimSpace(a[:idx]))
210
+ a = a[idx+1:]
211
+ }
212
+ if network == "unix" {
213
+ host = a
214
+ return
215
+ }
216
+ host, port, err = net.SplitHostPort(a)
217
+ return
218
+}
219
+
220
+// JoinListenAddr combines network, host, and port into a single
221
+// address string of the form "network/host:port". Port may be a
222
+// port range. For unix sockets, the network should be "unix" and
223
+// the path to the socket should be given in the host argument.
224
+func JoinListenAddr(network, host, port string) string {
225
+ var a string
226
+ if network != "" {
227
+ a = network + "/"
228
+ }
229
+ a += host
230
+ if port != "" {
231
+ a += ":" + port
232
+ }
233
+ return a
234
+}
listeners_test.go
renamed
+15
-6
@@ -12,7 +12,7 @@
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
-package caddyhttp
15
+package caddy
16
17
import (
18
"reflect"
@@ -62,8 +62,13 @@ func TestSplitListenerAddr(t *testing.T) {
62
expectNetwork: "udp",
63
expectErr: true,
64
},
65
+ {
66
+ input: "unix//foo/bar",
67
+ expectNetwork: "unix",
68
+ expectHost: "/foo/bar",
69
+ },
70
} {
66
- actualNetwork, actualHost, actualPort, err := splitListenAddr(tc.input)
71
+ actualNetwork, actualHost, actualPort, err := SplitListenAddr(tc.input)
72
if tc.expectErr && err == nil {
73
t.Errorf("Test %d: Expected error but got: %v", i, err)
74
}
@@ -119,8 +124,12 @@ func TestJoinListenerAddr(t *testing.T) {
124
network: "udp", host: "", port: "1234",
125
expect: "udp/:1234",
126
},
127
+ {
128
+ network: "unix", host: "/foo/bar", port: "",
129
+ expect: "unix//foo/bar",
130
+ },
131
} {
123
- actual := joinListenAddr(tc.network, tc.host, tc.port)
132
+ actual := JoinListenAddr(tc.network, tc.host, tc.port)
133
if actual != tc.expect {
134
t.Errorf("Test %d: Expected '%s' but got '%s'", i, tc.expect, actual)
135
}
@@ -165,9 +174,9 @@ func TestParseListenerAddr(t *testing.T) {
174
expectAddrs: []string{"localhost:1234"},
175
},
176
{
168
- input: "unix/localhost:1234-1236",
177
+ input: "unix//foo/bar",
178
expectNetwork: "unix",
170
- expectAddrs: []string{"localhost:1234", "localhost:1235", "localhost:1236"},
179
+ expectAddrs: []string{"/foo/bar"},
180
},
181
{
182
input: "localhost:1234-1234",
@@ -185,7 +194,7 @@ func TestParseListenerAddr(t *testing.T) {
194
expectAddrs: []string{"localhost:0"},
195
},
196
} {
188
- actualNetwork, actualAddrs, err := parseListenAddr(tc.input)
197
+ actualNetwork, actualAddrs, err := ParseListenAddr(tc.input)
198
if tc.expectErr && err == nil {
199
t.Errorf("Test %d: Expected error but got: %v", i, err)
200
}
modules/caddyhttp/caddyhttp.go
+6
-59
@@ -96,7 +96,7 @@ func (app *App) Validate() error {
96
lnAddrs := make(map[string]string)
97
for srvName, srv := range app.Servers {
98
for _, addr := range srv.Listen {
99
- netw, expanded, err := parseListenAddr(addr)
99
+ netw, expanded, err := caddy.ParseListenAddr(addr)
100
if err != nil {
101
return fmt.Errorf("invalid listener address '%s': %v", addr, err)
102
}
@@ -137,7 +137,7 @@ func (app *App) Start() error {
137
}
138
139
for _, lnAddr := range srv.Listen {
140
- network, addrs, err := parseListenAddr(lnAddr)
140
+ network, addrs, err := caddy.ParseListenAddr(lnAddr)
141
if err != nil {
142
return fmt.Errorf("%s: parsing listen address '%s': %v", srvName, lnAddr, err)
143
}
@@ -289,7 +289,7 @@ func (app *App) automaticHTTPS() error {
289
290
// create HTTP->HTTPS redirects
291
for _, addr := range srv.Listen {
292
- netw, host, port, err := splitListenAddr(addr)
292
+ netw, host, port, err := caddy.SplitListenAddr(addr)
293
if err != nil {
294
return fmt.Errorf("%s: invalid listener address: %v", srvName, addr)
295
}
@@ -298,7 +298,7 @@ func (app *App) automaticHTTPS() error {
298
if httpPort == 0 {
299
httpPort = DefaultHTTPPort
300
}
301
- httpRedirLnAddr := joinListenAddr(netw, host, strconv.Itoa(httpPort))
301
+ httpRedirLnAddr := caddy.JoinListenAddr(netw, host, strconv.Itoa(httpPort))
302
lnAddrMap[httpRedirLnAddr] = struct{}{}
303
304
if parts := strings.SplitN(port, "-", 2); len(parts) == 2 {
@@ -339,7 +339,7 @@ func (app *App) automaticHTTPS() error {
339
var lnAddrs []string
340
mapLoop:
341
for addr := range lnAddrMap {
342
- netw, addrs, err := parseListenAddr(addr)
342
+ netw, addrs, err := caddy.ParseListenAddr(addr)
343
if err != nil {
344
continue
345
}
@@ -364,7 +364,7 @@ func (app *App) automaticHTTPS() error {
364
func (app *App) listenerTaken(network, address string) bool {
365
for _, srv := range app.Servers {
366
for _, addr := range srv.Listen {
367
- netw, addrs, err := parseListenAddr(addr)
367
+ netw, addrs, err := caddy.ParseListenAddr(addr)
368
if err != nil || netw != network {
369
continue
370
}
@@ -425,59 +425,6 @@ func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
425
// sometimes better than a nil Handler pointer.
426
var emptyHandler HandlerFunc = func(w http.ResponseWriter, r *http.Request) error { return nil }
427
428
-func parseListenAddr(a string) (network string, addrs []string, err error) {
429
- var host, port string
430
- network, host, port, err = splitListenAddr(a)
431
- if network == "" {
432
- network = "tcp"
433
- }
434
- if err != nil {
435
- return
436
- }
437
- ports := strings.SplitN(port, "-", 2)
438
- if len(ports) == 1 {
439
- ports = append(ports, ports[0])
440
- }
441
- var start, end int
442
- start, err = strconv.Atoi(ports[0])
443
- if err != nil {
444
- return
445
- }
446
- end, err = strconv.Atoi(ports[1])
447
- if err != nil {
448
- return
449
- }
450
- if end < start {
451
- err = fmt.Errorf("end port must be greater than start port")
452
- return
453
- }
454
- for p := start; p <= end; p++ {
455
- addrs = append(addrs, net.JoinHostPort(host, fmt.Sprintf("%d", p)))
456
- }
457
- return
458
-}
459
-
460
-func splitListenAddr(a string) (network, host, port string, err error) {
461
- if idx := strings.Index(a, "/"); idx >= 0 {
462
- network = strings.ToLower(strings.TrimSpace(a[:idx]))
463
- a = a[idx+1:]
464
- }
465
- host, port, err = net.SplitHostPort(a)
466
- return
467
-}
468
-
469
-func joinListenAddr(network, host, port string) string {
470
- var a string
471
- if network != "" {
472
- a = network + "/"
473
- }
474
- a += host
475
- if port != "" {
476
- a += ":" + port
477
- }
478
- return a
479
-}
480
-
428
const (
429
// DefaultHTTPPort is the default port for HTTP.
430
DefaultHTTPPort = 80
modules/caddyhttp/server.go
+1
-1
@@ -156,7 +156,7 @@ func (s *Server) enforcementHandler(w http.ResponseWriter, r *http.Request, next
156
157
func (s *Server) listenersUseAnyPortOtherThan(otherPort int) bool {
158
for _, lnAddr := range s.Listen {
159
- _, addrs, err := parseListenAddr(lnAddr)
159
+ _, addrs, err := caddy.ParseListenAddr(lnAddr)
160
if err == nil {
161
for _, a := range addrs {
162
_, port, err := net.SplitHostPort(a)