lingxia-proxy 0.9.0

Local HTTP CONNECT proxy with PAC routing and optional MITM capture
Documentation
# lingxia-proxy

A local proxy runtime used by LingXia browser shells.

It provides:

- A local HTTP proxy listener bound on `127.0.0.1:*`
- Runtime-swappable routing between `Direct` and upstream `SOCKS5`
- Optional rule-list based proxy routing with cached rule updates
- Optional HTTPS MITM capture for development/debugging

## Scope

This crate is a low-level runtime component. It does not define product UI,
settings pages, or JS host APIs. In the current workspace those are owned by
`lingxia-shell`.

The main public types exported by this crate are:

- `LocalProxy`
- `ProxyRouter`
- `FixedRouter`
- `ProfileRouter`
- `Profile`
- `RouteDecision`
- `UpstreamConfig`
- `Socks5Credentials`
- `RuleListRouter` with feature `rule-list-routing`
- `CaConfig` and capture session types with feature `capture`

## Quick Start

```rust
use std::sync::Arc;
use lingxia_proxy::{FixedRouter, LocalProxy, UpstreamConfig};

let router = Arc::new(FixedRouter(UpstreamConfig::Direct));
let proxy = LocalProxy::bind("127.0.0.1:0", router).await?;
let addr = proxy.local_addr();

let proxy_task = proxy.clone();
tokio::spawn(async move {
    proxy_task.run().await;
});
```

`LocalProxy` accepts:

- `CONNECT host:port` tunnel requests
- Standard HTTP proxy requests for plain `http://` traffic

## Routing

### Fixed Upstream

```rust
use std::sync::Arc;
use lingxia_proxy::{FixedRouter, Socks5Credentials, UpstreamConfig};

let router = Arc::new(FixedRouter(UpstreamConfig::Socks5 {
    host: "127.0.0.1".into(),
    port: 1080,
    credentials: Some(Socks5Credentials {
        username: "user".into(),
        password: "pass".into(),
    }),
}));
proxy.set_router(router);
```

### Named Profiles

```rust
use std::sync::Arc;
use lingxia_proxy::{Profile, ProfileRouter, UpstreamConfig};

let mut router = ProfileRouter::new(vec![
    Profile {
        name: "direct".into(),
        upstream: UpstreamConfig::Direct,
    },
    Profile {
        name: "proxy".into(),
        upstream: UpstreamConfig::Socks5 {
            host: "127.0.0.1".into(),
            port: 1080,
            credentials: None,
        },
    },
]);
router.activate("proxy");
proxy.set_router(Arc::new(router));
```

### Custom Router

```rust
use lingxia_proxy::{ProxyError, ProxyRouter, RouteDecision, UpstreamConfig};

struct BlockExample;

impl ProxyRouter for BlockExample {
    fn route(&self, host: &str, _port: u16) -> Result<RouteDecision, ProxyError> {
        if host.ends_with(".example.invalid") {
            return Ok(RouteDecision::Block);
        }
        Ok(RouteDecision::Upstream(UpstreamConfig::Direct))
    }
}
```

## Rule-List Routing

Enable feature `rule-list-routing` to use:

- `RuleListRouter`
- `fetch_encoded_from_url(...)`
- `validate_source_url(...)`

This is intended for shells that want an "Auto Switch" style mode backed by a
downloaded rule list plus their own higher-level settings/runtime logic. The
current implementation supports gfwlist-compatible sources, but the Cargo
feature is named after the product capability rather than a specific source.

## HTTPS MITM Capture

Enable feature `capture` to use:

- `CaConfig`
- `session_receiver()`
- `CapturedSession` and related capture types

Important notes:

- This is for development/debugging use.
- The caller must provide and install a CA certificate.
- Upstream HTTPS connections are validated against the system/native root store.
- If upstream TLS validation fails, interception fails instead of silently
  trusting the upstream certificate.

## Feature Flags

- `rule-list-routing`
  Adds rule-list routing and HTTPS download support for rule list refresh.
- `capture`
  Adds MITM interception and structured HTTP capture types.