@marcel91200 / caddy Mirror · read-only / commits / 80b54f3b
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 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 )