Skip to content

Commit 7520b11

Browse files
committed
Expand the model to support Views for e.g. exchange upstream/downstream
This also pulls in the passthrough response data, populating the upstream, and attempts to ensure everywhere necessary depends on HttpExchangeView instead of HttpExchange, if they only need to view an exchange's data (rather than mutating - i.e. breakpoints, event store updates, etc). This is still not complete - upstream/downstream aborts differences aren't modeled, websockets are ignored, etc etc, but we're making good progress.
1 parent 3f36e1a commit 7520b11

34 files changed

+522
-303
lines changed

src/components/send/response-pane.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { logError } from "../../errors";
77

88
import { UiStore } from '../../model/ui/ui-store';
99
import { AccountStore } from '../../model/account/account-store';
10-
import { CompletedExchange, SuccessfulExchange } from "../../model/http/exchange";
10+
import { CompletedExchange, SuccessfulExchange } from "../../model/http/http-exchange-views";
1111
import { RequestInput } from "../../model/send/send-request-model";
1212
import { tagsToErrorType } from "../../model/http/error-types";
1313

src/components/send/sent-response-status.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getReadableSize } from '../../util/buffer';
99

1010
import { getStatusColor } from '../../model/events/categorization';
1111
import { getStatusMessage } from '../../model/http/http-docs';
12-
import { CompletedExchange, SuccessfulExchange } from '../../model/http/exchange';
12+
import { CompletedExchange, SuccessfulExchange } from '../../model/http/http-exchange-views';
1313
import { ErrorType } from '../../model/http/error-types';
1414

1515
import { SendCardSection } from './send-card-section';

src/components/view/http/http-aborted-card.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { observer, inject } from 'mobx-react';
33

4-
import { HttpExchange } from '../../../types';
4+
import { HttpExchangeView } from '../../../types';
55
import { styled } from '../../../styles';
66

