Skip to content

Commit

Permalink
Fixe PATH_TRANSLATED and PATH_INFO
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Butcher <matt.butcher@microsoft.com>
  • Loading branch information
technosophos committed Aug 23, 2021
1 parent 88e8053 commit 47b368d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
9 changes: 6 additions & 3 deletions docs/environment_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@ REMOTE_ADDR="127.0.0.1"
# The server's IP address
REMOTE_HOST="127.0.0.1"
# The path info after the SCRIPT_NAME. If the route is /envwasm/... and the
# request is /envwasm/foo, the PathInfo is /foo
# request is /envwasm/foo, the PathInfo is /foo. This value is run through a URL decoder
PATH_INFO="/foo"
# Wagi-specific: Same as PATH_INFO, but without being url-decoded. This can disambiguate
# cases where things like '.', '+', and '/' appear in the path segment.
X_RAW_PATH_INFO="/foo"
# In Wagi, this is always the same as PATH_INFO.
PATH_TRANSLATED="/foo"
# The client-supplied query string, E.g. http://example.com?foo=bar becomes foo=bar
QUERY_STRING=""
# This is PATH_INFO after it has been run through a url-decode
PATH_TRANSLATED="/foo"
# The length of the body sent by the client. This is >0 only if the client sends a
# non-empty body.
CONTENT_LENGTH="0"
Expand Down
27 changes: 20 additions & 7 deletions src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ impl Module {
headers.insert("GATEWAY_INTERFACE".to_owned(), WAGI_VERSION.to_owned());

// This is the Wagi route. This is different from PATH_INFO in that it may
// have a trailing '/..'
// have a trailing '/...'
headers.insert("X_MATCHED_ROUTE".to_owned(), self.route.to_owned());

headers.insert(
Expand All @@ -395,17 +395,30 @@ impl Module {
let script_name = self
.route
.strip_suffix("/...")
.map(|i| format!("/{}", i)) // At the bare minimum, SCRIPT_NAME must be '/'
.map(|i| {
if i.starts_with('/') {
i.to_owned()
} else {
format!("/{}", i)
}
}) // At the bare minimum, SCRIPT_NAME must be '/'
.unwrap_or_else(|| self.route.clone());
headers.insert("SCRIPT_NAME".to_owned(), script_name);
// PATH_INFO is any path information after SCRIPT_NAME
//
// I am intentionally ignoring the PATH_INFO rule that says that a PATH_INFO
// cannot have a path seperator in it. If it becomes important to distinguish
// between what was decoded out of the path and what is encoded in the path,
// the X_RAW_PATH_INFO can be used.
//
// https://datatracker.ietf.org/doc/html/rfc3875#section-4.1.5
let pathinfo = self.path_info(req.uri.path());
let path_translated = url_escape::decode(&pathinfo);
headers.insert("PATH_INFO".to_owned(), pathinfo.clone());
let pathsegment = self.path_info(req.uri.path());
let pathinfo = url_escape::decode(&pathsegment);
headers.insert("X_RAW_PATH_INFO".to_owned(), pathsegment.clone());
headers.insert("PATH_INFO".to_owned(), pathinfo.to_string());
// PATH_TRANSLATED is the url-decoded version of PATH_INFO
// https://datatracker.ietf.org/doc/html/rfc3875#section-4.1.6
headers.insert("PATH_TRANSLATED".to_owned(), path_translated.to_string());
headers.insert("PATH_TRANSLATED".to_owned(), pathinfo.to_string());

// From the spec: "the server would use the contents of the request's Host header
// field to select the correct virtual host."
Expand Down Expand Up @@ -1308,7 +1321,7 @@ mod test {
want("AUTH_TYPE", "");
want("REMOTE_ADDR", "192.168.0.1");
want("REMOTE_ADDR", "192.168.0.1");
want("PATH_INFO", "/test%3brun");
want("PATH_INFO", "/test;run");
want("PATH_TRANSLATED", "/test;run");
want("QUERY_STRING", "foo=bar");
want("CONTENT_LENGTH", "1234");
Expand Down

0 comments on commit 47b368d

Please sign in to comment.