Skip to content

Commit 7c539a1

Browse files
committed
add hex contentview
1 parent bc1cdf7 commit 7c539a1

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

mitmproxy-rs/src/contentview.rs

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

mitmproxy-rs/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::sync::RwLock;
55
use once_cell::sync::Lazy;
66
use pyo3::{exceptions::PyException, prelude::*};
77

8+
mod contentview;
89
mod dns_resolver;
910
mod process_info;
1011
mod server;
@@ -81,6 +82,18 @@ mod mitmproxy_rs {
8182
use crate::util::{genkey, pubkey};
8283
}
8384

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

src/contentviews/mod.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use anyhow::Result;
2+
use pretty_hex::{HexConfig, PrettyHex};
3+
use std::num::ParseIntError;
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
29+
.hex_conf(HexConfig {
30+
title: false,
31+
ascii: false,
32+
width: 0,
33+
group: 0,
34+
chunk: 0,
35+
max_bytes: usize::MAX,
36+
display_offset: 0,
37+
})
38+
.to_string())
39+
}
40+
}
41+
42+
impl SerializableContentview for HexStream {
43+
fn serialize(&self, data: String) -> Result<Vec<u8>, SerializeError> {
44+
(0..data.len())
45+
.step_by(2)
46+
.map(|i| u8::from_str_radix(&data[i..i + 2], 16))
47+
.collect::<Result<Vec<u8>, ParseIntError>>()
48+
.map_err(|e| {
49+
SerializeError::InvalidFormat(format!("Failed to parse hex string: {}", e))
50+
})
51+
}
52+
}
53+
54+
#[cfg(test)]
55+
mod tests {
56+
use super::*;
57+
58+
#[test]
59+
fn test_hexstream_deserialize() {
60+
let hex_stream = HexStream::default();
61+
let data = b"foo".to_vec();
62+
let result = hex_stream.deserialize(data).unwrap();
63+
assert_eq!(result, "666f6f");
64+
}
65+
66+
#[test]
67+
fn test_hexstream_deserialize_empty() {
68+
let hex_stream = HexStream::default();
69+
let data = vec![];
70+
let result = hex_stream.deserialize(data).unwrap();
71+
assert_eq!(result, "");
72+
}
73+
74+
#[test]
75+
fn test_hexstream_serialize() {
76+
let hex_stream = HexStream::default();
77+
let data = "666f6f".to_string();
78+
let result = hex_stream.serialize(data).unwrap();
79+
assert_eq!(result, b"foo");
80+
}
81+
}

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)