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
Add file-server and reverse-proxy subcommands
Matthew Holt committed
Oct 3, 2019 at 16:00 UTC
c11e3bffd698cfb1e19a21097ff4a65cf10e28b0
3 files changed
+248
-2
caddyconfig/httpcaddyfile/addresses.go
+4
-2
@@ -161,7 +161,7 @@ func (st *ServerType) listenerAddrsForServerBlockKey(sblock serverBlock, key str
161
}
162
addr = addr.Normalize()
163
164
- lnPort := defaultPort
164
+ lnPort := DefaultPort
165
if addr.Port != "" {
166
// port explicitly defined
167
lnPort = addr.Port
@@ -327,6 +327,8 @@ func (a Address) Key() string {
327
}
328
329
const (
330
- defaultPort = "2015"
330
+ // DefaultPort is the default port to use.
331
+ DefaultPort = "2015"
332
+
333
caseSensitivePath = false // TODO: Used?
334
)
modules/caddyhttp/fileserver/command.go
new
+106
@@ -0,0 +1,106 @@
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 fileserver
16
+
17
+import (
18
+ "encoding/json"
19
+ "flag"
20
+ "log"
21
+
22
+ "github.com/caddyserver/caddy/v2"
23
+ "github.com/caddyserver/caddy/v2/caddyconfig"
24
+ caddycmd "github.com/caddyserver/caddy/v2/cmd"
25
+ "github.com/caddyserver/caddy/v2/modules/caddyhttp"
26
+)
27
+
28
+func init() {
29
+ caddycmd.RegisterCommand(caddycmd.Command{
30
+ Name: "file-server",
31
+ Func: cmdFileServer,
32
+ Usage: "[--domain <example.com>] [--path <path>] [--listen <addr>] [--browse]",
33
+ Short: "Spins up a production-ready file server",
34
+ Long: `
35
+A simple but production-ready file server. Useful for quick deployments,
36
+demos, and development.
37
+
38
+If a qualifying hostname is specified with --domain, the server will use
39
+HTTPS if domain validation succeeds. Ensure A/AAAA records are properly
40
+configured before using this option.
41
+
42
+The listener's socket address can be customized with the --listen flag.
43
+
44
+If --browse is enabled, requests for folders without an index file will
45
+respond with a file listing.`,
46
+ Flags: func() *flag.FlagSet {
47
+ fs := flag.NewFlagSet("file-server", flag.ExitOnError)
48
+ fs.String("domain", "", "Domain name at which to serve the files")
49
+ fs.String("root", "", "The path to the root of the site")
50
+ fs.String("listen", "", "The address to which to bind the listener")
51
+ fs.Bool("browse", false, "Whether to enable directory browsing")
52
+ return fs
53
+ }(),
54
+ })
55
+}
56
+
57
+func cmdFileServer(fs caddycmd.Flags) (int, error) {
58
+ domain := fs.String("domain")
59
+ root := fs.String("root")
60
+ listen := fs.String("listen")
61
+ browse := fs.Bool("browse")
62
+
63
+ handler := FileServer{Root: root}
64
+ if browse {
65
+ handler.Browse = new(Browse)
66
+ }
67
+
68
+ route := caddyhttp.Route{
69
+ HandlersRaw: []json.RawMessage{
70
+ caddyconfig.JSONModuleObject(handler, "handler", "file_server", nil),
71
+ },
72
+ }
73
+ if domain != "" {
74
+ route.MatcherSetsRaw = []map[string]json.RawMessage{
75
+ map[string]json.RawMessage{
76
+ "host": caddyconfig.JSON(caddyhttp.MatchHost{domain}, nil),
77
+ },
78
+ }
79
+ }
80
+
81
+ server := &caddyhttp.Server{
82
+ Routes: caddyhttp.RouteList{route},
83
+ }
84
+ if listen != "" {
85
+ server.Listen = []string{listen}
86
+ }
87
+
88
+ httpApp := caddyhttp.App{
89
+ Servers: map[string]*caddyhttp.Server{"static": server},
90
+ }
91
+
92
+ cfg := &caddy.Config{
93
+ AppsRaw: map[string]json.RawMessage{
94
+ "http": caddyconfig.JSON(httpApp, nil),
95
+ },
96
+ }
97
+
98
+ err := caddy.Run(cfg)
99
+ if err != nil {
100
+ return caddy.ExitCodeFailedStartup, err
101
+ }
102
+
103
+ log.Println("Caddy 2 serving static files")
104
+
105
+ select {}
106
+}
modules/caddyhttp/reverseproxy/command.go
new
+138
@@ -0,0 +1,138 @@
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 reverseproxy
16
+
17
+import (
18
+ "encoding/json"
19
+ "flag"
20
+ "log"
21
+ "net/http"
22
+ "net/url"
23
+ "strings"
24
+
25
+ "github.com/caddyserver/caddy/v2"
26
+ "github.com/caddyserver/caddy/v2/caddyconfig"
27
+ "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
28
+ caddycmd "github.com/caddyserver/caddy/v2/cmd"
29
+ "github.com/caddyserver/caddy/v2/modules/caddyhttp"
30
+ "github.com/caddyserver/caddy/v2/modules/caddyhttp/headers"
31
+ "github.com/mholt/certmagic"
32
+)
33
+
34
+func init() {
35
+ caddycmd.RegisterCommand(caddycmd.Command{
36
+ Name: "reverse-proxy",
37
+ Func: cmdReverseProxy,
38
+ Usage: "[--from <addr>] [--to <addr>]",
39
+ Short: "A quick and production-ready reverse proxy",
40
+ Long: `
41
+A simple but production-ready reverse proxy. Useful for quick deployments,
42
+demos, and development.
43
+
44
+Simply shuttles HTTP traffic from the --from address to the --to address.
45
+
46
+If the --from address has a domain name, Caddy will attempt to serve the
47
+proxy over HTTPS with a certificate.
48
+`,
49
+ Flags: func() *flag.FlagSet {
50
+ fs := flag.NewFlagSet("file-server", flag.ExitOnError)
51
+ fs.String("from", "", "Address to receive traffic on")
52
+ fs.String("to", "", "Upstream address to proxy traffic to")
53
+ return fs
54
+ }(),
55
+ })
56
+}
57
+
58
+func cmdReverseProxy(fs caddycmd.Flags) (int, error) {
59
+ from := fs.String("from")
60
+ to := fs.String("to")
61
+
62
+ if from == "" {
63
+ from = "localhost:" + httpcaddyfile.DefaultPort
64
+ }
65
+
66
+ if !strings.Contains(from, "://") {
67
+ from = "http://" + from
68
+ }
69
+
70
+ fromURL, err := url.Parse(from)
71
+ if err != nil {
72
+ fromURL.Host = from
73
+ }
74
+
75
+ toURL, err := url.Parse(to)
76
+ if err != nil {
77
+ toURL.Host = to
78
+ }
79
+
80
+ ht := HTTPTransport{}
81
+ if toURL.Scheme == "https" {
82
+ ht.TLS = new(TLSConfig)
83
+ }
84
+
85
+ handler := Handler{
86
+ TransportRaw: caddyconfig.JSONModuleObject(ht, "protocol", "http", nil),
87
+ Upstreams: UpstreamPool{{Dial: toURL.Host}},
88
+ Headers: &headers.Handler{
89
+ Request: &headers.HeaderOps{
90
+ Set: http.Header{
91
+ "Host": []string{"{http.handlers.reverse_proxy.upstream.host}"},
92
+ },
93
+ },
94
+ },
95
+ }
96
+
97
+ route := caddyhttp.Route{
98
+ HandlersRaw: []json.RawMessage{
99
+ caddyconfig.JSONModuleObject(handler, "handler", "reverse_proxy", nil),
100
+ },
101
+ }
102
+ if fromURL.Hostname() != "" {
103
+ route.MatcherSetsRaw = []map[string]json.RawMessage{
104
+ map[string]json.RawMessage{
105
+ "host": caddyconfig.JSON(caddyhttp.MatchHost{fromURL.Hostname()}, nil),
106
+ },
107
+ }
108
+ }
109
+
110
+ listen := ":" + httpcaddyfile.DefaultPort
111
+ if certmagic.HostQualifies(fromURL.Hostname()) {
112
+ listen = ":443"
113
+ }
114
+
115
+ server := &caddyhttp.Server{
116
+ Routes: caddyhttp.RouteList{route},
117
+ Listen: []string{listen},
118
+ }
119
+
120
+ httpApp := caddyhttp.App{
121
+ Servers: map[string]*caddyhttp.Server{"proxy": server},
122
+ }
123
+
124
+ cfg := &caddy.Config{
125
+ AppsRaw: map[string]json.RawMessage{
126
+ "http": caddyconfig.JSON(httpApp, nil),
127
+ },
128
+ }
129
+
130
+ err = caddy.Run(cfg)
131
+ if err != nil {
132
+ return caddy.ExitCodeFailedStartup, err
133
+ }
134
+
135
+ log.Printf("Caddy 2 proxying from %s to %s", from, to)
136
+
137
+ select {}
138
+}