Skip to content

Commit

Permalink
Use absolute paths in app.js
Browse files Browse the repository at this point in the history
  • Loading branch information
davet2001 committed Dec 19, 2023
1 parent 8918984 commit b0012e0
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 30 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
([#6559](https://github.com/mitmproxy/mitmproxy/pull/6559), @mhils)
* `ignore_hosts` now waits for the entire HTTP headers if it suspects the connection to be HTTP.
([#6559](https://github.com/mitmproxy/mitmproxy/pull/6559), @mhils)

* Fix root-relative URLs for flow and other APIs so that mitmweb can run in subdirectories.
([#6562](https://github.com/mitmproxy/mitmproxy/pull/6562), @davet2001)

## 14 December 2023: mitmproxy 10.1.6

Expand Down
12 changes: 12 additions & 0 deletions test/mitmproxy/tools/web/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,18 @@ def test_index(self):
assert '"/' not in str(
response.body
), "HTML content should not contain root-relative paths"

def test_app_js(self):
response: httpclient.HTTPResponse = self.fetch("/static/app.js")
assert response.code == 200
result = (
'"/flows' not in str( response.body )
and '"/commands' not in str( response.body )
and '"/filter' not in str( response.body )
and '"/clear' not in str( response.body )
and '"/options' not in str( response.body )
)
assert result, "app.js content should not contain root-relative paths"

def test_filter_help(self):
assert self.fetch("/filter-help").code == 200
Expand Down
18 changes: 9 additions & 9 deletions web/src/js/__tests__/ducks/ui/keyboardSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe("onKeyDown", () => {

it("should handle delete action", () => {
store.dispatch(createKeyEvent("d"));
expect(fetchApi).toBeCalledWith("/flows/1", { method: "DELETE" });
expect(fetchApi).toBeCalledWith("flows/1", { method: "DELETE" });
});

it("should handle create action", () => {
Expand All @@ -138,48 +138,48 @@ describe("onKeyDown", () => {

it("should handle duplicate action", () => {
store.dispatch(createKeyEvent("D"));
expect(fetchApi).toBeCalledWith("/flows/1/duplicate", {
expect(fetchApi).toBeCalledWith("flows/1/duplicate", {
method: "POST",
});
});

it("should handle resume action", () => {
// resume all
store.dispatch(createKeyEvent("A"));
expect(fetchApi).toBeCalledWith("/flows/resume", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/resume", { method: "POST" });
// resume
store.getState().flows.byId[
store.getState().flows.selected[0]
].intercepted = true;
store.dispatch(createKeyEvent("a"));
expect(fetchApi).toBeCalledWith("/flows/1/resume", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/1/resume", { method: "POST" });
});

it("should handle replay action", () => {
store.dispatch(createKeyEvent("r"));
expect(fetchApi).toBeCalledWith("/flows/1/replay", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/1/replay", { method: "POST" });
});

it("should handle revert action", () => {
store.getState().flows.byId[
store.getState().flows.selected[0]
].modified = true;
store.dispatch(createKeyEvent("v"));
expect(fetchApi).toBeCalledWith("/flows/1/revert", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/1/revert", { method: "POST" });
});

it("should handle kill action", () => {
// kill all
store.dispatch(createKeyEvent("X"));
expect(fetchApi).toBeCalledWith("/flows/kill", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/kill", { method: "POST" });
// kill
store.dispatch(createKeyEvent("x"));
expect(fetchApi).toBeCalledWith("/flows/1/kill", { method: "POST" });
expect(fetchApi).toBeCalledWith("flows/1/kill", { method: "POST" });
});

it("should handle clear action", () => {
store.dispatch(createKeyEvent("z"));
expect(fetchApi).toBeCalledWith("/clear", { method: "POST" });
expect(fetchApi).toBeCalledWith("clear", { method: "POST" });
});

it("should stop on some action with no flow is selected", () => {
Expand Down
2 changes: 1 addition & 1 deletion web/src/js/components/CommandBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export default function CommandBar() {
const [currentPos, setCurrentPos] = useState<number | undefined>(undefined);

useEffect(() => {
fetchApi("/commands", { method: "GET" })
fetchApi("commands", { method: "GET" })
.then((response) => response.json())
.then((data: AllCommands) => {
setAllCommands(data);
Expand Down
4 changes: 2 additions & 2 deletions web/src/js/components/Header/FileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ export default React.memo(function FileMenu() {
}}
/>
</li>
<MenuItem onClick={() => location.replace("/flows/dump")}>
<MenuItem onClick={() => location.replace("flows/dump")}>
<i className="fa fa-fw fa-floppy-o" />
&nbsp;Save
</MenuItem>
<MenuItem
onClick={() => location.replace("/flows/dump?filter=" + filter)}
onClick={() => location.replace("flows/dump?filter=" + filter)}
>
<i className="fa fa-fw fa-floppy-o" />
&nbsp;Save filtered
Expand Down
2 changes: 1 addition & 1 deletion web/src/js/components/Header/FilterDocs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class FilterDocs extends Component<

componentDidMount() {
if (!FilterDocs.xhr) {
FilterDocs.xhr = fetchApi("/filter-help").then((response) =>
FilterDocs.xhr = fetchApi("filter-help").then((response) =>
response.json()
);
FilterDocs.xhr.catch(() => {
Expand Down
24 changes: 12 additions & 12 deletions web/src/js/ducks/flows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,63 +177,63 @@ export function selectRelative(flows, shift) {

export function resume(flow: Flow) {
return (dispatch) =>
fetchApi(`/flows/${flow.id}/resume`, { method: "POST" });
fetchApi(`flows/${flow.id}/resume`, { method: "POST" });
}

export function resumeAll() {
return (dispatch) => fetchApi("/flows/resume", { method: "POST" });
return (dispatch) => fetchApi("flows/resume", { method: "POST" });
}

export function kill(flow: Flow) {
return (dispatch) => fetchApi(`/flows/${flow.id}/kill`, { method: "POST" });
return (dispatch) => fetchApi(`flows/${flow.id}/kill`, { method: "POST" });
}

export function killAll() {
return (dispatch) => fetchApi("/flows/kill", { method: "POST" });
return (dispatch) => fetchApi("flows/kill", { method: "POST" });
}

export function remove(flow: Flow) {
return (dispatch) => fetchApi(`/flows/${flow.id}`, { method: "DELETE" });
return (dispatch) => fetchApi(`flows/${flow.id}`, { method: "DELETE" });
}

export function duplicate(flow: Flow) {
return (dispatch) =>
fetchApi(`/flows/${flow.id}/duplicate`, { method: "POST" });
fetchApi(`flows/${flow.id}/duplicate`, { method: "POST" });
}

export function replay(flow: Flow) {
return (dispatch) =>
fetchApi(`/flows/${flow.id}/replay`, { method: "POST" });
fetchApi(`flows/${flow.id}/replay`, { method: "POST" });
}

export function revert(flow: Flow) {
return (dispatch) =>
fetchApi(`/flows/${flow.id}/revert`, { method: "POST" });
fetchApi(`flows/${flow.id}/revert`, { method: "POST" });
}

export function update(flow: Flow, data) {
return (dispatch) => fetchApi.put(`/flows/${flow.id}`, data);
return (dispatch) => fetchApi.put(`flows/${flow.id}`, data);
}

export function uploadContent(flow: Flow, file, type) {
const body = new FormData();
file = new window.Blob([file], { type: "plain/text" });
body.append("file", file);
return (dispatch) =>
fetchApi(`/flows/${flow.id}/${type}/content.data`, {
fetchApi(`flows/${flow.id}/${type}/content.data`, {
method: "POST",
body,
});
}

export function clear() {
return (dispatch) => fetchApi("/clear", { method: "POST" });
return (dispatch) => fetchApi("clear", { method: "POST" });
}

export function upload(file) {
const body = new FormData();
body.append("file", file);
return (dispatch) => fetchApi("/flows/dump", { method: "POST", body });
return (dispatch) => fetchApi("flows/dump", { method: "POST", body });
}

export function select(id?: string) {
Expand Down
4 changes: 2 additions & 2 deletions web/src/js/ducks/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function reducer(state = defaultState, action): OptionsState {

export async function pureSendUpdate(option: Option, value, dispatch) {
try {
const response = await fetchApi.put("/options", { [option]: value });
const response = await fetchApi.put("options", { [option]: value });
if (response.status === 200) {
dispatch(optionsEditorActions.updateSuccess(option));
} else {
Expand All @@ -55,7 +55,7 @@ export function update(name: Option, value: any): AppThunk {
}

export function save() {
return (dispatch) => fetchApi("/options/save", { method: "POST" });
return (dispatch) => fetchApi("options/save", { method: "POST" });
}

export function addInterceptFilter(example) {
Expand Down
4 changes: 2 additions & 2 deletions web/src/js/urlState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ export function updateUrlFromStore(store) {

let url;
if (state.flows.selected.length > 0) {
url = `/flows/${state.flows.selected[0]}/${state.ui.flow.tab}`;
url = `flows/${state.flows.selected[0]}/${state.ui.flow.tab}`;
} else {
url = "/flows";
url = "flows";
}

if (queryStr) {
Expand Down

0 comments on commit b0012e0

Please sign in to comment.