77
import { UiStore } from '../../../model/ui/ui-store';
@@ -21,7 +21,7 @@ const ErrorContent = styled(ContentMonoValue)`
2121

2222
export const HttpAbortedResponseCard = inject('uiStore')(observer((p: {
2323
cardProps: CollapsibleCardProps,
24-
exchange: HttpExchange,
24+
exchange: HttpExchangeView,
2525
uiStore?: UiStore
2626
}) =>
2727
<CollapsibleCard {...p.cardProps} direction='left'>

src/components/view/http/http-details-footer.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import * as React from 'react';
22
import { action } from 'mobx';
33
import { observer, inject } from 'mobx-react';
44

5-
import { CollectedEvent } from '../../../types';
5+
import { CollectedEvent, ViewableEvent, HttpExchangeView } from '../../../types';
66
import { styled, css } from '../../../styles';
77
import { Ctrl } from '../../../util/ui';
88

9-
import { HttpExchange } from '../../../model/http/exchange';
109
import { RulesStore } from '../../../model/rules/rules-store';
1110
import { AccountStore } from '../../../model/account/account-store';
1211

@@ -120,20 +119,26 @@ export const HttpDetailsFooter = inject('rulesStore')(
120119
(props: {
121120
rulesStore?: RulesStore,
122121

123-
event: CollectedEvent,
122+
event: ViewableEvent,
124123
onDelete: (event: CollectedEvent) => void,
125124
onScrollToEvent: (event: CollectedEvent) => void,
126-
onBuildRuleFromExchange: (event: HttpExchange) => void,
127-
onPrepareToResendRequest?: (event: HttpExchange) => void,
125+
onBuildRuleFromExchange: (event: HttpExchangeView) => void,
126+
onPrepareToResendRequest?: (event: HttpExchangeView) => void,
128127
isPaidUser: boolean,
129128
navigate: (url: string) => void
130129
}) => {
131130
const { event } = props;
132131
const { pinned } = event;
133132

133+
// Some actions require the collected event, not just the
134+
// current view.
135+
const collectedEvent = 'downstream' in event
136+
? event.downstream
137+
: event;
138+
134139
return <ButtonsContainer>
135140
<ScrollToButton
136-
onClick={() => props.onScrollToEvent(props.event)}
141+
onClick={() => props.onScrollToEvent(collectedEvent)}
137142
/>
138143
<PinButton
139144
pinned={pinned}
@@ -143,7 +148,7 @@ export const HttpDetailsFooter = inject('rulesStore')(
143148
/>
144149
<DeleteButton
145150
pinned={pinned}
146-
onClick={() => props.onDelete(event)}
151+
onClick={() => props.onDelete(collectedEvent)}
147152
/>
148153

149154
{
@@ -154,13 +159,15 @@ export const HttpDetailsFooter = inject('rulesStore')(
154159
<ModifyButton
155160
isExchange={event.isHttp() && !event.isWebSocket()}
156161
isPaidUser={props.isPaidUser}
157-
onClick={() => props.onBuildRuleFromExchange(props.event as HttpExchange)}
162+
onClick={() => props.onBuildRuleFromExchange(props.event as HttpExchangeView)}
158163
/>
159164
{ props.onPrepareToResendRequest &&
160165
<SendButton
161166
isExchange={event.isHttp() && !event.isWebSocket()}
162167
isPaidUser={props.isPaidUser}
163-
onClick={() => props.onPrepareToResendRequest!(props.event as HttpExchange)}
168+
onClick={() => props.onPrepareToResendRequest!(
169+
props.event as HttpExchangeView
170+
)}
164171
/>
165172
}
166173
</ButtonsContainer>;

src/components/view/http/http-details-pane.tsx

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { action, computed } from 'mobx';
44
import { observer, inject } from 'mobx-react';
55
import * as portals from 'react-reverse-portal';
66

7-
import { CollectedEvent, HtkResponse, HttpExchange } from '../../../types';
7+
import { CollectedEvent, HtkResponse, HttpExchange, HttpExchangeView } from '../../../types';
88
import { styled } from '../../../styles';
99
import { logError } from '../../../errors';
1010

@@ -21,6 +21,7 @@ import { tagsToErrorType } from '../../../model/http/error-types';
2121
import { PaneScrollContainer } from '../view-details-pane';
2222
import { StreamMessageListCard } from '../stream-message-list-card';
2323
import { WebSocketCloseCard } from '../websocket-close-card';
24+
import { SelfSizedEditor } from '../../editor/base-editor';
2425

2526
import { HttpBodyCard } from './http-body-card';
2627
import { HttpApiCard, HttpApiPlaceholderCard } from './http-api-card';
@@ -30,7 +31,6 @@ import { HttpAbortedResponseCard } from './http-aborted-card';
3031
import { HttpTrailersCard } from './http-trailers-card';
3132
import { HttpPerformanceCard } from './http-performance-card';
3233
import { HttpExportCard } from './http-export-card';
33-
import { SelfSizedEditor } from '../../editor/base-editor';
3434
import { HttpErrorHeader } from './http-error-header';
3535
import { HttpDetailsFooter } from './http-details-footer';
3636
import { HttpRequestBreakpointHeader, HttpResponseBreakpointHeader } from './http-breakpoint-header';
@@ -60,7 +60,7 @@ const makeFriendlyApiName = (rawName: string) => {
6060
@inject('rulesStore')
6161
@observer
6262
export class HttpDetailsPane extends React.Component<{
63-
exchange: HttpExchange,
63+
exchange: HttpExchangeView,
6464

6565
requestEditor: portals.HtmlPortalNode<typeof SelfSizedEditor>,
6666
responseEditor: portals.HtmlPortalNode<typeof SelfSizedEditor>,
@@ -69,8 +69,8 @@ export class HttpDetailsPane extends React.Component<{
6969
navigate: (path: string) => void,
7070
onDelete: (event: CollectedEvent) => void,
7171
onScrollToEvent: (event: CollectedEvent) => void,
72-
onBuildRuleFromExchange: (exchange: HttpExchange) => void,
73-
onPrepareToResendRequest?: (exchange: HttpExchange) => void,
72+
onBuildRuleFromExchange: (exchange: HttpExchangeView) => void,
73+
onPrepareToResendRequest?: (exchange: HttpExchangeView) => void,
7474

7575
// Injected:
7676
uiStore?: UiStore,
@@ -96,7 +96,6 @@ export class HttpDetailsPane extends React.Component<{
9696

9797
const { isPaidUser } = accountStore!;
9898
const { expandedViewCard } = uiStore!;
99-
const { requestBreakpoint, responseBreakpoint } = exchange;
10099

101100
// The full API details - for paid APIs, and non-paid users, we don't show
102101
// the detailed API data in any of the cards, we just show the name (below)
@@ -121,8 +120,8 @@ export class HttpDetailsPane extends React.Component<{
121120
</>;
122121
}
123122

124-
const cards = (requestBreakpoint || responseBreakpoint)
125-
? this.renderBreakpointCards(exchange, apiName, apiExchange)
123+
const cards = (exchange.downstream.isBreakpointed)
124+
? this.renderBreakpointCards(exchange.downstream, apiName, apiExchange)
126125
: this.renderNormalCards(exchange, apiName, apiExchange);
127126

128127
return <>
@@ -142,15 +141,15 @@ export class HttpDetailsPane extends React.Component<{
142141
</>;
143142
}
144143

145-
renderHeaderCard(exchange: HttpExchange): JSX.Element | null {
144+
renderHeaderCard(exchange: HttpExchangeView): JSX.Element | null {
146145
const { accountStore, navigate } = this.props;
147146
const { isPaidUser, getPro } = accountStore!;
148147
const {
149148
requestBreakpoint,
150149
respondToBreakpointedRequest,
151150
responseBreakpoint,
152151
tags
153-
} = exchange;
152+
} = exchange.downstream;
154153

155154
if (requestBreakpoint) {
156155
return <HttpRequestBreakpointHeader
@@ -212,15 +211,15 @@ export class HttpDetailsPane extends React.Component<{
212211

213212
private renderExpandedCard(
214213
expandedCard: ExpandableViewCardKey,
215-
exchange: HttpExchange,
214+
exchange: HttpExchangeView,
216215
apiExchange: ApiExchange | undefined
217216
) {
218217
if (expandedCard === 'requestBody') {
219218
return this.renderRequestBody(exchange, apiExchange);
220219
} else if (
221220
expandedCard === 'responseBody' && (
222221
exchange.isSuccessfulExchange() ||
223-
!!exchange.responseBreakpoint
222+
!!exchange.downstream.responseBreakpoint
224223
)) {
225224
return this.renderResponseBody(exchange, apiExchange);
226225
} else if (
@@ -282,7 +281,7 @@ export class HttpDetailsPane extends React.Component<{
282281
}
283282

284283
private renderNormalCards(
285-
exchange: HttpExchange,
284+
exchange: HttpExchangeView,
286285
apiName: string | undefined,
287286
apiExchange: ApiExchange | undefined
288287
) {
@@ -378,8 +377,9 @@ export class HttpDetailsPane extends React.Component<{
378377
return cards;
379378
}
380379

381-
private renderRequestBody(exchange: HttpExchange, apiExchange: ApiExchange | undefined) {
382-
const { request, requestBreakpoint } = exchange;
380+
private renderRequestBody(exchange: HttpExchangeView, apiExchange: ApiExchange | undefined) {
381+
const { request } = exchange;
382+
const { requestBreakpoint } = exchange.downstream;
383383

384384
return requestBreakpoint
385385
? <HttpBreakpointBodyCard
@@ -398,8 +398,9 @@ export class HttpDetailsPane extends React.Component<{
398398
/>;
399399
}
400400

401-
private renderResponseBody(exchange: HttpExchange, apiExchange: ApiExchange | undefined) {
402-
const { response, responseBreakpoint } = exchange;
401+
private renderResponseBody(exchange: HttpExchangeView, apiExchange: ApiExchange | undefined) {
402+
const { response } = exchange;
403+
const { responseBreakpoint } = exchange.downstream;
403404

404405
return responseBreakpoint
405406
? <HttpBreakpointBodyCard

src/components/view/http/http-export-card.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { action, computed } from "mobx";
33
import { inject, observer } from "mobx-react";
44
import dedent from 'dedent';
55

6-
import { HttpExchange } from '../../../types';
6+
import { HttpExchangeView } from '../../../types';
77
import { styled } from '../../../styles';
88
import { Icon } from '../../../icons';
99
import { logError } from '../../../errors';
@@ -33,7 +33,7 @@ import { DocsLink } from '../../common/docs-link';
3333
import { SelfSizedEditor } from '../../editor/base-editor';
3434

3535
interface ExportCardProps extends CollapsibleCardProps {
36-
exchange: HttpExchange;
36+
exchange: HttpExchangeView;
3737
accountStore?: AccountStore;
3838
uiStore?: UiStore;
3939
}
@@ -69,7 +69,7 @@ const snippetEditorOptions = {
6969
};
7070

7171
const ExportSnippetEditor = observer((p: {
72-
exchange: HttpExchange
72+
exchange: HttpExchangeView
7373
exportOption: SnippetOption
7474
}) => {
7575
const { target, client, link, description } = p.exportOption;
@@ -122,7 +122,7 @@ const ExportSnippetEditor = observer((p: {
122122

123123
const ExportHarPill = styled(observer((p: {
124124
className?: string,
125-
exchange: HttpExchange
125+
exchange: HttpExchangeView
126126
}) =>
127127
<PillButton
128128
className={p.className}

src/components/view/http/http-performance-card.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { observer, inject } from 'mobx-react';
44
import { get } from 'typesafe-get';
55

66
import { styled } from '../../../styles';
7-
import { HttpExchange, ExchangeMessage } from '../../../types';
7+
import { ExchangeMessage, HttpExchangeView } from '../../../types';
88

99
import { getReadableSize } from '../../../util/buffer';
1010
import { asHeaderArray } from '../../../util/headers';
@@ -36,7 +36,7 @@ import { ContentLabelBlock, Markdown } from '../../common/text-content';
3636
import { ProHeaderPill, CardSalesPitch } from '../../account/pro-placeholders';
3737

3838
interface HttpPerformanceCardProps extends CollapsibleCardProps {
39-
exchange: HttpExchange;
39+
exchange: HttpExchangeView;
4040
accountStore?: AccountStore;
4141
}
4242

@@ -208,7 +208,7 @@ const CompressionOptionsTips = styled(PerformanceExplanation)`
208208
font-style: italic;
209209
`;
210210

211-
const CompressionPerformance = observer((p: { exchange: HttpExchange }) => {
211+
const CompressionPerformance = observer((p: { exchange: HttpExchangeView }) => {
212212
const messageTypes: Array<'request' | 'response'> = ['request', 'response'];
213213
const clientAcceptedEncodings = asHeaderArray(p.exchange.request.headers['accept-encoding'])
214214
.map(getEncodingName);
@@ -292,7 +292,7 @@ const CompressionPerformance = observer((p: { exchange: HttpExchange }) => {
292292
}) }</>;
293293
});
294294

295-
const CachingPerformance = observer((p: { exchange: HttpExchange }) => {
295+
const CachingPerformance = observer((p: { exchange: HttpExchangeView }) => {
296296
if (typeof p.exchange.response !== 'object') return null;
297297

298298
const cacheability = explainCacheability(p.exchange);

src/components/view/http/http-request-card.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { inject, observer } from 'mobx-react';
33

4-
import { HttpExchange, HtkRequest, HttpVersion } from '../../../types';
4+
import { HttpExchange, HtkRequest, HttpVersion, HttpExchangeView } from '../../../types';
55
import { styled } from '../../../styles';
66
import { PhosphorIcon } from '../../../icons';
77

@@ -149,7 +149,7 @@ const RawRequestDetails = (p: {
149149
}
150150

151151
interface HttpRequestCardProps extends CollapsibleCardProps {
152-
exchange: HttpExchange;
152+
exchange: HttpExchangeView;
153153
matchedRuleData: {
154154
stepTypes: HandlerClassKey[],
155155
status: 'unchanged' | 'modified-types' | 'deleted'

src/components/view/view-context-menu-builder.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import * as _ from 'lodash';
22
import { runInAction } from 'mobx';
33

4-
import { CollectedEvent, WebSocketStream } from '../../types';
4+
import { CollectedEvent, HttpExchangeView, WebSocketStream } from '../../types';
55

66
import { copyToClipboard } from '../../util/ui';
77

88
import { AccountStore } from '../../model/account/account-store';
99
import { UiStore } from '../../model/ui/ui-store';
10-
import { HttpExchange } from '../../model/http/exchange';
10+
import { HttpExchange } from '../../model/http/http-exchange';
1111
import {
1212
exportHar,
1313
generateCodeSnippet,
@@ -26,8 +26,8 @@ export class ViewEventContextMenuBuilder {
2626

2727
private onPin: (event: CollectedEvent) => void,
2828
private onDelete: (event: CollectedEvent) => void,
29-
private onBuildRuleFromExchange: (exchange: HttpExchange) => void,
30-
private onPrepareToResendRequest?: (exchange: HttpExchange) => void
29+
private onBuildRuleFromExchange: (exchange: HttpExchangeView) => void,
30+
private onPrepareToResendRequest?: (exchange: HttpExchangeView) => void
3131
) {}
3232

3333
private readonly BaseOptions = {
@@ -57,7 +57,7 @@ export class ViewEventContextMenuBuilder {
5757
{
5858
type: 'option',
5959
label: 'Copy Request URL',
60-
callback: (data: HttpExchange) => copyToClipboard(data.request.url)
60+
callback: (data: HttpExchangeView) => copyToClipboard(data.request.url)
6161
},
6262
...(!isPaidUser ? [
6363
{ type: 'separator' },
@@ -68,7 +68,7 @@ export class ViewEventContextMenuBuilder {
6868
type: 'option',
6969
enabled: isPaidUser,
7070
label: 'Resend Request',
71-
callback: (data: HttpExchange) => this.onPrepareToResendRequest!(data)
71+
callback: (data: HttpExchangeView) => this.onPrepareToResendRequest!(data)
7272
}
7373
] as const : []),
7474
{

src/components/view/view-event-list-buttons.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as dateFns from 'date-fns';
44
import * as dedent from 'dedent';
55
import * as Ajv from 'ajv';
66

7-
import { CollectedEvent } from '../../types';
7+
import { ViewableEvent } from '../../types';
88
import { saveFile, uploadFile, Ctrl } from '../../util/ui';
99

1010
import { AccountStore } from '../../model/account/account-store';
@@ -29,7 +29,7 @@ export const ClearAllButton = observer((props: {
2929
export const ExportAsHarButton = inject('accountStore')(observer((props: {
3030
className?: string,
3131
accountStore?: AccountStore,
32-
events: ReadonlyArray<CollectedEvent>
32+
events: ReadonlyArray<ViewableEvent>
3333
}) => {
3434
const { isPaidUser } = props.accountStore!;
3535

0 commit comments

Comments
 (0)