Merge branch 'release/v3.1.1'

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	README.md
#	README_ZH.md
#	client-java/orbien-client/pom.xml
#	client-java/orbien-client/src/main/java/io/github/lxien/orbien/client/OrbienClient.java
#	client-java/orbien-spring-boot-demo/pom.xml
#	client-java/orbien-spring-boot-starter/pom.xml
#	client-java/pom.xml
#	docs/docs/integrations/springboot.mdx
#	docs/i18n/en/docusaurus-plugin-content-docs/current/integrations/springboot.mdx
#	docs/package.json
#	docs/src/components/DownloadMatrix/index.tsx
#	server-ui/package-lock.json
#	server-ui/package.json
This commit is contained in:
lxien
2026-08-20 17:53:23 +08:00
26 changed files with 72 additions and 61 deletions
Generated
+4 -4
View File
@@ -3988,7 +3988,7 @@ dependencies = [
[[package]]
name = "orbien-client"
version = "3.1.0"
version = "3.1.1"
dependencies = [
"anyhow",
"async-trait",
@@ -4009,7 +4009,7 @@ dependencies = [
[[package]]
name = "orbien-core"
version = "3.1.0"
version = "3.1.1"
dependencies = [
"anyhow",
"base64",
@@ -4041,7 +4041,7 @@ dependencies = [
[[package]]
name = "orbien-desktop"
version = "3.1.0"
version = "3.1.1"
dependencies = [
"anyhow",
"libc",
@@ -4059,7 +4059,7 @@ dependencies = [
[[package]]
name = "orbien-server"
version = "3.1.0"
version = "3.1.1"
dependencies = [
"anyhow",
"axum",
+1 -1
View File
@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
version = "3.1.0"
version = "3.1.1"
edition = "2021"
license = "Apache-2.0"
authors = ["orbien"]
+1 -1
View File
@@ -21,7 +21,7 @@
<img src="https://img.shields.io/badge/Rust-Tokio-orange?style=for-the-badge&logo=rust&logoColor=white" alt="Rust"/>
</a>
<a href="https://github.com/orbien-org/orbien/releases">
<img src="https://img.shields.io/badge/orbien-3.1.0-blue?style=for-the-badge" alt="orbien:3.1.0"/>
<img src="https://img.shields.io/badge/orbien-3.1.1-blue?style=for-the-badge" alt="orbien:3.1.1"/>
</a>
<a href="https://somsubhra.github.io/github-release-stats/?username=orbien-org&repository=orbien">
<img src="https://img.shields.io/github/downloads/orbien-org/orbien/total?style=for-the-badge" alt="Downloads"/>
+1 -1
View File
@@ -21,7 +21,7 @@
<img src="https://img.shields.io/badge/Rust-Tokio-orange?style=for-the-badge&logo=rust&logoColor=white" alt="Rust"/>
</a>
<a href="https://github.com/orbien-org/orbien/releases">
<img src="https://img.shields.io/badge/orbien-3.1.0-blue?style=for-the-badge" alt="orbien:3.1.0"/>
<img src="https://img.shields.io/badge/orbien-3.1.1-blue?style=for-the-badge" alt="orbien:3.1.1"/>
</a>
<a href="https://somsubhra.github.io/github-release-stats/?username=orbien-org&repository=orbien">
<img src="https://img.shields.io/github/downloads/orbien-org/orbien/total?style=for-the-badge" alt="Downloads"/>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>io.github.lxien</groupId>
<artifactId>orbien</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</parent>
<artifactId>orbien-client</artifactId>
@@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
public final class OrbienClient implements AutoCloseable {
private static final Logger log = LoggerFactory.getLogger(OrbienClient.class);
private static final String VERSION = "3.1.0";
private static final String VERSION = "3.1.1";
private final OrbienClientConfig config;
private final AtomicBoolean started = new AtomicBoolean(false);
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>io.github.lxien</groupId>
<artifactId>orbien</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</parent>
<artifactId>orbien-spring-boot-demo</artifactId>
@@ -7,7 +7,7 @@
<parent>
<groupId>io.github.lxien</groupId>
<artifactId>orbien</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</parent>
<artifactId>orbien-spring-boot-starter</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>io.github.lxien</groupId>
<artifactId>orbien</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
<packaging>pom</packaging>
<name>orbien</name>
+1
View File
@@ -1,3 +1,4 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod client_log_layer;
mod config_bridge;
mod i18n;
+2 -2
View File
@@ -19,13 +19,13 @@ import TabItem from '@theme/TabItem';
<dependency>
<groupId>io.github.lxien</groupId>
<artifactId>orbien-spring-boot-starter</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</dependency>
```
</TabItem>
<TabItem value="Gradle" label="Gradle">
```groovy
implementation("io.github.lxien:orbien-spring-boot-starter:3.1.0")
implementation("io.github.lxien:orbien-spring-boot-starter:3.1.1")
```
</TabItem>
</Tabs>
@@ -19,13 +19,13 @@ import TabItem from '@theme/TabItem';
<dependency>
<groupId>io.github.lxien</groupId>
<artifactId>orbien-spring-boot-starter</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</dependency>
```
</TabItem>
<TabItem value="Gradle" label="Gradle">
```groovy
implementation("io.github.lxien:orbien-spring-boot-starter:3.1.0")
implementation("io.github.lxien:orbien-spring-boot-starter:3.1.1")
```
</TabItem>
</Tabs>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "orbien-docs",
"version": "3.1.0",
"version": "3.1.1",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
+1 -1
View File
@@ -6,7 +6,7 @@ import styles from './styles.module.css';
const REPO = 'orbien-org/orbien';
const FALLBACK_VERSION = '3.1.0';
const FALLBACK_VERSION = '3.1.1';
type OsId = 'windows' | 'linux' | 'darwin' | 'freebsd';
type ArchId = 'amd64' | 'arm64';
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "orbien-server-ui",
"version": "3.1.0",
"version": "3.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "orbien-server-ui",
"version": "3.1.0",
"version": "3.1.1",
"dependencies": {
"vue": "^3.5.22",
"vue-i18n": "^11.4.8",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "orbien-server-ui",
"private": true,
"version": "3.1.0",
"version": "3.1.1",
"type": "module",
"scripts": {
"dev": "vite",
+13 -5
View File
@@ -1,9 +1,9 @@
use super::model::{
ApiResponse, ClientInfo, Page, TunnelInfo, TunnelTrafficPoint, TunnelTrafficResp, SystemConfig,
SystemInfo, SystemStatus,
ApiResponse, ClientInfo, Page, SystemConfig, SystemInfo, SystemStatus, TunnelInfo,
TunnelTrafficPoint, TunnelTrafficResp,
};
use super::DashState;
use crate::metrics::{TunnelTrafficHistory, TrafficWindow};
use crate::metrics::{TrafficWindow, TunnelTrafficHistory};
use axum::body::Body;
use axum::extract::{Path, Query, State};
use axum::http::{header, HeaderMap, HeaderValue, Request, StatusCode};
@@ -241,7 +241,11 @@ async fn get_client(
) -> Result<Json<ApiResponse<ClientInfo>>, StatusCode> {
let session_id = urlencoding_decode(&session_id);
let snap = state.svc.dashboard_snapshot().await;
match snap.clients.into_iter().find(|c| c.session_id == session_id) {
match snap
.clients
.into_iter()
.find(|c| c.session_id == session_id)
{
Some(c) => Ok(Json(ApiResponse::ok(c))),
None => Err(StatusCode::NOT_FOUND),
}
@@ -305,7 +309,11 @@ async fn tunnel_traffic(
Query(q): Query<TrafficQuery>,
) -> Result<Json<ApiResponse<TunnelTrafficResp>>, StatusCode> {
let name = urlencoding_decode(&name);
match state.svc.metrics().tunnel_traffic(&name, traffic_window(&q)) {
match state
.svc
.metrics()
.tunnel_traffic(&name, traffic_window(&q))
{
Some(hist) => Ok(Json(ApiResponse::ok(traffic_resp(hist)))),
None => Err(StatusCode::NOT_FOUND),
}
+1 -1
View File
@@ -2,8 +2,8 @@ mod access;
mod control;
mod dashboard;
mod metrics;
mod tunnel;
mod service;
mod tunnel;
use anyhow::Result;
use clap::Parser;
+5 -1
View File
@@ -149,7 +149,11 @@ impl MemMetrics {
g.tunnels.get(name).map(|p| to_tunnel_snapshot(name, p))
}
pub fn tunnel_traffic(&self, name: &str, window: TrafficWindow) -> Option<TunnelTrafficHistory> {
pub fn tunnel_traffic(
&self,
name: &str,
window: TrafficWindow,
) -> Option<TunnelTrafficHistory> {
let g = self.state.lock().expect("metrics lock");
let p = g.tunnels.get(name)?;
Some(match window {
+1 -1
View File
@@ -4,7 +4,7 @@ mod hour_counter;
mod mem;
mod traits;
pub use mem::{MemMetrics, TunnelTrafficHistory, TrafficWindow};
pub use mem::{MemMetrics, TrafficWindow, TunnelTrafficHistory};
pub use traits::ServerMetrics;
pub const RESERVE_DAYS: usize = 7;
+4 -1
View File
@@ -73,7 +73,10 @@ impl Service {
}
}
pub(super) async fn run_kcp(self: Arc<Self>, mut listener: kcp_tokio::KcpListener) -> Result<()> {
pub(super) async fn run_kcp(
self: Arc<Self>,
mut listener: kcp_tokio::KcpListener,
) -> Result<()> {
loop {
let (stream, peer) = transport::accept_kcp(&mut listener).await?;
tracing::debug!(%peer, transport = "kcp", "incoming connection");
+2 -6
View File
@@ -99,9 +99,7 @@ impl Service {
let gw = Arc::clone(gw);
let access = Arc::clone(&this.access);
let shutdown = Arc::clone(&gw_shutdown);
set.spawn(
async move { run_http_gw_listener(bind, port, gw, access, shutdown).await },
);
set.spawn(async move { run_http_gw_listener(bind, port, gw, access, shutdown).await });
}
if let Some(ref gw) = this.https_gw {
@@ -110,9 +108,7 @@ impl Service {
let gw = Arc::clone(gw);
let access = Arc::clone(&this.access);
let shutdown = Arc::clone(&gw_shutdown);
set.spawn(async move {
run_https_gw_listener(bind, port, gw, access, shutdown).await
});
set.spawn(async move { run_https_gw_listener(bind, port, gw, access, shutdown).await });
}
if this.cfg.quic_enabled() {
+4 -1
View File
@@ -152,7 +152,10 @@ impl Service {
c.push_data_conn(stream).await;
Ok(())
}
None => Err(anyhow!("unknown session_id for data conn: {}", nw.session_id)),
None => Err(anyhow!(
"unknown session_id for data conn: {}",
nw.session_id
)),
}
}
}
+1 -4
View File
@@ -121,10 +121,7 @@ pub fn normalize_host(host: &str) -> String {
.to_ascii_lowercase()
}
pub fn build_domains(
domains: &[String],
root_domain: &str,
) -> anyhow::Result<Vec<String>> {
pub fn build_domains(domains: &[String], root_domain: &str) -> anyhow::Result<Vec<String>> {
let root = normalize_host(root_domain);
let entries: Vec<String> = domains
.iter()
+15 -16
View File
@@ -1,6 +1,6 @@
use super::gw::{
build_domains, expand_locations, normalize_host, route_basic_auth_ok, route_user_from_headers,
HttpRoute, HttpGw,
HttpGw, HttpRoute,
};
use crate::access::{prepare_ingress, AccessPolicy};
use crate::control::Control;
@@ -42,21 +42,20 @@ impl HttpTunnel {
for domain in &domains {
for location in &locations {
gw
.register(
domain,
HttpRoute {
tunnel_name: name.clone(),
control: Arc::downgrade(&control),
location: location.clone(),
host_header_rewrite: rewrite.clone(),
basic_auth_user: basic_auth_user.clone(),
basic_auth_password: basic_auth_password.clone(),
route_by_http_user: route_by_http_user.clone(),
limiter: limiter.clone(),
},
)
.await?;
gw.register(
domain,
HttpRoute {
tunnel_name: name.clone(),
control: Arc::downgrade(&control),
location: location.clone(),
host_header_rewrite: rewrite.clone(),
basic_auth_user: basic_auth_user.clone(),
basic_auth_password: basic_auth_password.clone(),
route_by_http_user: route_by_http_user.clone(),
limiter: limiter.clone(),
},
)
.await?;
}
}
+4 -4
View File
@@ -1,13 +1,13 @@
mod gw;
mod http;
mod https;
mod manager;
mod tcp;
mod udp;
mod gw;
pub use gw::HttpGw;
pub use http::{run_http_gw_listener, HttpTunnel};
pub use https::{run_https_gw_listener, HttpsTunnel, HttpsGw};
pub use manager::{format_local_addr, TunnelManager, TunnelSummary, RegisteredTunnel};
pub use https::{run_https_gw_listener, HttpsGw, HttpsTunnel};
pub use manager::{format_local_addr, RegisteredTunnel, TunnelManager, TunnelSummary};
pub use tcp::TcpTunnel;
pub use udp::UdpTunnel;
pub use gw::HttpGw;