Merge branch 'master' into pr/atty303/1948
This commit is contained in:
commit
c4a4a31eec
78 files changed
+1277
-4465
No files matched your search
@@ -1,6 +1,4 @@
|
||||
use crate::assets::AssetConfigDropGuard;
|
||||
#[cfg(feature = "plugin")]
|
||||
use crate::plugin::PluginManager;
|
||||
use crate::server::fullstack;
|
||||
use dioxus_cli_config::Platform;
|
||||
|
||||
@@ -55,7 +53,7 @@ impl Build {
|
||||
crate_config.set_cargo_args(self.build.cargo_args.clone());
|
||||
|
||||
// #[cfg(feature = "plugin")]
|
||||
// let _ = PluginManager::on_build_start(&crate_config, &platform);
|
||||
// let _ = crate::plugin::PluginManager::on_build_start(&crate_config, &platform);
|
||||
|
||||
let build_result = match platform {
|
||||
Platform::Web => {
|
||||
@@ -116,7 +114,7 @@ impl Build {
|
||||
file.write_all(temp.as_bytes())?;
|
||||
|
||||
// #[cfg(feature = "plugin")]
|
||||
// let _ = PluginManager::on_build_finish(&crate_config, &platform);
|
||||
// let _ = crate::plugin::PluginManager::on_build_finish(&crate_config, &platform);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use dioxus_cli::*;
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
use dioxus_cli::plugin::PluginManager;
|
||||
|
||||
use Commands::*;
|
||||
|
||||
fn get_bin(bin: Option<String>) -> Result<PathBuf> {
|
||||
@@ -92,6 +89,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
DioxusConfig::default()
|
||||
});
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
use dioxus_cli::plugin::PluginManager;
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
PluginManager::init(_dioxus_config.plugin)
|
||||
.context(error_wrapper("Plugin system initialization failed"))?;
|
||||
|
||||
@@ -45,7 +45,7 @@ impl UserData for PluginCommander {
|
||||
if cmd.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let cmd_name = cmd.get(0).unwrap();
|
||||
let cmd_name = cmd.first().unwrap();
|
||||
let mut command = Command::new(cmd_name);
|
||||
let t = cmd
|
||||
.iter()
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use crate::server::HotReloadState;
|
||||
use axum::{
|
||||
extract::{ws::Message, WebSocketUpgrade},
|
||||
response::IntoResponse,
|
||||
Extension, TypedHeader,
|
||||
Extension,
|
||||
};
|
||||
|
||||
use crate::server::HotReloadState;
|
||||
|
||||
pub async fn hot_reload_handler(
|
||||
ws: WebSocketUpgrade,
|
||||
_: Option<TypedHeader<headers::UserAgent>>,
|
||||
Extension(state): Extension<HotReloadState>,
|
||||
) -> impl IntoResponse {
|
||||
ws.on_upgrade(|mut socket| async move {
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::{
|
||||
BuildResult, Result,
|
||||
};
|
||||
use axum::{
|
||||
body::{Full, HttpBody},
|
||||
extract::{ws::Message, Extension, TypedHeader, WebSocketUpgrade},
|
||||
body::Body,
|
||||
extract::{ws::Message, Extension, WebSocketUpgrade},
|
||||
http::{
|
||||
self,
|
||||
header::{HeaderName, HeaderValue},
|
||||
@@ -287,20 +287,18 @@ async fn setup_router(
|
||||
let mut response = if file_service_config.dioxus_config.web.watcher.index_on_404
|
||||
&& response.status() == StatusCode::NOT_FOUND
|
||||
{
|
||||
let body = Full::from(
|
||||
let body = Body::from(
|
||||
// TODO: Cache/memoize this.
|
||||
std::fs::read_to_string(file_service_config.out_dir().join("index.html"))
|
||||
.ok()
|
||||
.unwrap(),
|
||||
)
|
||||
.map_err(|err| match err {})
|
||||
.boxed();
|
||||
);
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body(body)
|
||||
.unwrap()
|
||||
} else {
|
||||
response.map(|body| body.boxed())
|
||||
response.into_response()
|
||||
};
|
||||
let headers = response.headers_mut();
|
||||
headers.insert(
|
||||
@@ -324,7 +322,7 @@ async fn setup_router(
|
||||
|
||||
// Route file service
|
||||
router = router.fallback(get_service(file_service).handle_error(
|
||||
|error: std::io::Error| async move {
|
||||
|error: std::convert::Infallible| async move {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Unhandled internal error: {}", error),
|
||||
@@ -335,7 +333,7 @@ async fn setup_router(
|
||||
router = if let Some(base_path) = config.dioxus_config.web.app.base_path.clone() {
|
||||
let base_path = format!("/{}", base_path.trim_matches('/'));
|
||||
Router::new()
|
||||
.nest(&base_path, axum::routing::any_service(router))
|
||||
.route(&base_path, axum::routing::any_service(router))
|
||||
.fallback(get(move || {
|
||||
let base_path = base_path.clone();
|
||||
async move { format!("Outside of the base path: {}", base_path) }
|
||||
@@ -388,9 +386,8 @@ async fn start_server(
|
||||
.await?
|
||||
}
|
||||
None => {
|
||||
axum::Server::bind(&addr)
|
||||
.serve(router.into_make_service())
|
||||
.await?
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
axum::serve(listener, router.into_make_service()).await?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +415,6 @@ fn get_ip() -> Option<String> {
|
||||
/// Handle websockets
|
||||
async fn ws_handler(
|
||||
ws: WebSocketUpgrade,
|
||||
_: Option<TypedHeader<headers::UserAgent>>,
|
||||
Extension(state): Extension<Arc<WsReloadState>>,
|
||||
) -> impl IntoResponse {
|
||||
ws.on_upgrade(|mut socket| async move {
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
use crate::Result;
|
||||
use dioxus_cli_config::WebProxyConfig;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{anyhow, Context};
|
||||
use axum::{http::StatusCode, routing::any, Router};
|
||||
use hyper::{Request, Response, Uri};
|
||||
use hyper_util::{
|
||||
client::legacy::{self, connect::HttpConnector},
|
||||
rt::TokioExecutor,
|
||||
};
|
||||
|
||||
use axum::body::Body as MyBody;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ProxyClient {
|
||||
inner: hyper::Client<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>,
|
||||
inner: legacy::Client<hyper_rustls::HttpsConnector<HttpConnector>, MyBody>,
|
||||
url: Uri,
|
||||
}
|
||||
|
||||
@@ -15,19 +21,17 @@ impl ProxyClient {
|
||||
fn new(url: Uri) -> Self {
|
||||
let https = hyper_rustls::HttpsConnectorBuilder::new()
|
||||
.with_native_roots()
|
||||
.unwrap()
|
||||
.https_or_http()
|
||||
.enable_http1()
|
||||
.build();
|
||||
Self {
|
||||
inner: hyper::Client::builder().build(https),
|
||||
inner: legacy::Client::builder(TokioExecutor::new()).build(https),
|
||||
url,
|
||||
}
|
||||
}
|
||||
|
||||
async fn send(
|
||||
&self,
|
||||
mut req: Request<hyper::body::Body>,
|
||||
) -> Result<Response<hyper::body::Body>> {
|
||||
async fn send(&self, mut req: Request<MyBody>) -> Result<Response<hyper::body::Incoming>> {
|
||||
let mut uri_parts = req.uri().clone().into_parts();
|
||||
uri_parts.authority = self.url.authority().cloned();
|
||||
uri_parts.scheme = self.url.scheme().cloned();
|
||||
@@ -35,7 +39,7 @@ impl ProxyClient {
|
||||
self.inner
|
||||
.request(req)
|
||||
.await
|
||||
.map_err(crate::error::Error::ProxyRequestError)
|
||||
.map_err(|err| crate::error::Error::Other(anyhow!(err)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +53,7 @@ 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('/');
|
||||
let trimmed_path = path.trim_start_matches('/');
|
||||
|
||||
if trimmed_path.is_empty() {
|
||||
return Err(crate::Error::ProxySetupError(format!(
|
||||
@@ -61,14 +65,11 @@ pub fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Router> {
|
||||
|
||||
let client = ProxyClient::new(url);
|
||||
|
||||
// We also match everything after the path using a wildcard matcher.
|
||||
let wildcard_client = client.clone();
|
||||
|
||||
router = router.route(
|
||||
// Always remove trailing /'s so that the exact route
|
||||
// matches.
|
||||
trimmed_path,
|
||||
any(move |req| async move {
|
||||
&format!("/*{}", trimmed_path.trim_end_matches('/')),
|
||||
any(move |req: Request<MyBody>| async move {
|
||||
client
|
||||
.send(req)
|
||||
.await
|
||||
@@ -76,19 +77,6 @@ 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", trimmed_path);
|
||||
router = router.route(
|
||||
&wildcard,
|
||||
any(move |req| async move {
|
||||
wildcard_client
|
||||
.send(req)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))
|
||||
}),
|
||||
);
|
||||
Ok(router)
|
||||
}
|
||||
|
||||
@@ -97,30 +85,47 @@ mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
use axum::{extract::Path, Router};
|
||||
use axum::Router;
|
||||
use axum_server::{Handle, Server};
|
||||
|
||||
fn setup_servers(
|
||||
mut config: WebProxyConfig,
|
||||
) -> (
|
||||
tokio::task::JoinHandle<()>,
|
||||
tokio::task::JoinHandle<()>,
|
||||
String,
|
||||
) {
|
||||
let backend_router = Router::new().route(
|
||||
"/*path",
|
||||
any(|path: Path<String>| async move { format!("backend: {}", path.0) }),
|
||||
);
|
||||
let backend_server = axum::Server::bind(&"127.0.0.1:0".parse().unwrap())
|
||||
.serve(backend_router.into_make_service());
|
||||
let backend_addr = backend_server.local_addr();
|
||||
let backend_handle = tokio::spawn(async move { backend_server.await.unwrap() });
|
||||
async fn setup_servers(mut config: WebProxyConfig) -> String {
|
||||
let backend_router =
|
||||
Router::new().route(
|
||||
"/*path",
|
||||
any(|request: axum::extract::Request| async move {
|
||||
format!("backend: {}", request.uri())
|
||||
}),
|
||||
);
|
||||
|
||||
// The API backend server
|
||||
let backend_handle_handle = Handle::new();
|
||||
let backend_handle_handle_ = backend_handle_handle.clone();
|
||||
tokio::spawn(async move {
|
||||
Server::bind("127.0.0.1:0".parse().unwrap())
|
||||
.handle(backend_handle_handle_)
|
||||
.serve(backend_router.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// Set the user's config to this dummy API we just built so we can test it
|
||||
let backend_addr = backend_handle_handle.listening().await.unwrap();
|
||||
config.backend = format!("http://{}{}", backend_addr, config.backend);
|
||||
|
||||
// Now set up our actual filesystem server
|
||||
let router = super::add_proxy(Router::new(), &config);
|
||||
let server = axum::Server::bind(&"127.0.0.1:0".parse().unwrap())
|
||||
.serve(router.unwrap().into_make_service());
|
||||
let server_addr = server.local_addr();
|
||||
let server_handle = tokio::spawn(async move { server.await.unwrap() });
|
||||
(backend_handle, server_handle, server_addr.to_string())
|
||||
let server_handle_handle = Handle::new();
|
||||
let server_handle_handle_ = server_handle_handle.clone();
|
||||
tokio::spawn(async move {
|
||||
Server::bind("127.0.0.1:0".parse().unwrap())
|
||||
.handle(server_handle_handle_)
|
||||
.serve(router.unwrap().into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// Expose *just* the fileystem web server's address
|
||||
server_handle_handle.listening().await.unwrap().to_string()
|
||||
}
|
||||
|
||||
async fn test_proxy_requests(path: String) {
|
||||
@@ -132,42 +137,38 @@ mod test {
|
||||
// So in day to day usage, use `http://localhost:8000/api` instead!
|
||||
backend: path,
|
||||
};
|
||||
let (backend_handle, server_handle, server_addr) = setup_servers(config);
|
||||
let resp = hyper::Client::new()
|
||||
.get(format!("http://{}/api", server_addr).parse().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
let server_addr = setup_servers(config).await;
|
||||
|
||||
assert_eq!(
|
||||
hyper::body::to_bytes(resp.into_body()).await.unwrap(),
|
||||
reqwest::get(format!("http://{}/api", server_addr))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap(),
|
||||
"backend: /api"
|
||||
);
|
||||
|
||||
let resp = hyper::Client::new()
|
||||
.get(format!("http://{}/api/", server_addr).parse().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
hyper::body::to_bytes(resp.into_body()).await.unwrap(),
|
||||
reqwest::get(format!("http://{}/api/", server_addr))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap(),
|
||||
"backend: /api/"
|
||||
);
|
||||
|
||||
let resp = hyper::Client::new()
|
||||
.get(
|
||||
format!("http://{}/api/subpath", server_addr)
|
||||
.parse()
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
hyper::body::to_bytes(resp.into_body()).await.unwrap(),
|
||||
reqwest::get(format!("http://{server_addr}/api/subpath"))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap(),
|
||||
"backend: /api/subpath"
|
||||
);
|
||||
backend_handle.abort();
|
||||
server_handle.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in new issue
Block a user