mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 09:40:32 +00:00
Compare commits
6 Commits
1.0.0-alph
...
1.0.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63d846ed14 | ||
|
|
3a79fcfe73 | ||
|
|
b3c80ae362 | ||
|
|
3fd003b21d | ||
|
|
1d3f622922 | ||
|
|
e31b4303ed |
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -691,9 +691,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-s3"
|
||||
version = "1.115.0"
|
||||
version = "1.116.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdaa0053cbcbc384443dd24569bd5d1664f86427b9dc04677bd0ab853954baec"
|
||||
checksum = "cd4c10050aa905b50dc2a1165a9848d598a80c3a724d6f93b5881aa62235e4a5"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -4266,9 +4266,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.18"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56"
|
||||
checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -4816,9 +4816,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd"
|
||||
checksum = "8b484ba8d4f775eeca644c452a56650e544bf7e617f1d170fe7298122ead5222"
|
||||
dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
@@ -4875,11 +4875,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
@@ -10394,9 +10394,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2"
|
||||
checksum = "36134c44663532e6519d7a6dfdbbe06f6f8192bde8ae9ed076e9b213f0e31df7"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
|
||||
@@ -105,7 +105,7 @@ futures-core = "0.3.31"
|
||||
futures-util = "0.3.31"
|
||||
hyper = { version = "1.8.1", features = ["http2", "http1", "server"] }
|
||||
hyper-rustls = { version = "0.27.7", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "ring", "webpki-roots"] }
|
||||
hyper-util = { version = "0.1.18", features = ["tokio", "server-auto", "server-graceful"] }
|
||||
hyper-util = { version = "0.1.19", features = ["tokio", "server-auto", "server-graceful"] }
|
||||
http = "1.4.0"
|
||||
http-body = "1.0.1"
|
||||
reqwest = { version = "0.12.24", default-features = false, features = ["rustls-tls-webpki-roots", "charset", "http2", "system-proxy", "stream", "json", "blocking"] }
|
||||
@@ -167,7 +167,7 @@ atoi = "2.0.0"
|
||||
atomic_enum = "0.3.0"
|
||||
aws-config = { version = "1.8.11" }
|
||||
aws-credential-types = { version = "1.2.10" }
|
||||
aws-sdk-s3 = { version = "1.115.0", default-features = false, features = ["sigv4a", "rustls", "rt-tokio"] }
|
||||
aws-sdk-s3 = { version = "1.116.0", default-features = false, features = ["sigv4a", "rustls", "rt-tokio"] }
|
||||
aws-smithy-types = { version = "1.3.4" }
|
||||
base64 = "0.22.1"
|
||||
base64-simd = "0.8.0"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.rustfs.com/introduction.html">Getting Started</a>
|
||||
<a href="https://docs.rustfs.com/installation/">Getting Started</a>
|
||||
· <a href="https://docs.rustfs.com/">Docs</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/issues">Bug reports</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/discussions">Discussions</a>
|
||||
@@ -151,7 +151,7 @@ make help-docker # Show all Docker-related commands
|
||||
|
||||
### 4\. Build with Helm Chart (Option 4) - Cloud Native
|
||||
|
||||
Follow the instructions in the [Helm Chart README](https://www.google.com/search?q=./helm/README.md) to install RustFS on a Kubernetes cluster.
|
||||
Follow the instructions in the [Helm Chart README](https://charts.rustfs.com/) to install RustFS on a Kubernetes cluster.
|
||||
|
||||
-----
|
||||
|
||||
@@ -188,7 +188,7 @@ If you have any questions or need assistance:
|
||||
- **Business**: [hello@rustfs.com](mailto:hello@rustfs.com)
|
||||
- **Jobs**: [jobs@rustfs.com](mailto:jobs@rustfs.com)
|
||||
- **General Discussion**: [GitHub Discussions](https://github.com/rustfs/rustfs/discussions)
|
||||
- **Contributing**: [CONTRIBUTING.md](https://www.google.com/search?q=CONTRIBUTING.md)
|
||||
- **Contributing**: [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
## Contributors
|
||||
|
||||
@@ -206,8 +206,6 @@ RustFS is a community-driven project, and we appreciate all contributions. Check
|
||||
|
||||
## Star History
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://www.star-history.com/#rustfs/rustfs&type=date&legend=top-left)
|
||||
|
||||
## License
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.rustfs.com/introduction.html">快速开始</a>
|
||||
<a href="https://docs.rustfs.com/installation/">快速开始</a>
|
||||
· <a href="https://docs.rustfs.com/">文档</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/issues">报告 Bug</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/discussions">社区讨论</a>
|
||||
@@ -153,7 +153,7 @@ make help-docker # 显示所有 Docker 相关命令
|
||||
|
||||
### 4\. 使用 Helm Chart 安装 (选项 4) - 云原生环境
|
||||
|
||||
请按照 [Helm Chart README](https://www.google.com/search?q=./helm/README.md) 上的说明在 Kubernetes 集群上安装 RustFS。
|
||||
请按照 [Helm Chart README](https://charts.rustfs.com) 上的说明在 Kubernetes 集群上安装 RustFS。
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -271,10 +271,10 @@ impl DiskAPI for Disk {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
async fn list_dir(&self, _origvolume: &str, volume: &str, _dir_path: &str, _count: i32) -> Result<Vec<String>> {
|
||||
async fn list_dir(&self, _origvolume: &str, volume: &str, dir_path: &str, count: i32) -> Result<Vec<String>> {
|
||||
match self {
|
||||
Disk::Local(local_disk) => local_disk.list_dir(_origvolume, volume, _dir_path, _count).await,
|
||||
Disk::Remote(remote_disk) => remote_disk.list_dir(_origvolume, volume, _dir_path, _count).await,
|
||||
Disk::Local(local_disk) => local_disk.list_dir(_origvolume, volume, dir_path, count).await,
|
||||
Disk::Remote(remote_disk) => remote_disk.list_dir(_origvolume, volume, dir_path, count).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ use rustfs_protos::proto_gen::node_service::RenamePartRequest;
|
||||
use rustfs_rio::{HttpReader, HttpWriter};
|
||||
use tokio::{io::AsyncWrite, net::TcpStream, time::timeout};
|
||||
use tonic::Request;
|
||||
use tracing::info;
|
||||
use tracing::{debug, info};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -596,14 +596,16 @@ impl DiskAPI for RemoteDisk {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
async fn list_dir(&self, _origvolume: &str, volume: &str, _dir_path: &str, _count: i32) -> Result<Vec<String>> {
|
||||
info!("list_dir {}/{}", volume, _dir_path);
|
||||
async fn list_dir(&self, _origvolume: &str, volume: &str, dir_path: &str, count: i32) -> Result<Vec<String>> {
|
||||
debug!("list_dir {}/{}", volume, dir_path);
|
||||
let mut client = node_service_time_out_client(&self.addr)
|
||||
.await
|
||||
.map_err(|err| Error::other(format!("can not get client, err: {err}")))?;
|
||||
let request = Request::new(ListDirRequest {
|
||||
disk: self.endpoint.to_string(),
|
||||
volume: volume.to_string(),
|
||||
dir_path: dir_path.to_string(),
|
||||
count,
|
||||
});
|
||||
|
||||
let response = client.list_dir(request).await?.into_inner();
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod models;
|
||||
|
||||
@@ -303,6 +303,10 @@ pub struct ListDirRequest {
|
||||
pub disk: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "2")]
|
||||
pub volume: ::prost::alloc::string::String,
|
||||
#[prost(string, tag = "3")]
|
||||
pub dir_path: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag = "4")]
|
||||
pub count: i32,
|
||||
}
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ListDirResponse {
|
||||
|
||||
@@ -16,7 +16,9 @@ use std::{cmp, env, fs, io::Write, path::Path, process::Command};
|
||||
|
||||
type AnyError = Box<dyn std::error::Error>;
|
||||
|
||||
/// Expected version of `protoc` compiler.
|
||||
const VERSION_PROTOBUF: Version = Version(33, 1, 0); // 31.1.0
|
||||
/// Expected version of `flatc` compiler.
|
||||
const VERSION_FLATBUFFERS: Version = Version(25, 9, 23); // 25.9.23
|
||||
/// Build protos if the major version of `flatc` or `protoc` is greater
|
||||
/// or lesser than the expected version.
|
||||
@@ -26,8 +28,10 @@ const ENV_FLATC_PATH: &str = "FLATC_PATH";
|
||||
|
||||
fn main() -> Result<(), AnyError> {
|
||||
let version = protobuf_compiler_version()?;
|
||||
|
||||
let need_compile = match version.compare_ext(&VERSION_PROTOBUF) {
|
||||
Ok(cmp::Ordering::Greater) => true,
|
||||
Ok(cmp::Ordering::Equal) => true,
|
||||
Ok(_) => {
|
||||
if let Some(version_err) = Version::build_error_message(&version, &VERSION_PROTOBUF) {
|
||||
println!("cargo:warning=Tool `protoc` {version_err}, skip compiling.");
|
||||
@@ -42,6 +46,7 @@ fn main() -> Result<(), AnyError> {
|
||||
};
|
||||
|
||||
if !need_compile {
|
||||
println!("no need to compile protos.{}", need_compile);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -121,13 +126,20 @@ fn main() -> Result<(), AnyError> {
|
||||
Err(_) => "flatc".to_string(),
|
||||
};
|
||||
|
||||
compile_flatbuffers_models(
|
||||
match compile_flatbuffers_models(
|
||||
&mut generated_mod_rs,
|
||||
&flatc_path,
|
||||
proto_dir.clone(),
|
||||
flatbuffer_out_dir.clone(),
|
||||
vec!["models"],
|
||||
)?;
|
||||
) {
|
||||
Ok(_) => {
|
||||
println!("Successfully compiled flatbuffers models.");
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("Failed to compile flatbuffers models: {e}").into());
|
||||
}
|
||||
}
|
||||
|
||||
fmt();
|
||||
Ok(())
|
||||
@@ -144,6 +156,7 @@ fn compile_flatbuffers_models<P: AsRef<Path>, S: AsRef<str>>(
|
||||
let version = flatbuffers_compiler_version(flatc_path)?;
|
||||
let need_compile = match version.compare_ext(&VERSION_FLATBUFFERS) {
|
||||
Ok(cmp::Ordering::Greater) => true,
|
||||
Ok(cmp::Ordering::Equal) => true,
|
||||
Ok(_) => {
|
||||
if let Some(version_err) = Version::build_error_message(&version, &VERSION_FLATBUFFERS) {
|
||||
println!("cargo:warning=Tool `{flatc_path}` {version_err}, skip compiling.");
|
||||
@@ -161,6 +174,23 @@ fn compile_flatbuffers_models<P: AsRef<Path>, S: AsRef<str>>(
|
||||
|
||||
// $rust_dir/mod.rs
|
||||
let mut sub_mod_rs = fs::File::create(rust_dir.join("mod.rs"))?;
|
||||
writeln!(
|
||||
&mut sub_mod_rs,
|
||||
r#"// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License."#
|
||||
)?;
|
||||
writeln!(&mut sub_mod_rs, "\n")?;
|
||||
writeln!(generated_mod_rs)?;
|
||||
writeln!(generated_mod_rs, "mod flatbuffers_generated;")?;
|
||||
for mod_name in mod_names.iter() {
|
||||
|
||||
@@ -225,6 +225,8 @@ message ReadAtResponse {
|
||||
message ListDirRequest {
|
||||
string disk = 1; // indicate which one in the disks
|
||||
string volume = 2;
|
||||
string dir_path = 3;
|
||||
int32 count = 4;
|
||||
}
|
||||
|
||||
message ListDirResponse {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.rustfs.com/en/introduction.html">Getting Started</a>
|
||||
<a href="https://docs.rustfs.com/installation/">Getting Started</a>
|
||||
· <a href="https://docs.rustfs.com/en/">Docs</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/issues">Bug reports</a>
|
||||
· <a href="https://github.com/rustfs/rustfs/discussions">Discussions</a>
|
||||
|
||||
@@ -58,13 +58,13 @@ struct StaticFiles;
|
||||
/// If the requested file is not found, it serves index.html as a fallback.
|
||||
/// If index.html is also not found, it returns a 404 Not Found response.
|
||||
///
|
||||
/// Arguments:
|
||||
/// # Arguments:
|
||||
/// - `uri`: The request URI.
|
||||
///
|
||||
/// Returns:
|
||||
/// # Returns:
|
||||
/// - An `impl IntoResponse` containing the static file content or a 404 response.
|
||||
///
|
||||
pub(crate) async fn static_handler(uri: Uri) -> impl IntoResponse {
|
||||
async fn static_handler(uri: Uri) -> impl IntoResponse {
|
||||
let mut path = uri.path().trim_start_matches('/');
|
||||
if path.is_empty() {
|
||||
path = "index.html"
|
||||
@@ -180,7 +180,8 @@ struct License {
|
||||
url: String,
|
||||
}
|
||||
|
||||
pub(crate) static CONSOLE_CONFIG: OnceLock<Config> = OnceLock::new();
|
||||
/// Global console configuration
|
||||
static CONSOLE_CONFIG: OnceLock<Config> = OnceLock::new();
|
||||
|
||||
#[allow(clippy::const_is_empty)]
|
||||
pub(crate) fn init_console_cfg(local_ip: IpAddr, port: u16) {
|
||||
@@ -199,12 +200,13 @@ pub(crate) fn init_console_cfg(local_ip: IpAddr, port: u16) {
|
||||
});
|
||||
}
|
||||
|
||||
// fn is_socket_addr_or_ip_addr(host: &str) -> bool {
|
||||
// host.parse::<SocketAddr>().is_ok() || host.parse::<IpAddr>().is_ok()
|
||||
// }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn license_handler() -> impl IntoResponse {
|
||||
/// License handler
|
||||
/// Returns the current license information of the console.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - 200 OK with JSON body containing license details.
|
||||
#[instrument]
|
||||
async fn license_handler() -> impl IntoResponse {
|
||||
let license = get_license().unwrap_or_default();
|
||||
|
||||
Response::builder()
|
||||
@@ -214,6 +216,7 @@ pub async fn license_handler() -> impl IntoResponse {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Check if the given IP address is a private IP
|
||||
fn _is_private_ip(ip: IpAddr) -> bool {
|
||||
match ip {
|
||||
IpAddr::V4(ip) => {
|
||||
@@ -229,8 +232,48 @@ fn _is_private_ip(ip: IpAddr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Version handler
|
||||
/// Returns the current version information of the console.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - 200 OK with JSON body containing version details if configuration is initialized.
|
||||
/// - 500 Internal Server Error if configuration is not initialized.
|
||||
#[instrument]
|
||||
async fn version_handler() -> impl IntoResponse {
|
||||
match CONSOLE_CONFIG.get() {
|
||||
Some(cfg) => Response::builder()
|
||||
.header("content-type", "application/json")
|
||||
.status(StatusCode::OK)
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"version": cfg.release.version,
|
||||
"version_info": cfg.version_info(),
|
||||
"date": cfg.release.date,
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap(),
|
||||
None => Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Console configuration not initialized"))
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration handler
|
||||
/// Returns the current console configuration in JSON format.
|
||||
/// The configuration is dynamically adjusted based on the request's host and scheme.
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `uri`: The request URI.
|
||||
/// - `Host(host)`: The host extracted from the request.
|
||||
/// - `headers`: The request headers.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - 200 OK with JSON body containing the console configuration if initialized.
|
||||
/// - 500 Internal Server Error if configuration is not initialized.
|
||||
#[instrument(fields(host))]
|
||||
pub async fn config_handler(uri: Uri, Host(host): Host, headers: HeaderMap) -> impl IntoResponse {
|
||||
async fn config_handler(uri: Uri, Host(host): Host, headers: HeaderMap) -> impl IntoResponse {
|
||||
// Get the scheme from the headers or use the URI scheme
|
||||
let scheme = headers
|
||||
.get(HeaderName::from_static("x-forwarded-proto"))
|
||||
@@ -275,7 +318,15 @@ pub async fn config_handler(uri: Uri, Host(host): Host, headers: HeaderMap) -> i
|
||||
}
|
||||
|
||||
/// Console access logging middleware
|
||||
async fn console_logging_middleware(req: Request, next: axum::middleware::Next) -> axum::response::Response {
|
||||
/// Logs each console access with method, URI, status code, and duration.
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `req`: The incoming request.
|
||||
/// - `next`: The next middleware or handler in the chain.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - The response from the next middleware or handler.
|
||||
async fn console_logging_middleware(req: Request, next: middleware::Next) -> Response {
|
||||
let method = req.method().clone();
|
||||
let uri = req.uri().clone();
|
||||
let start = std::time::Instant::now();
|
||||
@@ -367,6 +418,14 @@ async fn _setup_console_tls_config(tls_path: Option<&String>) -> Result<Option<R
|
||||
}
|
||||
|
||||
/// Get console configuration from environment variables
|
||||
/// Returns a tuple containing console configuration values from environment variables.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - rate_limit_enable: bool indicating if rate limiting is enabled.
|
||||
/// - rate_limit_rpm: u32 indicating the rate limit in requests per minute.
|
||||
/// - auth_timeout: u64 indicating the authentication timeout in seconds.
|
||||
/// - cors_allowed_origins: String containing allowed CORS origins.
|
||||
///
|
||||
fn get_console_config_from_env() -> (bool, u32, u64, String) {
|
||||
let rate_limit_enable = std::env::var(rustfs_config::ENV_CONSOLE_RATE_LIMIT_ENABLE)
|
||||
.unwrap_or_else(|_| rustfs_config::DEFAULT_CONSOLE_RATE_LIMIT_ENABLE.to_string())
|
||||
@@ -390,11 +449,27 @@ fn get_console_config_from_env() -> (bool, u32, u64, String) {
|
||||
(rate_limit_enable, rate_limit_rpm, auth_timeout, cors_allowed_origins)
|
||||
}
|
||||
|
||||
/// Check if the given path is for console access
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `path`: The request path.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - `true` if the path is for console access, `false` otherwise.
|
||||
pub fn is_console_path(path: &str) -> bool {
|
||||
path == "/favicon.ico" || path.starts_with(CONSOLE_PREFIX)
|
||||
}
|
||||
|
||||
/// Setup comprehensive middleware stack with tower-http features
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `cors_layer`: The CORS layer to apply.
|
||||
/// - `rate_limit_enable`: bool indicating if rate limiting is enabled.
|
||||
/// - `rate_limit_rpm`: u32 indicating the rate limit in requests per minute.
|
||||
/// - `auth_timeout`: u64 indicating the authentication timeout in seconds.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - A `Router` with the configured middleware stack.
|
||||
fn setup_console_middleware_stack(
|
||||
cors_layer: CorsLayer,
|
||||
rate_limit_enable: bool,
|
||||
@@ -405,6 +480,7 @@ fn setup_console_middleware_stack(
|
||||
.route("/favicon.ico", get(static_handler))
|
||||
.route(&format!("{CONSOLE_PREFIX}/license"), get(license_handler))
|
||||
.route(&format!("{CONSOLE_PREFIX}/config.json"), get(config_handler))
|
||||
.route(&format!("{CONSOLE_PREFIX}/version"), get(version_handler))
|
||||
.route(&format!("{CONSOLE_PREFIX}/health"), get(health_check).head(health_check))
|
||||
.nest(CONSOLE_PREFIX, Router::new().fallback_service(get(static_handler)))
|
||||
.fallback_service(get(static_handler));
|
||||
@@ -437,6 +513,13 @@ fn setup_console_middleware_stack(
|
||||
}
|
||||
|
||||
/// Console health check handler with comprehensive health information
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `method`: The HTTP method of the request.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - A `Response` containing the health check result.
|
||||
#[instrument]
|
||||
async fn health_check(method: Method) -> Response {
|
||||
let builder = Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
@@ -538,6 +621,12 @@ async fn health_check(method: Method) -> Response {
|
||||
}
|
||||
|
||||
/// Parse CORS allowed origins from configuration
|
||||
///
|
||||
/// # Arguments:
|
||||
/// - `origins`: An optional reference to a string containing allowed origins.
|
||||
///
|
||||
/// # Returns:
|
||||
/// - A `CorsLayer` configured with the specified origins.
|
||||
pub fn parse_cors_origins(origins: Option<&String>) -> CorsLayer {
|
||||
let cors_layer = CorsLayer::new()
|
||||
.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE, Method::OPTIONS])
|
||||
@@ -580,6 +669,10 @@ pub fn parse_cors_origins(origins: Option<&String>) -> CorsLayer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create and configure the console server router
|
||||
///
|
||||
/// # Returns:
|
||||
/// - A `Router` configured for the console server with middleware.
|
||||
pub(crate) fn make_console_server() -> Router {
|
||||
let (rate_limit_enable, rate_limit_rpm, auth_timeout, cors_allowed_origins) = get_console_config_from_env();
|
||||
// String to Option<&String>
|
||||
|
||||
@@ -213,7 +213,7 @@ pub async fn start_http_server(
|
||||
// Detailed endpoint information (showing all API endpoints)
|
||||
let api_endpoints = format!("{protocol}://{local_ip}:{server_port}");
|
||||
let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}");
|
||||
|
||||
let now_time = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
if opt.console_enable {
|
||||
admin::console::init_console_cfg(local_ip, server_port);
|
||||
|
||||
@@ -227,11 +227,13 @@ pub async fn start_http_server(
|
||||
|
||||
);
|
||||
|
||||
println!("Console WebUI Start Time: {now_time}");
|
||||
println!("Console WebUI available at: {protocol}://{local_ip}:{server_port}/rustfs/console/index.html");
|
||||
println!("Console WebUI (localhost): {protocol}://127.0.0.1:{server_port}/rustfs/console/index.html",);
|
||||
} else {
|
||||
info!(" API: {} {}", api_endpoints, localhost_endpoint);
|
||||
println!(" API: {api_endpoints} {localhost_endpoint}");
|
||||
info!(target: "rustfs::main::startup","RustFS API: {api_endpoints} {localhost_endpoint}");
|
||||
println!("RustFS API: {api_endpoints} {localhost_endpoint}");
|
||||
println!("RustFS Start Time: {now_time}");
|
||||
if DEFAULT_ACCESS_KEY.eq(&opt.access_key) && DEFAULT_SECRET_KEY.eq(&opt.secret_key) {
|
||||
warn!(
|
||||
"Detected default credentials '{}:{}', we recommend that you change these values with 'RUSTFS_ACCESS_KEY' and 'RUSTFS_SECRET_KEY' environment variables",
|
||||
|
||||
@@ -2773,7 +2773,7 @@ impl S3 for FS {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let output = ListObjectVersionsOutput {
|
||||
// is_truncated: Some(object_infos.is_truncated),
|
||||
is_truncated: Some(object_infos.is_truncated),
|
||||
max_keys: Some(key_count),
|
||||
delimiter,
|
||||
name: Some(bucket),
|
||||
|
||||
@@ -782,7 +782,7 @@ impl Node for NodeService {
|
||||
async fn list_dir(&self, request: Request<ListDirRequest>) -> Result<Response<ListDirResponse>, Status> {
|
||||
let request = request.into_inner();
|
||||
if let Some(disk) = self.find_disk(&request.disk).await {
|
||||
match disk.list_dir("", &request.volume, "", 0).await {
|
||||
match disk.list_dir("", &request.volume, &request.dir_path, request.count).await {
|
||||
Ok(volumes) => Ok(Response::new(ListDirResponse {
|
||||
success: true,
|
||||
volumes,
|
||||
@@ -2623,6 +2623,8 @@ mod tests {
|
||||
let request = Request::new(ListDirRequest {
|
||||
disk: "invalid-disk-path".to_string(),
|
||||
volume: "test-volume".to_string(),
|
||||
dir_path: "test-dir-path".to_string(),
|
||||
count: 10,
|
||||
});
|
||||
|
||||
let response = service.list_dir(request).await;
|
||||
|
||||
67
scripts/install-flatc.sh
Executable file
67
scripts/install-flatc.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# Install flatc 25.9.23 on macOS
|
||||
|
||||
set -e
|
||||
|
||||
FLATC_VERSION="25.9.23"
|
||||
ARCH=$(uname -m)
|
||||
INSTALL_DIR="${HOME}/.local/bin"
|
||||
FLATC_BIN="${INSTALL_DIR}/flatc"
|
||||
|
||||
# Select download URL based on architecture
|
||||
if [ "$ARCH" = "arm64" ]; then
|
||||
# Apple Silicon (M1/M2/M3)
|
||||
FLATC_URL="https://github.com/google/flatbuffers/releases/download/v${FLATC_VERSION}/Mac.flatc.binary.zip"
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
# Intel Mac
|
||||
FLATC_URL="https://github.com/google/flatbuffers/releases/download/v${FLATC_VERSION}/MacIntel.flatc.binary.zip"
|
||||
else
|
||||
echo "Error: Unsupported architecture $ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Downloading flatc ${FLATC_VERSION} for ${ARCH}..."
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
# Download and extract
|
||||
curl -L -o flatc.zip "$FLATC_URL"
|
||||
unzip -q flatc.zip
|
||||
|
||||
# Create install directory
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# Backup existing version if present
|
||||
if [ -f "$FLATC_BIN" ]; then
|
||||
echo "Backing up existing flatc to ${FLATC_BIN}.backup"
|
||||
mv "$FLATC_BIN" "${FLATC_BIN}.backup"
|
||||
fi
|
||||
|
||||
# Install flatc
|
||||
cp flatc "$FLATC_BIN"
|
||||
chmod +x "$FLATC_BIN"
|
||||
|
||||
# Clean up temporary files
|
||||
cd -
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Verify installation
|
||||
echo ""
|
||||
echo "Verifying installation..."
|
||||
"$FLATC_BIN" --version
|
||||
|
||||
# Check PATH
|
||||
if [[ ":$PATH:" != *":${INSTALL_DIR}:"* ]]; then
|
||||
echo ""
|
||||
echo "⚠️ Warning: ${INSTALL_DIR} is not in PATH"
|
||||
echo "Please add the following to ~/.zshrc or ~/.bash_profile:"
|
||||
echo ""
|
||||
echo " export PATH=\"\${HOME}/.local/bin:\$PATH\""
|
||||
echo ""
|
||||
echo "Then run: source ~/.zshrc"
|
||||
else
|
||||
echo ""
|
||||
echo "✅ flatc ${FLATC_VERSION} installed successfully!"
|
||||
echo "Location: $FLATC_BIN"
|
||||
fi
|
||||
|
||||
67
scripts/install-protoc.sh
Executable file
67
scripts/install-protoc.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# Install protoc 33.1 on macOS
|
||||
|
||||
set -e
|
||||
|
||||
PROTOC_VERSION="33.1"
|
||||
ARCH=$(uname -m)
|
||||
INSTALL_DIR="${HOME}/.local/bin"
|
||||
PROTOC_BIN="${INSTALL_DIR}/protoc"
|
||||
|
||||
# Select download URL based on architecture
|
||||
if [ "$ARCH" = "arm64" ]; then
|
||||
# Apple Silicon (M1/M2/M3)
|
||||
PROTOC_URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-osx-aarch_64.zip"
|
||||
elif [ "$ARCH" = "x86_64" ]; then
|
||||
# Intel Mac
|
||||
PROTOC_URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-osx-x86_64.zip"
|
||||
else
|
||||
echo "Error: Unsupported architecture $ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Downloading protoc ${PROTOC_VERSION} for ${ARCH}..."
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
# Download and extract
|
||||
curl -L -o protoc.zip "$PROTOC_URL"
|
||||
unzip -q protoc.zip
|
||||
|
||||
# Create install directory
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# Backup existing version if present
|
||||
if [ -f "$PROTOC_BIN" ]; then
|
||||
echo "Backing up existing protoc to ${PROTOC_BIN}.backup"
|
||||
mv "$PROTOC_BIN" "${PROTOC_BIN}.backup"
|
||||
fi
|
||||
|
||||
# Install protoc
|
||||
cp bin/protoc "$PROTOC_BIN"
|
||||
chmod +x "$PROTOC_BIN"
|
||||
|
||||
# Clean up temporary files
|
||||
cd -
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Verify installation
|
||||
echo ""
|
||||
echo "Verifying installation..."
|
||||
"$PROTOC_BIN" --version
|
||||
|
||||
# Check PATH
|
||||
if [[ ":$PATH:" != *":${INSTALL_DIR}:"* ]]; then
|
||||
echo ""
|
||||
echo "⚠️ Warning: ${INSTALL_DIR} is not in PATH"
|
||||
echo "Please add the following to ~/.zshrc or ~/.bash_profile:"
|
||||
echo ""
|
||||
echo " export PATH=\"\${HOME}/.local/bin:\$PATH\""
|
||||
echo ""
|
||||
echo "Then run: source ~/.zshrc"
|
||||
else
|
||||
echo ""
|
||||
echo "✅ protoc ${PROTOC_VERSION} installed successfully!"
|
||||
echo "Location: $PROTOC_BIN"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user