mirror of
https://github.com/dstotijn/hetty.git
synced 2025-07-01 18:47:29 -04:00
Add intercept response filter
This commit is contained in:
@ -5,8 +5,10 @@ query ActiveProject {
|
||||
isActive
|
||||
settings {
|
||||
intercept {
|
||||
enabled
|
||||
requestsEnabled
|
||||
responsesEnabled
|
||||
requestFilter
|
||||
responseFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ function Actions(): JSX.Element {
|
||||
|
||||
{clearLogsResult.error && <Alert severity="error">Failed to clear HTTP logs: {clearLogsResult.error}</Alert>}
|
||||
|
||||
{activeProject?.settings.intercept.enabled && (
|
||||
{(activeProject?.settings.intercept.requestsEnabled || activeProject?.settings.intercept.responsesEnabled) && (
|
||||
<Link href="/proxy/intercept/?id=" passHref>
|
||||
<Button
|
||||
variant="contained"
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
Switch,
|
||||
Tab,
|
||||
TextField,
|
||||
TextFieldProps,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { SwitchBaseProps } from "@mui/material/internal/SwitchBase";
|
||||
@ -25,6 +26,26 @@ enum TabValue {
|
||||
Intercept = "intercept",
|
||||
}
|
||||
|
||||
function FilterTextField(props: TextFieldProps): JSX.Element {
|
||||
return (
|
||||
<TextField
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
sx: { fontFamily: "'JetBrains Mono', monospace" },
|
||||
autoCorrect: "false",
|
||||
spellCheck: "false",
|
||||
}}
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
margin="normal"
|
||||
sx={{ mr: 1 }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Settings(): JSX.Element {
|
||||
const client = useApolloClient();
|
||||
const activeProject = useActiveProject();
|
||||
@ -41,16 +62,22 @@ export default function Settings(): JSX.Element {
|
||||
}));
|
||||
|
||||
setInterceptReqFilter(data.updateInterceptSettings.requestFilter || "");
|
||||
setInterceptResFilter(data.updateInterceptSettings.responseFilter || "");
|
||||
},
|
||||
});
|
||||
|
||||
const [interceptReqFilter, setInterceptReqFilter] = useState("");
|
||||
const [interceptResFilter, setInterceptResFilter] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setInterceptReqFilter(activeProject?.settings.intercept.requestFilter || "");
|
||||
}, [activeProject?.settings.intercept.requestFilter]);
|
||||
|
||||
const handleInterceptEnabled: SwitchBaseProps["onChange"] = (e, checked) => {
|
||||
useEffect(() => {
|
||||
setInterceptResFilter(activeProject?.settings.intercept.responseFilter || "");
|
||||
}, [activeProject?.settings.intercept.responseFilter]);
|
||||
|
||||
const handleReqInterceptEnabled: SwitchBaseProps["onChange"] = (e, checked) => {
|
||||
if (!activeProject) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
@ -60,7 +87,23 @@ export default function Settings(): JSX.Element {
|
||||
variables: {
|
||||
input: {
|
||||
...withoutTypename(activeProject.settings.intercept),
|
||||
enabled: checked,
|
||||
requestsEnabled: checked,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleResInterceptEnabled: SwitchBaseProps["onChange"] = (e, checked) => {
|
||||
if (!activeProject) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
updateInterceptSettings({
|
||||
variables: {
|
||||
input: {
|
||||
...withoutTypename(activeProject.settings.intercept),
|
||||
responsesEnabled: checked,
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -81,6 +124,21 @@ export default function Settings(): JSX.Element {
|
||||
});
|
||||
};
|
||||
|
||||
const handleInterceptResFilter = () => {
|
||||
if (!activeProject) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateInterceptSettings({
|
||||
variables: {
|
||||
input: {
|
||||
...withoutTypename(activeProject.settings.intercept),
|
||||
responseFilter: interceptResFilter,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const [tabValue, setTabValue] = useState(TabValue.Intercept);
|
||||
|
||||
const tabSx = {
|
||||
@ -111,16 +169,19 @@ export default function Settings(): JSX.Element {
|
||||
</TabList>
|
||||
|
||||
<TabPanel value={TabValue.Intercept} sx={{ px: 0 }}>
|
||||
<FormControl>
|
||||
<Typography variant="h6" sx={{ mt: 3, mb: 1 }}>
|
||||
Requests
|
||||
</Typography>
|
||||
<FormControl sx={{ mb: 2 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
disabled={updateIntercepSettingsResult.loading}
|
||||
onChange={handleInterceptEnabled}
|
||||
checked={activeProject.settings.intercept.enabled}
|
||||
onChange={handleReqInterceptEnabled}
|
||||
checked={activeProject.settings.intercept.requestsEnabled}
|
||||
/>
|
||||
}
|
||||
label="Enable proxy interception"
|
||||
label="Enable request interception"
|
||||
labelPlacement="start"
|
||||
sx={{ display: "inline-block", m: 0 }}
|
||||
/>
|
||||
@ -129,28 +190,13 @@ export default function Settings(): JSX.Element {
|
||||
<Link href="/proxy/intercept">manual review</Link>.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
<Typography variant="h6" sx={{ mt: 3 }}>
|
||||
Rules
|
||||
</Typography>
|
||||
<form>
|
||||
<FormControl sx={{ width: "50%" }}>
|
||||
<TextField
|
||||
<FilterTextField
|
||||
label="Request filter"
|
||||
placeholder={`method = "GET" OR url =~ "/foobar"`}
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
placeholder={`Example: method = "GET" OR url =~ "/foobar"`}
|
||||
value={interceptReqFilter}
|
||||
onChange={(e) => setInterceptReqFilter(e.target.value)}
|
||||
InputProps={{
|
||||
sx: { fontFamily: "'JetBrains Mono', monospace" },
|
||||
autoCorrect: "false",
|
||||
spellCheck: "false",
|
||||
}}
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
margin="normal"
|
||||
sx={{ mr: 1 }}
|
||||
/>
|
||||
<FormHelperText>
|
||||
Filter expression to match incoming requests on. When set, only matching requests are intercepted.
|
||||
@ -172,6 +218,55 @@ export default function Settings(): JSX.Element {
|
||||
Update
|
||||
</Button>
|
||||
</form>
|
||||
<Typography variant="h6" sx={{ mt: 3 }}>
|
||||
Responses
|
||||
</Typography>
|
||||
<FormControl sx={{ mb: 2 }}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
disabled={updateIntercepSettingsResult.loading}
|
||||
onChange={handleResInterceptEnabled}
|
||||
checked={activeProject.settings.intercept.responsesEnabled}
|
||||
/>
|
||||
}
|
||||
label="Enable response interception"
|
||||
labelPlacement="start"
|
||||
sx={{ display: "inline-block", m: 0 }}
|
||||
/>
|
||||
<FormHelperText>
|
||||
When enabled, HTTP responses received by the proxy are stalled for{" "}
|
||||
<Link href="/proxy/intercept">manual review</Link>.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
<form>
|
||||
<FormControl sx={{ width: "50%" }}>
|
||||
<FilterTextField
|
||||
label="Response filter"
|
||||
placeholder={`Example: statusCode =~ "^2" OR body =~ "foobar"`}
|
||||
value={interceptResFilter}
|
||||
onChange={(e) => setInterceptResFilter(e.target.value)}
|
||||
/>
|
||||
<FormHelperText>
|
||||
Filter expression to match received responses on. When set, only matching responses are intercepted.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="text"
|
||||
color="primary"
|
||||
size="large"
|
||||
sx={{
|
||||
mt: 2,
|
||||
py: 1.8,
|
||||
}}
|
||||
onClick={handleInterceptResFilter}
|
||||
disabled={updateIntercepSettingsResult.loading}
|
||||
startIcon={updateIntercepSettingsResult.loading ? <CircularProgress size={22} /> : undefined}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</form>
|
||||
</TabPanel>
|
||||
</TabContext>
|
||||
</>
|
||||
|
@ -1,6 +1,8 @@
|
||||
mutation UpdateInterceptSettings($input: UpdateInterceptSettingsInput!) {
|
||||
updateInterceptSettings(input: $input) {
|
||||
enabled
|
||||
requestsEnabled
|
||||
responsesEnabled
|
||||
requestFilter
|
||||
responseFilter
|
||||
}
|
||||
}
|
||||
|
@ -135,8 +135,10 @@ export type HttpResponseLog = {
|
||||
|
||||
export type InterceptSettings = {
|
||||
__typename?: 'InterceptSettings';
|
||||
enabled: Scalars['Boolean'];
|
||||
requestFilter?: Maybe<Scalars['String']>;
|
||||
requestsEnabled: Scalars['Boolean'];
|
||||
responseFilter?: Maybe<Scalars['String']>;
|
||||
responsesEnabled: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type ModifyRequestInput = {
|
||||
@ -359,8 +361,10 @@ export type SenderRequestInput = {
|
||||
};
|
||||
|
||||
export type UpdateInterceptSettingsInput = {
|
||||
enabled: Scalars['Boolean'];
|
||||
requestFilter?: InputMaybe<Scalars['String']>;
|
||||
requestsEnabled: Scalars['Boolean'];
|
||||
responseFilter?: InputMaybe<Scalars['String']>;
|
||||
responsesEnabled: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type CancelRequestMutationVariables = Exact<{
|
||||
@ -401,7 +405,7 @@ export type ModifyResponseMutation = { __typename?: 'Mutation', modifyResponse:
|
||||
export type ActiveProjectQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ActiveProjectQuery = { __typename?: 'Query', activeProject?: { __typename?: 'Project', id: string, name: string, isActive: boolean, settings: { __typename?: 'ProjectSettings', intercept: { __typename?: 'InterceptSettings', enabled: boolean, requestFilter?: string | null } } } | null };
|
||||
export type ActiveProjectQuery = { __typename?: 'Query', activeProject?: { __typename?: 'Project', id: string, name: string, isActive: boolean, settings: { __typename?: 'ProjectSettings', intercept: { __typename?: 'InterceptSettings', requestsEnabled: boolean, responsesEnabled: boolean, requestFilter?: string | null, responseFilter?: string | null } } } | null };
|
||||
|
||||
export type CloseProjectMutationVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@ -513,7 +517,7 @@ export type UpdateInterceptSettingsMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateInterceptSettingsMutation = { __typename?: 'Mutation', updateInterceptSettings: { __typename?: 'InterceptSettings', enabled: boolean, requestFilter?: string | null } };
|
||||
export type UpdateInterceptSettingsMutation = { __typename?: 'Mutation', updateInterceptSettings: { __typename?: 'InterceptSettings', requestsEnabled: boolean, responsesEnabled: boolean, requestFilter?: string | null, responseFilter?: string | null } };
|
||||
|
||||
export type GetInterceptedRequestsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@ -715,8 +719,10 @@ export const ActiveProjectDocument = gql`
|
||||
isActive
|
||||
settings {
|
||||
intercept {
|
||||
enabled
|
||||
requestsEnabled
|
||||
responsesEnabled
|
||||
requestFilter
|
||||
responseFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1381,8 +1387,10 @@ export type GetSenderRequestsQueryResult = Apollo.QueryResult<GetSenderRequestsQ
|
||||
export const UpdateInterceptSettingsDocument = gql`
|
||||
mutation UpdateInterceptSettings($input: UpdateInterceptSettingsInput!) {
|
||||
updateInterceptSettings(input: $input) {
|
||||
enabled
|
||||
requestsEnabled
|
||||
responsesEnabled
|
||||
requestFilter
|
||||
responseFilter
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
Reference in New Issue
Block a user