Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor Proxy Improvements #1289

Merged
merged 2 commits into from Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/docs/src/configure.md
Expand Up @@ -144,7 +144,7 @@ Configeration related to static resources your application uses in development:
Configeration related to any proxies your application requires durring development. Proxies will forward requests to a new service

```
[web.proxy]
[[web.proxy]]
# configuration
```

Expand Down
3 changes: 3 additions & 0 deletions packages/cli/src/error.rs
Expand Up @@ -35,6 +35,9 @@ pub enum Error {
#[error("Invalid proxy URL: {0}")]
InvalidProxy(#[from] hyper::http::uri::InvalidUri),

#[error("Failed to establish proxy: {0}")]
ProxySetupError(String),

#[error("Error proxying request: {0}")]
ProxyRequestError(hyper::Error),

Expand Down
31 changes: 29 additions & 2 deletions packages/cli/src/server/web/proxy.rs
Expand Up @@ -48,6 +48,16 @@ impl ProxyClient {
pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Router> {
let url: Uri = proxy.backend.parse()?;
let path = url.path().to_string();
let trimmed_path = path.trim_end_matches('/');

if trimmed_path.is_empty() {
return Err(crate::Error::ProxySetupError(format!(
"Proxy backend URL must have a non-empty path, e.g. {}/api instead of {}",
proxy.backend.trim_end_matches('/'),
proxy.backend
)));
}

let client = ProxyClient::new(url);

// We also match everything after the path using a wildcard matcher.
Expand All @@ -56,7 +66,7 @@ pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Router> {
router = router.route(
// Always remove trailing /'s so that the exact route
// matches.
path.trim_end_matches('/'),
trimmed_path,
any(move |req| async move {
client
.send(req)
Expand All @@ -68,7 +78,7 @@ pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Router> {
// Wildcard match anything else _after_ the backend URL's path.
// Note that we know `path` ends with a trailing `/` in this branch,
// so `wildcard` will look like `http://localhost/api/*proxywildcard`.
let wildcard = format!("{}/*proxywildcard", path.trim_end_matches('/'));
let wildcard = format!("{}/*proxywildcard", trimmed_path);
router = router.route(
&wildcard,
any(move |req| async move {
Expand Down Expand Up @@ -168,4 +178,21 @@ mod test {
async fn add_proxy_trailing_slash() {
test_proxy_requests("/api/".to_string()).await;
}

#[test]
fn add_proxy_empty_path() {
let config = WebProxyConfig {
backend: "http://localhost:8000".to_string(),
};
let router = super::add_proxy(Router::new(), &config);
match router.unwrap_err() {
crate::Error::ProxySetupError(e) => {
assert_eq!(
e,
"Proxy backend URL must have a non-empty path, e.g. http://localhost:8000/api instead of http://localhost:8000"
);
}
e => panic!("Unexpected error type: {}", e),
}
}
}