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 original URI to request context; implement into fastcgi env
Matthew Holt committed
Sep 5, 2019 at 13:36 UTC
80b54f3b9d5e207316fb9e8f83dd1e90659b25d7
2 files changed
+46
-48
modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
+29
-48
@@ -19,12 +19,14 @@ import (
19
"crypto/tls"
20
"fmt"
21
"net/http"
22
+ "net/url"
23
"path"
24
"path/filepath"
25
"strconv"
26
"strings"
27
"time"
28
29
+ "github.com/caddyserver/caddy/v2/modules/caddyhttp"
30
"github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy"
31
"github.com/caddyserver/caddy/v2/modules/caddytls"
32
@@ -37,25 +39,11 @@ func init() {
39
40
// Transport facilitates FastCGI communication.
41
type Transport struct {
40
- //////////////////////////////
41
- // TODO: taken from v1 Handler type
42
-
43
- SoftwareName string
44
- SoftwareVersion string
45
- ServerName string
46
- ServerPort string
47
-
48
- //////////////////////////
49
- // TODO: taken from v1 Rule type
50
-
51
- // The base path to match. Required.
52
- // Path string
53
-
54
- // upstream load balancer
55
- // balancer
56
-
57
- // Always process files with this extension with fastcgi.
58
- // Ext string
42
+ // TODO: Populate these
43
+ softwareName string
44
+ softwareVersion string
45
+ serverName string
46
+ serverPort string
47
48
// Use this directory as the fastcgi root directory. Defaults to the root
49
// directory of the parent virtual host.
@@ -67,16 +55,9 @@ type Transport struct {
55
// PATH_INFO for the CGI script to use.
56
SplitPath string `json:"split_path,omitempty"`
57
70
- // If the URL ends with '/' (which indicates a directory), these index
71
- // files will be tried instead.
72
- // IndexFiles []string
73
-
58
// Environment Variables
59
EnvVars [][2]string `json:"env,omitempty"`
60
77
- // Ignored paths
78
- // IgnoredSubPaths []string
79
-
61
// The duration used to set a deadline when connecting to an upstream.
62
DialTimeout caddy.Duration `json:"dial_timeout,omitempty"`
63
@@ -170,7 +151,6 @@ func (t Transport) buildEnv(r *http.Request) (map[string]string, error) {
151
ip = strings.Replace(ip, "[", "", 1)
152
ip = strings.Replace(ip, "]", "", 1)
153
173
- // TODO: respect index files? or leave that to matcher/rewrite (I prefer that)?
154
fpath := r.URL.Path
155
156
// Split path in preparation for env variables.
@@ -194,16 +174,17 @@ func (t Transport) buildEnv(r *http.Request) (map[string]string, error) {
174
pathPrefix, _ := r.Context().Value(caddy.CtxKey("path_prefix")).(string)
175
scriptName = path.Join(pathPrefix, scriptName)
176
197
- // TODO: Disabled for now
198
- // // Get the request URI from context. The context stores the original URI in case
199
- // // it was changed by a middleware such as rewrite. By default, we pass the
200
- // // original URI in as the value of REQUEST_URI (the user can overwrite this
201
- // // if desired). Most PHP apps seem to want the original URI. Besides, this is
202
- // // how nginx defaults: http://stackoverflow.com/a/12485156/1048862
203
- // reqURL, _ := r.Context().Value(httpserver.OriginalURLCtxKey).(url.URL)
204
-
205
- // // Retrieve name of remote user that was set by some downstream middleware such as basicauth.
206
- // remoteUser, _ := r.Context().Value(httpserver.RemoteUserCtxKey).(string)
177
+ // Get the request URL from context. The context stores the original URL in case
178
+ // it was changed by a middleware such as rewrite. By default, we pass the
179
+ // original URI in as the value of REQUEST_URI (the user can overwrite this
180
+ // if desired). Most PHP apps seem to want the original URI. Besides, this is
181
+ // how nginx defaults: http://stackoverflow.com/a/12485156/1048862
182
+ reqURL, ok := r.Context().Value(caddyhttp.OriginalURLCtxKey).(url.URL)
183
+ if !ok {
184
+ // some requests, like active health checks, don't add this to
185
+ // the request context, so we can just use the current URL
186
+ reqURL = *r.URL
187
+ }
188
189
requestScheme := "http"
190
if r.TLS != nil {
@@ -224,19 +205,19 @@ func (t Transport) buildEnv(r *http.Request) (map[string]string, error) {
205
"REMOTE_HOST": ip, // For speed, remote host lookups disabled
206
"REMOTE_PORT": port,
207
"REMOTE_IDENT": "", // Not used
227
- // "REMOTE_USER": remoteUser, // TODO:
228
- "REQUEST_METHOD": r.Method,
229
- "REQUEST_SCHEME": requestScheme,
230
- "SERVER_NAME": t.ServerName,
231
- "SERVER_PORT": t.ServerPort,
232
- "SERVER_PROTOCOL": r.Proto,
233
- "SERVER_SOFTWARE": t.SoftwareName + "/" + t.SoftwareVersion,
208
+ "REMOTE_USER": "", // TODO: once there are authentication handlers, populate this
209
+ "REQUEST_METHOD": r.Method,
210
+ "REQUEST_SCHEME": requestScheme,
211
+ "SERVER_NAME": t.ServerName,
212
+ "SERVER_PORT": t.ServerPort,
213
+ "SERVER_PROTOCOL": r.Proto,
214
+ "SERVER_SOFTWARE": t.SoftwareName + "/" + t.SoftwareVersion,
215
216
// Other variables
236
- // "DOCUMENT_ROOT": rule.Root,
237
- "DOCUMENT_URI": docURI,
238
- "HTTP_HOST": r.Host, // added here, since not always part of headers
239
- // "REQUEST_URI": reqURL.RequestURI(), // TODO:
217
+ "DOCUMENT_ROOT": t.Root,
218
+ "DOCUMENT_URI": docURI,
219
+ "HTTP_HOST": r.Host, // added here, since not always part of headers
220
+ "REQUEST_URI": reqURL.RequestURI(),
221
"SCRIPT_FILENAME": scriptFilename,
222
"SCRIPT_NAME": scriptName,
223
}
modules/caddyhttp/server.go
+17
@@ -20,6 +20,7 @@ import (
20
"log"
21
"net"
22
"net/http"
23
+ "net/url"
24
"strconv"
25
"strings"
26
@@ -58,6 +59,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
59
ctx := context.WithValue(r.Context(), caddy.ReplacerCtxKey, repl)
60
ctx = context.WithValue(ctx, ServerCtxKey, s)
61
ctx = context.WithValue(ctx, VarCtxKey, make(map[string]interface{}))
62
+ ctx = context.WithValue(ctx, OriginalURLCtxKey, cloneURL(r.URL))
63
r = r.WithContext(ctx)
64
65
// once the pointer to the request won't change
@@ -228,6 +230,18 @@ type HTTPErrorConfig struct {
230
Routes RouteList `json:"routes,omitempty"`
231
}
232
233
+// cloneURL makes a copy of r.URL and returns a
234
+// new value that doesn't reference the original.
235
+func cloneURL(u *url.URL) url.URL {
236
+ urlCopy := *u
237
+ if u.User != nil {
238
+ userInfo := new(url.Userinfo)
239
+ *userInfo = *u.User
240
+ urlCopy.User = userInfo
241
+ }
242
+ return urlCopy
243
+}
244
+
245
// Context keys for HTTP request context values.
246
const (
247
// For referencing the server instance
@@ -235,4 +249,7 @@ const (
249
250
// For the request's variable table
251
VarCtxKey caddy.CtxKey = "vars"
252
+
253
+ // For the unmodified URL that originally came in with a request
254
+ OriginalURLCtxKey caddy.CtxKey = "original_url"
255
)