mirror of
https://github.com/icewind1991/warp-real-ip.git
synced 2026-08-02 08:14:49 +02:00
updates and warp 0.4
This commit is contained in:
parent
7b33c0d79d
commit
9a3991d243
9 changed files with 393 additions and 813 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
17
.github/workflows/ci.yaml
vendored
Normal file
17
.github/workflows/ci.yaml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: "CI"
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
checks:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: cachix/install-nix-action@v26
|
||||||
|
- uses: icewind1991/attic-action@v1
|
||||||
|
with:
|
||||||
|
name: ci
|
||||||
|
instance: https://cache.icewind.me
|
||||||
|
authToken: "${{ secrets.ATTIC_TOKEN }}"
|
||||||
|
- run: nix flake check --keep-going
|
||||||
33
.github/workflows/rust.yml
vendored
33
.github/workflows/rust.yml
vendored
|
|
@ -1,33 +0,0 @@
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
name: CI
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
- uses: Swatinem/rust-cache@v1
|
|
||||||
- uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: check
|
|
||||||
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Tests
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
- uses: Swatinem/rust-cache@v1
|
|
||||||
- uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1 +1,4 @@
|
||||||
/target
|
.idea
|
||||||
|
target
|
||||||
|
result
|
||||||
|
.direnv
|
||||||
1010
Cargo.lock
generated
1010
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
15
Cargo.toml
15
Cargo.toml
|
|
@ -1,19 +1,22 @@
|
||||||
[package]
|
[package]
|
||||||
name = "warp-real-ip"
|
name = "warp-real-ip"
|
||||||
description = "Warp filter to get the \"real ip\" of the remote client"
|
description = "Warp filter to get the \"real ip\" of the remote client"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2024"
|
||||||
keywords = ["warp"]
|
keywords = ["warp"]
|
||||||
categories = ["web-programming::http-server"]
|
categories = ["web-programming::http-server"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/icewind1991/warp-real-ip"
|
repository = "https://github.com/icewind1991/warp-real-ip"
|
||||||
documentation = "https://docs.rs/warp-real-ip"
|
documentation = "https://docs.rs/warp-real-ip"
|
||||||
|
rust-version = "1.85.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
warp = { version = "0.3" }
|
warp = { version = "0.4" }
|
||||||
rfc7239 = "0.1"
|
rfc7239 = "0.1.3"
|
||||||
ipnetwork = "0.18"
|
ipnetwork = "0.21"
|
||||||
|
comma-separated = "0.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.0", features = ["macros"] }
|
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
|
||||||
|
warp = { version = "0.4", features = ["test"] }
|
||||||
|
|
|
||||||
107
flake.lock
generated
Normal file
107
flake.lock
generated
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"crane": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780099841,
|
||||||
|
"narHash": "sha256-EVZd2RsbpreRUDSi9rBwPY+ZxoyMaiEBbZxxhljbaS4=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "0532eb17955225173906d671fb36306bdeb1e2dc",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flakelight": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1783953866,
|
||||||
|
"narHash": "sha256-S2qmQTzeI270WnguYV6R0vXDgtekjjCB7HQI9QiqDGI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flakelight",
|
||||||
|
"rev": "c9219d15f7d74ba690cba3b613f4ef2a08c16840",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flakelight",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mill-scale": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane",
|
||||||
|
"flakelight": [
|
||||||
|
"flakelight"
|
||||||
|
],
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780231986,
|
||||||
|
"narHash": "sha256-OyafczPtzE0Xa2zl3j/KvV2+ZVYGhYQHt0MOVWtDXlY=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "f5cbda29b945df03256bf63c22fa4cd5fa429e67",
|
||||||
|
"revCount": 72,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://codeberg.org/icewind/mill-scale.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://codeberg.org/icewind/mill-scale.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1783856661,
|
||||||
|
"narHash": "sha256-ZGP04e+Q6WyQJGA9ZvI5CL6+heGQldbAG9U1T9NGvmU=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "569d578509928497eddc3fdbf94a799027050be4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-26.05",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flakelight": "flakelight",
|
||||||
|
"mill-scale": "mill-scale",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"mill-scale",
|
||||||
|
"flakelight",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780197589,
|
||||||
|
"narHash": "sha256-FVCr2Ij/jKf59a4LW481eeOF6rJRreOBrVgW/aUBTrw=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "21632e942d89bf1cce4e5a63d7e58a215a0cbfcc",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
14
flake.nix
Normal file
14
flake.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-26.05";
|
||||||
|
flakelight = {
|
||||||
|
url = "github:nix-community/flakelight";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
mill-scale = {
|
||||||
|
url = "git+https://codeberg.org/icewind/mill-scale.git";
|
||||||
|
inputs.flakelight.follows = "flakelight";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
outputs = {mill-scale, ...}: mill-scale ./. {};
|
||||||
|
}
|
||||||
102
src/lib.rs
102
src/lib.rs
|
|
@ -1,3 +1,4 @@
|
||||||
|
use comma_separated::CommaSeparatedIterator;
|
||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
use rfc7239::{parse, Forwarded, NodeIdentifier, NodeName};
|
use rfc7239::{parse, Forwarded, NodeIdentifier, NodeName};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
@ -117,106 +118,12 @@ pub fn get_forwarded_for() -> impl Filter<Extract = (Vec<IpAddr>,), Error = Infa
|
||||||
.unify()
|
.unify()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum CommaSeparatedIteratorState {
|
|
||||||
/// Start of string or after a ',' (including whitespace)
|
|
||||||
Default,
|
|
||||||
/// Inside a double quote
|
|
||||||
Quoted,
|
|
||||||
/// After escape character inside quote
|
|
||||||
QuotedPair,
|
|
||||||
/// Non quoted part
|
|
||||||
Token,
|
|
||||||
/// After closing double quote
|
|
||||||
PostAmbleForQuoted,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CommaSeparatedIterator<'a> {
|
|
||||||
/// target
|
|
||||||
target: &'a str,
|
|
||||||
/// iterator
|
|
||||||
char_indices: std::str::CharIndices<'a>,
|
|
||||||
/// current scanner state
|
|
||||||
state: CommaSeparatedIteratorState,
|
|
||||||
/// start position of the last token found
|
|
||||||
s: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> CommaSeparatedIterator<'a> {
|
|
||||||
pub fn new(target: &'a str) -> Self {
|
|
||||||
Self {
|
|
||||||
target,
|
|
||||||
char_indices: target.char_indices(),
|
|
||||||
state: CommaSeparatedIteratorState::Default,
|
|
||||||
s: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for CommaSeparatedIterator<'a> {
|
|
||||||
type Item = &'a str;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
for (i, c) in &mut self.char_indices {
|
|
||||||
let (next, next_state) = match (self.state, c) {
|
|
||||||
(CommaSeparatedIteratorState::Default, '"') => {
|
|
||||||
self.s = i;
|
|
||||||
(None, CommaSeparatedIteratorState::Quoted)
|
|
||||||
}
|
|
||||||
(CommaSeparatedIteratorState::Default, ' ' | '\t') => {
|
|
||||||
(None, CommaSeparatedIteratorState::Default)
|
|
||||||
}
|
|
||||||
(CommaSeparatedIteratorState::Default, ',') => (
|
|
||||||
Some(Some(&self.target[i..i])),
|
|
||||||
CommaSeparatedIteratorState::Default,
|
|
||||||
),
|
|
||||||
(CommaSeparatedIteratorState::Default, _) => {
|
|
||||||
self.s = i;
|
|
||||||
(None, CommaSeparatedIteratorState::Token)
|
|
||||||
}
|
|
||||||
(CommaSeparatedIteratorState::Quoted, '"') => (
|
|
||||||
Some(Some(&self.target[self.s..i + 1])),
|
|
||||||
CommaSeparatedIteratorState::PostAmbleForQuoted,
|
|
||||||
),
|
|
||||||
(CommaSeparatedIteratorState::Quoted, '\\') => {
|
|
||||||
(None, CommaSeparatedIteratorState::QuotedPair)
|
|
||||||
}
|
|
||||||
(CommaSeparatedIteratorState::QuotedPair, _) => {
|
|
||||||
(None, CommaSeparatedIteratorState::Quoted)
|
|
||||||
}
|
|
||||||
(CommaSeparatedIteratorState::Token, ',') => (
|
|
||||||
Some(Some(&self.target[self.s..i])),
|
|
||||||
CommaSeparatedIteratorState::Default,
|
|
||||||
),
|
|
||||||
(CommaSeparatedIteratorState::PostAmbleForQuoted, ',') => {
|
|
||||||
(None, CommaSeparatedIteratorState::Default)
|
|
||||||
}
|
|
||||||
(current_state, _) => (None, current_state),
|
|
||||||
};
|
|
||||||
self.state = next_state;
|
|
||||||
if let Some(next) = next {
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match self.state {
|
|
||||||
CommaSeparatedIteratorState::Default
|
|
||||||
| CommaSeparatedIteratorState::PostAmbleForQuoted => None,
|
|
||||||
CommaSeparatedIteratorState::Quoted
|
|
||||||
| CommaSeparatedIteratorState::QuotedPair
|
|
||||||
| CommaSeparatedIteratorState::Token => {
|
|
||||||
self.state = CommaSeparatedIteratorState::Default;
|
|
||||||
Some(&self.target[self.s..])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EscapeState {
|
enum EscapeState {
|
||||||
Normal,
|
Normal,
|
||||||
Escaped,
|
Escaped,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_quoted(x: &str) -> Cow<str> {
|
fn maybe_quoted(x: &str) -> Cow<'_, str> {
|
||||||
let mut i = x.chars();
|
let mut i = x.chars();
|
||||||
if i.next() == Some('"') {
|
if i.next() == Some('"') {
|
||||||
let mut s = String::with_capacity(x.len());
|
let mut s = String::with_capacity(x.len());
|
||||||
|
|
@ -279,7 +186,9 @@ mod tests {
|
||||||
fn test_comma_separated_iterator() {
|
fn test_comma_separated_iterator() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec!["abc", "def", "ghi", "jkl", "mno", "pqr"],
|
vec!["abc", "def", "ghi", "jkl", "mno", "pqr"],
|
||||||
CommaSeparatedIterator::new("abc,def, ghi,\tjkl , mno,\tpqr").collect::<Vec<&str>>()
|
CommaSeparatedIterator::new("abc,def, ghi,\tjkl , mno,\tpqr")
|
||||||
|
.map(str::trim)
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -294,6 +203,7 @@ mod tests {
|
||||||
CommaSeparatedIterator::new(
|
CommaSeparatedIterator::new(
|
||||||
"abc,\"def\", \"ghi\",\t\"jkl\" , \"mno\",\tpqr, \"abc, def\""
|
"abc,\"def\", \"ghi\",\t\"jkl\" , \"mno\",\tpqr, \"abc, def\""
|
||||||
)
|
)
|
||||||
|
.map(str::trim)
|
||||||
.collect::<Vec<&str>>()
|
.collect::<Vec<&str>>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue