Skip to content

Commit 0e81f26

Browse files
committed
add hex contentview
1 parent bc1cdf7 commit 0e81f26

4 files changed

Lines changed: 127 additions & 0 deletions

File tree

mitmproxy-rs/src/contentview.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use pyo3::prelude::*;
2+
use anyhow::{Result};
3+
use mitmproxy::contentviews::Contentview;
4+
5+
#[pyclass]
6+
pub struct PyContentview(&'static dyn Contentview);
7+
8+
impl PyContentview {
9+
pub fn new<'py>(py: Python<'py>, contentview: &'static dyn Contentview) -> PyResult<Bound<'py, Self>> {
10+
PyContentview(contentview).into_pyobject(py)
11+
}
12+
}
13+
14+
#[pymethods]
15+
impl PyContentview {
16+
17+
#[getter]
18+
pub fn name(&self) -> &str {
19+
self.0.name()
20+
}
21+
22+
pub fn deserialize<'py>(
23+
&self,
24+
data: Vec<u8>
25+
) -> Result<String> {
26+
self.0.deserialize(data)
27+
}
28+
29+
fn __repr__(&self) -> PyResult<String> {
30+
Ok(format!("<{} Contentview>", self.0.name()))
31+
}
32+
}

mitmproxy-rs/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod stream;
1212
pub mod task;
1313
mod udp_client;
1414
mod util;
15+
mod contentview;
1516

1617
static LOGGER_INITIALIZED: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(false));
1718

@@ -81,6 +82,21 @@ mod mitmproxy_rs {
8182
use crate::util::{genkey, pubkey};
8283
}
8384

85+
#[pymodule]
86+
mod contentviews {
87+
use crate::contentview::PyContentview;
88+
use super::*;
89+
use mitmproxy::contentviews::*;
90+
91+
#[pymodule_init]
92+
fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {
93+
m.add(
94+
"hex",
95+
PyContentview::new(m.py(), &HexStream())?
96+
)
97+
}
98+
}
99+
84100
#[pymodule_export]
85101
use crate::stream::Stream;
86102

src/contentviews/mod.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use std::num::ParseIntError;
2+
use anyhow::{Result};
3+
use pretty_hex::{HexConfig, PrettyHex};
4+
5+
#[derive(Debug)]
6+
pub enum SerializeError {
7+
InvalidFormat(String),
8+
}
9+
10+
pub trait Contentview: Send + Sync {
11+
fn name(&self) -> &str;
12+
fn deserialize(&self, data: Vec<u8>) -> Result<String>;
13+
}
14+
15+
pub trait SerializableContentview: Contentview {
16+
fn serialize(&self, data: String) -> Result<Vec<u8>, SerializeError>;
17+
}
18+
19+
#[derive(Default)]
20+
pub struct HexStream();
21+
22+
impl Contentview for HexStream {
23+
fn name(&self) -> &str {
24+
"HexStream"
25+
}
26+
27+
fn deserialize(&self, data: Vec<u8>) -> Result<String> {
28+
Ok(data.hex_conf(HexConfig {
29+
title: false,
30+
ascii: false,
31+
width: 0,
32+
group: 0,
33+
chunk: 0,
34+
max_bytes: usize::MAX,
35+
display_offset: 0,
36+
}).to_string())
37+
}
38+
}
39+
40+
impl SerializableContentview for HexStream {
41+
fn serialize(&self, data: String) -> Result<Vec<u8>, SerializeError> {
42+
(0..data.len())
43+
.step_by(2)
44+
.map(|i| u8::from_str_radix(&data[i..i + 2], 16))
45+
.collect::<Result<Vec<u8>, ParseIntError>>()
46+
.map_err(
47+
|e| SerializeError::InvalidFormat(format!("Failed to parse hex string: {}", e)))
48+
}
49+
}
50+
51+
#[cfg(test)]
52+
mod tests {
53+
use super::*;
54+
55+
#[test]
56+
fn test_hexstream_deserialize() {
57+
let hex_stream = HexStream::default();
58+
let data = b"foo".to_vec();
59+
let result = hex_stream.deserialize(data).unwrap();
60+
assert_eq!(result, "666f6f");
61+
}
62+
63+
#[test]
64+
fn test_hexstream_deserialize_empty() {
65+
let hex_stream = HexStream::default();
66+
let data = vec![];
67+
let result = hex_stream.deserialize(data).unwrap();
68+
assert_eq!(result, "");
69+
}
70+
71+
#[test]
72+
fn test_hexstream_serialize() {
73+
let hex_stream = HexStream::default();
74+
let data = "666f6f".to_string();
75+
let result = hex_stream.serialize(data).unwrap();
76+
assert_eq!(result, b"foo");
77+
}
78+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub use network::MAX_PACKET_SIZE;
22

33
pub mod certificates;
4+
pub mod contentviews;
45
pub mod dns;
56
pub mod intercept_conf;
67
pub mod ipc;

0 commit comments

Comments
 (0)