mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
net: Move listing of directories to async code (#42108)
Listing directory and constructing the list is another prime candidate to switch from blocking code to async code. This PR does this. Of note is the change in type for ProtocolHandler::load which now has a lifetime bounded by Request and self and the Response has a similar lifetime bound. Signed-off-by: Narfinger <Narfinger@users.noreply.github.com> Testing: Looking at directories still works. --------- Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::fs::{DirEntry, Metadata, ReadDir};
|
||||
use std::fs::Metadata;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use chrono::{DateTime, Local};
|
||||
@@ -15,7 +15,7 @@ use servo_config::pref;
|
||||
use servo_url::ServoUrl;
|
||||
use url::Url;
|
||||
|
||||
pub fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Response {
|
||||
pub(crate) async fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Response {
|
||||
if !pref!(network_local_directory_listing_enabled) {
|
||||
// If you want to be able to browse local directories, configure Servo prefs so that
|
||||
// "network.local_directory_listing.enabled" is set to true.
|
||||
@@ -29,7 +29,7 @@ pub fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Respons
|
||||
return Response::network_error(NetworkError::LocalDirectoryError);
|
||||
}
|
||||
|
||||
let directory_contents = match std::fs::read_dir(path_buf.clone()) {
|
||||
let directory_contents = match tokio::fs::read_dir(path_buf.clone()).await {
|
||||
Ok(directory_contents) => directory_contents,
|
||||
Err(error) => {
|
||||
return Response::network_error(NetworkError::ResourceLoadError(format!(
|
||||
@@ -38,7 +38,7 @@ pub fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Respons
|
||||
},
|
||||
};
|
||||
|
||||
let output = build_html_directory_listing(url.as_url(), path_buf, directory_contents);
|
||||
let output = build_html_directory_listing(url.as_url(), path_buf, directory_contents).await;
|
||||
|
||||
let mut response = Response::new(url, ResourceFetchTiming::new(request.timing_type()));
|
||||
response.headers.typed_insert(ContentType::html());
|
||||
@@ -55,10 +55,10 @@ pub fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Respons
|
||||
/// * `url` - the original URL of the request that triggered this directory listing.
|
||||
/// * `path` - the full path to the local directory.
|
||||
/// * `directory_contents` - a [`ReadDir`] with the contents of the directory.
|
||||
pub fn build_html_directory_listing(
|
||||
pub(crate) async fn build_html_directory_listing(
|
||||
url: &Url,
|
||||
path: PathBuf,
|
||||
directory_contents: ReadDir,
|
||||
mut directory_contents: tokio::fs::ReadDir,
|
||||
) -> String {
|
||||
let mut page_html = String::with_capacity(1024);
|
||||
page_html.push_str("<!DOCTYPE html>");
|
||||
@@ -81,11 +81,8 @@ pub fn build_html_directory_listing(
|
||||
parent_url_string
|
||||
));
|
||||
|
||||
for directory_entry in directory_contents {
|
||||
let Ok(directory_entry) = directory_entry else {
|
||||
continue;
|
||||
};
|
||||
let Ok(metadata) = directory_entry.metadata() else {
|
||||
while let Ok(Some(directory_entry)) = directory_contents.next_entry().await {
|
||||
let Ok(metadata) = directory_entry.metadata().await else {
|
||||
continue;
|
||||
};
|
||||
write_directory_entry(directory_entry, metadata, url, &mut page_html);
|
||||
@@ -97,7 +94,12 @@ pub fn build_html_directory_listing(
|
||||
page_html
|
||||
}
|
||||
|
||||
fn write_directory_entry(entry: DirEntry, metadata: Metadata, url: &Url, output: &mut String) {
|
||||
fn write_directory_entry(
|
||||
entry: tokio::fs::DirEntry,
|
||||
metadata: Metadata,
|
||||
url: &Url,
|
||||
output: &mut String,
|
||||
) {
|
||||
let Ok(name) = entry.file_name().into_string() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -25,12 +25,12 @@ use crate::protocols::{
|
||||
pub struct FileProtocolHander {}
|
||||
|
||||
impl ProtocolHandler for FileProtocolHander {
|
||||
fn load(
|
||||
&self,
|
||||
request: &mut Request,
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
request: &'a mut Request,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext,
|
||||
) -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
) -> Pin<Box<dyn Future<Output = Response> + Send + 'a>> {
|
||||
let url = request.current_url();
|
||||
|
||||
if request.method != Method::GET {
|
||||
@@ -38,9 +38,9 @@ impl ProtocolHandler for FileProtocolHander {
|
||||
}
|
||||
let response = if let Ok(file_path) = url.to_file_path() {
|
||||
if file_path.is_dir() {
|
||||
return Box::pin(ready(local_directory_listing::fetch(
|
||||
request, url, file_path,
|
||||
)));
|
||||
return Box::pin(async move {
|
||||
local_directory_listing::fetch(request, url, file_path).await
|
||||
});
|
||||
}
|
||||
|
||||
if let Ok(file) = File::open(file_path.clone()) {
|
||||
|
||||
@@ -29,7 +29,7 @@ use blob::BlobProtocolHander;
|
||||
use data::DataProtocolHander;
|
||||
use file::FileProtocolHander;
|
||||
|
||||
type FutureResponse = Pin<Box<dyn Future<Output = Response> + Send>>;
|
||||
type FutureResponse<'a> = Pin<Box<dyn Future<Output = Response> + Send + 'a>>;
|
||||
|
||||
// The set of schemes that can't be registered.
|
||||
static FORBIDDEN_SCHEMES: [&str; 4] = ["http", "https", "chrome", "about"];
|
||||
@@ -47,12 +47,12 @@ pub trait ProtocolHandler: Send + Sync {
|
||||
/// http endpoint, it is recommended to a least provide:
|
||||
/// - A relevant status code.
|
||||
/// - A Content Type.
|
||||
fn load(
|
||||
&self,
|
||||
request: &mut Request,
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
request: &'a mut Request,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext,
|
||||
) -> FutureResponse;
|
||||
) -> FutureResponse<'a>;
|
||||
|
||||
/// Specify if resources served by that protocol can be retrieved
|
||||
/// with `fetch()` without no-cors mode to allow the caller direct
|
||||
@@ -177,12 +177,12 @@ struct WebPageContentProtocolHandler {
|
||||
|
||||
impl ProtocolHandler for WebPageContentProtocolHandler {
|
||||
/// <https://html.spec.whatwg.org/multipage/#protocol-handler-invocation>
|
||||
fn load(
|
||||
&self,
|
||||
request: &mut Request,
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
request: &'a mut Request,
|
||||
_done_chan: &mut DoneChannel,
|
||||
context: &FetchContext,
|
||||
) -> FutureResponse {
|
||||
) -> FutureResponse<'a> {
|
||||
let mut url = request.current_url();
|
||||
// Step 1. Assert: inputURL's scheme is normalizedScheme.
|
||||
assert!(url.scheme() == self.scheme);
|
||||
|
||||
Reference in New Issue
Block a user