0.2.88
This commit is contained in:
1 parent
df403c0aa7
commit
9e133628e5
17 files changed
+270
-34
No files matched your search
@@ -20,6 +20,7 @@ use axum::{
|
||||
use pages::*;
|
||||
use tower::{ServiceBuilder, service_fn};
|
||||
use tower_http::{
|
||||
compression::CompressionLayer,
|
||||
services::ServeDir,
|
||||
set_header::SetResponseHeaderLayer,
|
||||
trace::{MakeSpan, TraceLayer},
|
||||
@@ -48,6 +49,7 @@ pub fn router(
|
||||
static_dir: &str,
|
||||
upload_body_limit_bytes: usize,
|
||||
asset_cache_max_age_seconds: u64,
|
||||
http_compression: bool,
|
||||
) -> Router {
|
||||
let asset_version = state.asset_version.clone();
|
||||
let asset_not_found = service_fn(move |_request| {
|
||||
@@ -259,6 +261,12 @@ pub fn router(
|
||||
.layer(TraceLayer::new_for_http().make_span_with(PathOnlyMakeSpan))
|
||||
.layer(middleware::from_fn(require_csrf_token))
|
||||
.layer(middleware::from_fn(apply_response_header_policy))
|
||||
// Negotiate HTTP compression only when enabled; WebSocket frames are unaffected.
|
||||
.layer(
|
||||
CompressionLayer::new()
|
||||
.br(http_compression)
|
||||
.gzip(http_compression),
|
||||
)
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ pub struct Config {
|
||||
pub guest_upload_max_size_bytes: usize,
|
||||
pub asset_version: String,
|
||||
pub asset_cache_max_age_seconds: u64,
|
||||
pub http_compression: bool,
|
||||
pub file_cache_max_age_seconds: u64,
|
||||
pub files_public_url: Option<String>,
|
||||
pub smtp: Option<crate::state::SmtpConfig>,
|
||||
@@ -174,6 +175,7 @@ impl Config {
|
||||
guest_upload_max_size_mb,
|
||||
)?,
|
||||
asset_version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
http_compression: values.bool("HTTP_COMPRESSION", false)?,
|
||||
asset_cache_max_age_seconds: values
|
||||
.nonnegative_u64("ASSET_CACHE_MAX_AGE_SECONDS", 600)?,
|
||||
file_cache_max_age_seconds: values
|
||||
|
||||
@@ -22,6 +22,7 @@ const KNOWN_CONFIG_KEYS: &[&str] = &[
|
||||
"GUEST_UPLOAD_ENABLED",
|
||||
"GUEST_UPLOAD_MAX_SIZE_MB",
|
||||
"ASSET_CACHE_MAX_AGE_SECONDS",
|
||||
"HTTP_COMPRESSION",
|
||||
"FILE_CACHE_MAX_AGE_SECONDS",
|
||||
"REGISTRATION_ENABLED",
|
||||
"ACCOUNT_CONFIRMATION_REQUIRED",
|
||||
|
||||
@@ -68,6 +68,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
guest_upload_enabled = config.guest_upload_enabled,
|
||||
guest_upload_max_size_bytes = config.guest_upload_max_size_bytes,
|
||||
asset_cache_max_age_seconds = config.asset_cache_max_age_seconds,
|
||||
http_compression = config.http_compression,
|
||||
file_cache_max_age_seconds = config.file_cache_max_age_seconds,
|
||||
files_public_url = config.files_public_url.as_deref().unwrap_or("application origin"),
|
||||
registration_enabled = config.registration_enabled,
|
||||
@@ -173,6 +174,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
&config.static_dir,
|
||||
config.upload_body_limit_bytes(),
|
||||
config.asset_cache_max_age_seconds,
|
||||
config.http_compression,
|
||||
);
|
||||
let address = SocketAddr::new(config.host, config.port);
|
||||
let listener = TcpListener::bind(address).await?;
|
||||
|
||||
+18
-11
@@ -863,6 +863,7 @@ async fn handle_socket(
|
||||
access_refresh.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
access_refresh.tick().await;
|
||||
let (mut sender, mut receiver) = socket.split();
|
||||
let mut last_broadcast_access_check = Instant::now() - Duration::from_secs(2);
|
||||
if send_split(
|
||||
&mut sender,
|
||||
&ServerMessage::Diagnostics {
|
||||
@@ -1053,17 +1054,23 @@ async fn handle_socket(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let (read_allowed, _) = current_resource_access(
|
||||
&state,
|
||||
"workspace",
|
||||
&workspace_slug,
|
||||
&external_tokens,
|
||||
session_token.as_deref(),
|
||||
password_ok,
|
||||
).await;
|
||||
if !read_allowed {
|
||||
let _=send_split(&mut sender,&ServerMessage::Error{message:"Access expired or revoked".into()}).await;
|
||||
break;
|
||||
// Broadcasts can arrive hundreds of times a second per connection.
|
||||
// Keep access checks off the per-message hot path; the separate
|
||||
// access_refresh ticker also enforces revocation while idle.
|
||||
if last_broadcast_access_check.elapsed() >= Duration::from_secs(1) {
|
||||
let (read_allowed, _) = current_resource_access(
|
||||
&state,
|
||||
"workspace",
|
||||
&workspace_slug,
|
||||
&external_tokens,
|
||||
session_token.as_deref(),
|
||||
password_ok,
|
||||
).await;
|
||||
if !read_allowed {
|
||||
let _=send_split(&mut sender,&ServerMessage::Error{message:"Access expired or revoked".into()}).await;
|
||||
break;
|
||||
}
|
||||
last_broadcast_access_check = Instant::now();
|
||||
}
|
||||
match update {
|
||||
Ok(RoomEvent::Document(update))=>if send_split(&mut sender,&ServerMessage::Document{base_revision_id:update.base_revision_id,revision_id:update.revision_id,updated_at:update.updated_at,author:update.author,client_id:update.client_id,update_id:update.update_id,operation:update.operation,owner_replacements:update.owner_replacements}).await.is_err(){break;},
|
||||
|
||||
+18
-11
@@ -356,6 +356,7 @@ async fn handle_pad_socket(
|
||||
.await;
|
||||
let _ = channel.send(RoomEvent::Presence(users));
|
||||
let mut last_chat = Instant::now() - Duration::from_secs(1);
|
||||
let mut last_broadcast_access_check = Instant::now() - Duration::from_secs(2);
|
||||
let mut access_refresh = tokio::time::interval(Duration::from_secs(10));
|
||||
access_refresh.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
access_refresh.tick().await;
|
||||
@@ -552,17 +553,23 @@ async fn handle_pad_socket(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let (read_allowed, _) = current_resource_access(
|
||||
&state,
|
||||
"pad",
|
||||
&slug,
|
||||
&external_tokens,
|
||||
session_token.as_deref(),
|
||||
password_ok,
|
||||
).await;
|
||||
if !read_allowed {
|
||||
let _=send_pad_split(&mut sender,&PadServerMessage::Error{message:"Access expired or revoked".into()}).await;
|
||||
break;
|
||||
// Broadcasts can arrive hundreds of times a second per connection.
|
||||
// Keep access checks off the per-message hot path; the separate
|
||||
// access_refresh ticker also enforces revocation while idle.
|
||||
if last_broadcast_access_check.elapsed() >= Duration::from_secs(1) {
|
||||
let (read_allowed, _) = current_resource_access(
|
||||
&state,
|
||||
"pad",
|
||||
&slug,
|
||||
&external_tokens,
|
||||
session_token.as_deref(),
|
||||
password_ok,
|
||||
).await;
|
||||
if !read_allowed {
|
||||
let _=send_pad_split(&mut sender,&PadServerMessage::Error{message:"Access expired or revoked".into()}).await;
|
||||
break;
|
||||
}
|
||||
last_broadcast_access_check = Instant::now();
|
||||
}
|
||||
match update {
|
||||
Ok(RoomEvent::Document(u))=>if send_pad_split(&mut sender,&PadServerMessage::Document{base_revision_id:u.base_revision_id,revision_id:u.revision_id,updated_at:u.updated_at,author:u.author,client_id:u.client_id,update_id:u.update_id,operation:u.operation,owner_replacements:u.owner_replacements}).await.is_err(){break;},
|
||||
|
||||
Reference in new issue
Block a user