Repository navigation
Proxy storage: flows table, bodies in blobs.sqlite, settings #751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,11 @@ | ||
| import { createModelStore } from "@yaakapp-internal/model-store"; | ||
| import type { HttpExchange } from "@yaakapp-internal/proxy-lib"; | ||
| import type { Flow } from "@yaakapp-internal/proxy-lib"; | ||
|
|
||
| type ProxyModels = { | ||
| http_exchange: HttpExchange; | ||
| flow: Flow; | ||
| }; | ||
|
|
||
| export const { dataAtom, applyChange, replaceAll, listAtom, orderedListAtom } = | ||
| createModelStore<ProxyModels>(["http_exchange"]); | ||
| createModelStore<ProxyModels>(["flow"]); | ||
|
|
||
| export const httpExchangesAtom = orderedListAtom("http_exchange", "createdAt", "desc"); | ||
| export const flowsAtom = orderedListAtom("flow", "startedAt", "desc"); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| DROP TABLE http_exchanges; | ||
|
|
||
| CREATE TABLE flows | ||
| ( | ||
| id TEXT NOT NULL PRIMARY KEY, | ||
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, | ||
| updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, | ||
| started_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, | ||
| method TEXT NOT NULL DEFAULT '', | ||
| url TEXT NOT NULL DEFAULT '', | ||
| client_http_version TEXT NOT NULL DEFAULT '', | ||
| upstream_http_version TEXT, | ||
| remote_addr TEXT, | ||
| status INTEGER, | ||
| content_type TEXT, | ||
| request_headers TEXT NOT NULL DEFAULT '[]', | ||
| response_headers TEXT NOT NULL DEFAULT '[]', | ||
| request_size INTEGER NOT NULL DEFAULT 0, | ||
| response_size INTEGER NOT NULL DEFAULT 0, | ||
| request_truncated BOOLEAN NOT NULL DEFAULT FALSE, | ||
| response_truncated BOOLEAN NOT NULL DEFAULT FALSE, | ||
| elapsed_headers_ms INTEGER, | ||
| elapsed_ms INTEGER, | ||
| error TEXT | ||
| ); | ||
|
|
||
| CREATE INDEX idx_flows_started_at ON flows (started_at); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| use crate::models::{Flow, FlowBody, find_header}; | ||
| use std::io::Cursor; | ||
| use tokio::io::AsyncReadExt; | ||
| use yaak_http::decompress::{ContentEncoding, streaming_decoder}; | ||
| use yaak_models::blob_manager::BlobManager; | ||
|
|
||
| /// A flow's body as stored: the bytes on the wire, up to the capture limit. | ||
| pub fn read_raw_body( | ||
| blobs: &BlobManager, | ||
| flow_id: &str, | ||
| body: FlowBody, | ||
| ) -> Result<Vec<u8>, String> { | ||
| let chunks = | ||
| blobs.connect().get_chunks(&Flow::body_id(flow_id, body)).map_err(|e| e.to_string())?; | ||
| Ok(chunks.into_iter().flat_map(|c| c.data).collect()) | ||
| } | ||
|
|
||
| /// A flow's body decoded with its Content-Encoding. A truncated body decodes as far as its | ||
| /// stored bytes go. | ||
| pub async fn read_body( | ||
| blobs: &BlobManager, | ||
| flow: &Flow, | ||
| body: FlowBody, | ||
| ) -> Result<Vec<u8>, String> { | ||
| let raw = read_raw_body(blobs, &flow.id, body)?; | ||
| let encoding = ContentEncoding::from_header(find_header(flow.headers(body), "content-encoding")); | ||
| if encoding == ContentEncoding::Identity { | ||
| return Ok(raw); | ||
| } | ||
|
|
||
| let mut decoded = Vec::new(); | ||
| match streaming_decoder(Cursor::new(raw), encoding).read_to_end(&mut decoded).await { | ||
|
Comment on lines
+31
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| Ok(_) => Ok(decoded), | ||
| Err(_) if flow.truncated(body) => Ok(decoded), | ||
| Err(e) => Err(format!("Failed to decode {encoding:?} body: {e}")), | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opening an existing
proxy.dbrunsDROP TABLE http_exchangesbefore any history is copied. This permanently deletes every saved exchange, including both inline bodies. Copy the old rows intoflowsand move their bodies intoblobs.sqlitebefore dropping the table.Knowledge Base Used: