From 4fc893ce74c9547b3b61b6a75e20b5409bac3400 Mon Sep 17 00:00:00 2001 From: Dave Christenson Date: Mon, 25 Sep 2023 11:35:57 -0500 Subject: [PATCH 1/2] v3-31-0: LogViewer UI view --- README.md | 8 +- bin/allproxy | 6 +- client/public/index.html | 47 ++++--- client/src/components/Footer.tsx | 11 +- client/src/components/Header.tsx | 162 +++++++++++++------------ client/src/components/HelpDialog.tsx | 13 +- client/src/components/SideBar.tsx | 54 +++++---- client/src/components/SnapshotTabs.tsx | 134 +++++++++++--------- client/src/store/LogViewerStore.ts | 17 +++ server/src/AllProxyApp.ts | 6 + server/src/Global.ts | 1 + 11 files changed, 269 insertions(+), 190 deletions(-) create mode 100644 client/src/store/LogViewerStore.ts diff --git a/README.md b/README.md index 89c2596d..32ca3d0f 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ MITM debugging proxy with a web GUI to view and modify all of the HTTP and HTTPS ### Install -> Mac: **[allproxy.dmg](https://github.com/allproxy/allproxy/releases/download/v3.30.0/allproxy-3.30.1-x64.dmg)** +> Mac: **[allproxy.dmg](https://github.com/allproxy/allproxy/releases/download/v3.31.0/allproxy-3.31.0-x64.dmg)** -> RedHat: **[allproxy.rpm](https://github.com/allproxy/allproxy/releases/download/v3.30.0/allproxy-3.30.1-1.x86_64.rpm)** +> RedHat: **[allproxy.rpm](https://github.com/allproxy/allproxy/releases/download/v3.31.0/allproxy-3.31.0-1.x86_64.rpm)** -> Ubuntu: **[allproxy.deb](https://github.com/allproxy/allproxy/releases/download/v3.30.0/allproxy_3.30.1_amd64.deb)** +> Ubuntu: **[allproxy.deb](https://github.com/allproxy/allproxy/releases/download/v3.31.0/allproxy_3.31.0_amd64.deb)** -> Windows: **[Setup.exe](https://github.com/allproxy/allproxy/releases/download/v3.30.0/allproxy-3.30.1.Setup.exe)** +> Windows: **[Setup.exe](https://github.com/allproxy/allproxy/releases/download/v3.31.0/allproxy-3.31.0.Setup.exe)** > Other install options: > 1. Install NPM package: **npm install -g allproxy** diff --git a/bin/allproxy b/bin/allproxy index 313535fd..695716f8 100755 --- a/bin/allproxy +++ b/bin/allproxy @@ -7,4 +7,8 @@ if [ ! -z "$SYMLINK" ]; then fi cd $BIN_DIR -npm start +if [ "$1" == "headless" ]; then + npm run headless +else + npm start +fi diff --git a/client/public/index.html b/client/public/index.html index 8b4ea2cc..53ba7316 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -1,20 +1,18 @@ - - - - - - - + - - - AllProxy - - - -
- - - + + + + \ No newline at end of file diff --git a/client/src/components/Footer.tsx b/client/src/components/Footer.tsx index 58e93320..c0b9ca18 100644 --- a/client/src/components/Footer.tsx +++ b/client/src/components/Footer.tsx @@ -3,6 +3,7 @@ import { observer } from 'mobx-react-lite'; import BreakpointStore from '../store/BreakpointStore'; import ExcludeTags from './ExcludeTags'; import { messageQueueStore } from '../store/MessageQueueStore'; +import { logViewerStore } from '../store/LogViewerStore'; /** * Footer view @@ -19,11 +20,13 @@ const Footer = observer(({ filterStore, breakpointStore }: Props): JSX.Element =
Messages: {messageQueueStore.getUnfilteredCount()} of {messageQueueStore.getTotalLength()}
-
-
-
Breakpoints: {breakpointStore.getBreakpointCount()}
+ {!logViewerStore.isLogViewer() && +
+
+
Breakpoints: {breakpointStore.getBreakpointCount()}
+
-
+ }
Exclude:
diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index 32c6a51b..09993a84 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -23,6 +23,7 @@ import JSONFieldsModal, { getJSONFields } from './JSONFieldsModal'; import { jsonLogStore, updateJSONRequestLabels } from '../store/JSONLogStore'; import FilterBar from './FilterBar'; import NotesModal from './NotesModal'; +import { logViewerStore } from '../store/LogViewerStore'; let filterWasStopped = false; @@ -72,7 +73,10 @@ const Header = observer(({ socketStore, messageQueueStore, snapshotStore, filter width="24" height="24" />
window.location.reload()}> - AllProxy + {logViewerStore.isLogViewer() + ? LogViewer + : AllProxy + }
@@ -139,45 +143,49 @@ const Header = observer(({ socketStore, messageQueueStore, snapshotStore, filter open={Boolean(moreMenuIcon)} onClose={() => setMoreMenuIcon(null)} > - 1 ? undefined : 0.3, - pointerEvents: snapshotStore.getSnapshotCount() > 1 ? undefined : 'none' - }}> -
{ - snapshotStore.deleteAllSnapshots(); - setMoreMenuIcon(null); - }} - > -  Delete Snapshots -
-
- -
{ - setOpenExportDialog(true); - setMoreMenuIcon(null); - }} - > -  Export Snapshot -
-
- -
{ - openSnapshotFileSelector(); - setMoreMenuIcon(null); - }} - > -  Import Snapshot -
-
+ {!logViewerStore.isLogViewer() && + <> + 1 ? undefined : 0.3, + pointerEvents: snapshotStore.getSnapshotCount() > 1 ? undefined : 'none' + }}> +
{ + snapshotStore.deleteAllSnapshots(); + setMoreMenuIcon(null); + }} + > +  Delete Snapshots +
+
+ +
{ + setOpenExportDialog(true); + setMoreMenuIcon(null); + }} + > +  Export Snapshot +
+
+ +
{ + openSnapshotFileSelector(); + setMoreMenuIcon(null); + }} + > +  Import Snapshot +
+
+ + }
{ @@ -246,41 +254,45 @@ const Header = observer(({ socketStore, messageQueueStore, snapshotStore, filter open={Boolean(settingsMenuIcon)} onClose={() => setSettingsMenuIcon(null)} > - -
{ - setSettingsMenuIcon(null); - settingsStore.toggleOpenSettingsModal(); - settingsStore.reset(); - if (!messageQueueStore.getStopped()) { - messageQueueStore.setStopped(true); - filterWasStopped = true; - } - }} - > -  Proxy Configuration -
-
- -
{ - setSettingsMenuIcon(null); - setShowBreakpointModal(true); - breakpointStore.init(); - }}> -  Breakpoints -
-
- -
{ - setSettingsMenuIcon(null); - setShowNoCaptureModal(true); - noCaptureStore.init(); - }}> -  No Capture List -
-
+ {!logViewerStore.isLogViewer() && + <> + +
{ + setSettingsMenuIcon(null); + settingsStore.toggleOpenSettingsModal(); + settingsStore.reset(); + if (!messageQueueStore.getStopped()) { + messageQueueStore.setStopped(true); + filterWasStopped = true; + } + }} + > +  Proxy Configuration +
+
+ +
{ + setSettingsMenuIcon(null); + setShowBreakpointModal(true); + breakpointStore.init(); + }}> +  Breakpoints +
+
+ +
{ + setSettingsMenuIcon(null); + setShowNoCaptureModal(true); + noCaptureStore.init(); + }}> +  No Capture List +
+
+ + } {window.darkMode &&
{ const [openImportJSONFileDialog, setOpenImportJSONFileDialog] = React.useState(false); const [showSessionModal, setShowSessionModal] = React.useState(false); - const [tabValue, setTabValue] = React.useState('1'); + const [tabValue, setTabValue] = React.useState(logViewerStore.isLogViewer() ? '4' : '1'); const [showJSONFieldsModal, setShowJSONFieldsModal] = React.useState(false); const [jsonFields, setJsonFields] = React.useState<{ name: string, count: number, selected: boolean }[]>([]); @@ -95,10 +96,10 @@ const HelpDialog = observer(({ open, onClose }: Props) => { indicatorColor="primary" aria-label="help-tabs" > - - - - + {!logViewerStore.isLogViewer() && } + {!logViewerStore.isLogViewer() && } + {!logViewerStore.isLogViewer() && } +

Quick Start

@@ -255,7 +256,7 @@ const HelpDialog = observer(({ open, onClose }: Props) => {
-

JSON Logs

+

Log Viewer

JSON logs can be imported and annotated for easier reading.

Annotating JSON Fields
diff --git a/client/src/components/SideBar.tsx b/client/src/components/SideBar.tsx index f4ef8ae4..a1449595 100644 --- a/client/src/components/SideBar.tsx +++ b/client/src/components/SideBar.tsx @@ -11,6 +11,7 @@ import MessageStore from "../store/MessageStore"; import { snapshotStore } from "../store/SnapshotStore"; import { useFilePicker } from "use-file-picker"; import ImportJSONFileDialog from "./ImportJSONFileDialog"; +import { logViewerStore } from "../store/LogViewerStore"; const SideBar = observer(() => { const [openSaveSessionDialog, setOpenSaveSessionDialog] = React.useState(false); @@ -188,7 +189,11 @@ const SideBar = observer(() => { @@ -238,28 +243,31 @@ const SideBar = observer(() => { onChange={() => messageQueueStore.toggleFullPageSearch()} /> Full Page Search
- - - + {!logViewerStore.isLogViewer() && + <> + + + + }
diff --git a/client/src/components/SnapshotTabs.tsx b/client/src/components/SnapshotTabs.tsx index 5d07af21..d7603e0b 100644 --- a/client/src/components/SnapshotTabs.tsx +++ b/client/src/components/SnapshotTabs.tsx @@ -6,6 +6,8 @@ import { TabContext, TabPanel } from '@material-ui/lab'; import SnapshotTabContent from './SnapshotTabContent'; import SnapshotStore, { ACTIVE_SNAPSHOT_NAME } from '../store/SnapshotStore'; import CreateSnapshotNameDialog from './CreateSnapshotDialog'; +import { logViewerStore } from '../store/LogViewerStore'; +import LayoutStore from '../store/LayoutStore'; type Props = { messageQueueStore: MessageQueueStore, @@ -32,75 +34,93 @@ const SnapshotTabs = observer(({ messageQueueStore, snapshotStore }: Props) => { snapshotStore.setSelectedSnapshotName(ACTIVE_SNAPSHOT_NAME); } snapshotStore.deleteSnapshot(value); + if (logViewerStore.isLogViewer()) { + const names = snapshotStore.getSnapshotNames(); + if (names.length > 1) { + snapshotStore.setSelectedSnapshotName(names[1]); + } + } } function title(value: string, i: number) { return (i === 0 - ? messageQueueStore.getStopped() ? 'Stopped' : 'Recording' + ? 'Proxy' : snapshotStore.getSnapshotName(value)) + ' (' + snapshotStore.getSnapshotSize(value) + ')'; } + const dim = new LayoutStore().requestContainer(true); return (
- - + {snapshotStore.getSnapshotNames().length === 1 && logViewerStore.isLogViewer() + ? +
+
+ Click the Import or Restore Session button +
+
+ : + + + {snapshotStore.getSnapshotNames().map((value, i) => ( + (i > 0 || !logViewerStore.isLogViewer()) && + +
+ {title(value, i)} +
+ {value === ACTIVE_SNAPSHOT_NAME + ?
handleTakeSnapshot(value)} + /> + :
handleDeleteTab(e, value)} + /> + } +
+ }> + + ))} + {snapshotStore.getSnapshotNames().map((value, i) => ( - 0 || !logViewerStore.isLogViewer()) && + -
- {title(value, i)} -
- {value === ACTIVE_SNAPSHOT_NAME - ?
handleTakeSnapshot(value)} - /> - :
handleDeleteTab(e, value)} - /> - } -
- }> - + value={value}> + snapshotStore.getSelectedReqSeqNumbers()[i] = num + } + scrollTop={snapshotStore.getScrollTop()[i]} + setScrollTop={ + (scrollTop) => snapshotStore.getScrollTop()[i] = scrollTop + } + highlightSeqNum={snapshotStore.getHightlightSeqNum()[i]} + setHighlightSeqNum={ + (seqNum) => snapshotStore.getHightlightSeqNum()[i] = seqNum + } + /> + ))} - - {snapshotStore.getSnapshotNames().map((value, i) => ( - - snapshotStore.getSelectedReqSeqNumbers()[i] = num - } - scrollTop={snapshotStore.getScrollTop()[i]} - setScrollTop={ - (scrollTop) => snapshotStore.getScrollTop()[i] = scrollTop - } - highlightSeqNum={snapshotStore.getHightlightSeqNum()[i]} - setHighlightSeqNum={ - (seqNum) => snapshotStore.getHightlightSeqNum()[i] = seqNum - } - /> - - ))} - + + } { diff --git a/client/src/store/LogViewerStore.ts b/client/src/store/LogViewerStore.ts new file mode 100644 index 00000000..de4c8b2e --- /dev/null +++ b/client/src/store/LogViewerStore.ts @@ -0,0 +1,17 @@ +import { makeAutoObservable } from "mobx"; + +export default class LogViewerStore { + private logViewer = false; + + + public constructor() { + this.logViewer = document.location.pathname.includes('logviewer'); + makeAutoObservable(this); + } + + public isLogViewer() { + return this.logViewer; + } +} + +export const logViewerStore = new LogViewerStore(); \ No newline at end of file diff --git a/server/src/AllProxyApp.ts b/server/src/AllProxyApp.ts index dae93ba4..de79aa19 100644 --- a/server/src/AllProxyApp.ts +++ b/server/src/AllProxyApp.ts @@ -25,6 +25,12 @@ const AllProxyApp = ( 'content-type': 'text/html' }); clientRes.end(fs.readFileSync(clientBuildDir + Paths.sep() + 'index.html')); + } else if (reqUrl.pathname === '/' + 'logviewer') { + clientRes.writeHead(200, { + 'content-type': 'text/html' + }); + clientRes.end(fs.readFileSync(clientBuildDir + Paths.sep() + 'index.html')); + Global.renderLogView = true; } else { const dir = clientBuildDir + reqUrl.pathname?.replace(/\//g, Paths.sep()); // File exists locally? diff --git a/server/src/Global.ts b/server/src/Global.ts index deb92e40..f83d9c71 100644 --- a/server/src/Global.ts +++ b/server/src/Global.ts @@ -9,6 +9,7 @@ export default class Global { static prevNow: number = 0; static dupCount: number = 0; static inDockerContainer: boolean = false; + static renderLogView: boolean = false; static nextSequenceNumber(): number { const now = Date.now(); From 8d77f5dea6e5a0871121ba8b7a846e84e2a9f5d0 Mon Sep 17 00:00:00 2001 From: Dave Christenson Date: Mon, 25 Sep 2023 11:36:11 -0500 Subject: [PATCH 2/2] 3.31.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74f481db..6c2d3a4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "allproxy", - "version": "3.30.1", + "version": "3.31.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "allproxy", - "version": "3.30.1", + "version": "3.31.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4aa6be0c..97adbcf3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "allproxy", - "version": "3.30.1", + "version": "3.31.0", "description": "AllProxy: MITM HTTP Debugging Tool.", "keywords": [ "proxy",