Skip to content

Commit 87eb88c

Browse files
committed
Simplify away lastHeader to getHeaderValue instead
1 parent d82dfda commit 87eb88c

File tree

11 files changed

+41
-48
lines changed

11 files changed

+41
-48
lines changed

src/components/editor/content-viewer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { styled } from '../../styles';
1010
import { ObservablePromise, isObservablePromise } from '../../util/observable';
1111
import { asError, unreachableCheck } from '../../util/error';
1212
import { stringToBuffer } from '../../util/buffer';
13-
import { lastHeader } from '../../util/headers';
13+
import { getHeaderValue } from '../../util/headers';
1414

1515
import { ViewableContentType } from '../../model/events/content-types';
1616
import { Formatters, isEditorFormatter } from '../../model/events/body-formatting';
@@ -201,7 +201,7 @@ export class ContentViewer extends React.Component<ContentViewerProps> {
201201
return <FormatterContainer expanded={this.props.expanded}>
202202
<formatterConfig.Component
203203
content={this.contentBuffer}
204-
rawContentType={lastHeader(this.props.headers?.['content-type'])}
204+
rawContentType={getHeaderValue(this.props.headers, 'content-type')}
205205
/>
206206
</FormatterContainer>;
207207
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as portals from 'react-reverse-portal';
77
import { ExchangeMessage } from '../../types';
88

99
import { ErrorLike } from '../../util/error';
10-
import { getHeaderValue, lastHeader } from '../../util/headers';
10+
import { getHeaderValue } from '../../util/headers';
1111

1212
import { ViewableContentType, getCompatibleTypes } from '../../model/events/content-types';
1313

@@ -80,7 +80,7 @@ export class SentResponseBodyCard extends React.Component<ExpandableCardProps &
8080
const compatibleContentTypes = message
8181
? getCompatibleTypes(
8282
message.contentType,
83-
lastHeader(message.headers['content-type']),
83+
getHeaderValue(message.headers, 'content-type'),
8484
message.body,
8585
message.headers,
8686
)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as portals from 'react-reverse-portal';
88
import { ExchangeMessage } from '../../../types';
99

1010
import { ErrorLike } from '../../../util/error';
11-
import { getHeaderValue, lastHeader } from '../../../util/headers';
11+
import { getHeaderValue } from '../../../util/headers';
1212

1313
import { ViewableContentType, getCompatibleTypes } from '../../../model/events/content-types';
1414

@@ -81,7 +81,7 @@ export class HttpBodyCard extends React.Component<ExpandableCardProps & {
8181

8282
const compatibleContentTypes = getCompatibleTypes(
8383
message.contentType,
84-
lastHeader(message.headers['content-type']),
84+
getHeaderValue(message.headers, 'content-type'),
8585
message.body,
8686
message.headers,
8787
);

src/model/api/openapi.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
Html
2222
} from "../../types";
2323
import { firstMatch, empty } from '../../util';
24-
import { lastHeader } from '../../util/headers';
24+
import { getHeaderValue } from '../../util/headers';
2525
import { formatAjvError } from '../../util/json-schema';
2626

2727
import {
@@ -235,7 +235,7 @@ export function getBodySchema(
235235
): SchemaObject {
236236
if (!bodyDefinition || !message || message === 'aborted') return {};
237237

238-
const contentType = lastHeader(message.headers['content-type']) || '*/*';
238+
const contentType = getHeaderValue(message.headers, 'content-type') || '*/*';
239239

240240
const schemasByType = bodyDefinition.content;
241241
if (!schemasByType) return {};
@@ -352,7 +352,7 @@ export function matchOpenApiOperation(api: OpenApiMetadata, request: HtkRequest)
352352
}
353353

354354
const method = (
355-
lastHeader(request.headers['x-http-method-override']) || request.method
355+
getHeaderValue(request.headers, 'x-http-method-override') || request.method
356356
).toLowerCase();
357357

358358
let operation: OperationObject | undefined = get(pathSpec, method);

src/model/events/categorization.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ import * as _ from 'lodash';
22

33
import { ExchangeMessage } from '../../types';
44
import { Theme } from '../../styles';
5-
import { lastHeader } from '../../util/headers';
5+
import { getHeaderValue } from '../../util/headers';
66

77
import { getBaseContentType } from './content-types';
88

99
import { HTKEventBase } from './event-base';
1010
import { HttpExchange, SuccessfulExchange } from '../http/exchange';
1111

1212
export const getMessageBaseAcceptTypes = (message: ExchangeMessage) =>
13-
(lastHeader(message.headers['accept'])?.split(',') || [])
13+
(getHeaderValue(message.headers, 'accept')?.split(',') || [])
1414
.map((acceptType) => getBaseContentType(acceptType));
1515

1616
export const getMessageBaseContentType = (message: ExchangeMessage) =>
17-
getBaseContentType(lastHeader(message.headers['content-type']));
17+
getBaseContentType(getHeaderValue(message.headers, 'content-type'));
1818

1919
const isMutatativeExchange = (exchange: HttpExchange) => _.includes([
2020
'POST',

src/model/http/caching.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from 'date-fns';
99

1010
import { HttpExchange, ExchangeMessage } from '../../types';
11-
import { lastHeader, asHeaderArray } from '../../util/headers';
11+
import { getHeaderValue, asHeaderArray } from '../../util/headers';
1212
import { joinAnd } from '../../util/text';
1313
import { escapeForMarkdownEmbedding } from '../ui/markdown';
1414

@@ -106,7 +106,7 @@ export function explainCacheability(exchange: HttpExchange): (
106106
// This is a CORS preflight request - it's not really cacheable, but the CORS
107107
// headers specifically (probably the only interesting bit) are, via their
108108
// own separate funky mechanism.
109-
const maxAgeHeader = lastHeader(response.headers['access-control-max-age']);
109+
const maxAgeHeader = getHeaderValue(response.headers, 'access-control-max-age');
110110
const maxAge = maxAgeHeader ? parseInt(maxAgeHeader, 10) : undefined;
111111

112112
if (maxAge !== undefined && maxAge >= 1) {
@@ -238,7 +238,7 @@ export function explainCacheability(exchange: HttpExchange): (
238238
`;
239239

240240
const contentLocationUrl = response.headers['content-location'] ?
241-
new URL(lastHeader(response.headers['content-location']!), request.url) : undefined;
241+
new URL(getHeaderValue(response.headers, 'content-location')!, request.url) : undefined;
242242

243243
const hasFreshnessInfo =
244244
!!responseCCDirectives['max-age'] ||
@@ -272,7 +272,7 @@ export function explainCacheability(exchange: HttpExchange): (
272272
let warning: string | undefined;
273273

274274
const responseDateHeader = response.headers['date'] ?
275-
parseDate(lastHeader(response.headers['date'])!)
275+
parseDate(getHeaderValue(response.headers, 'date')!)
276276
: undefined;
277277

278278
if (!responseDateHeader) {
@@ -287,7 +287,7 @@ export function explainCacheability(exchange: HttpExchange): (
287287
predictably.
288288
`;
289289
} else if (response.headers['expires'] && Math.abs(differenceInSeconds(
290-
parseDate(lastHeader(response.headers['expires']!)),
290+
parseDate(getHeaderValue(response.headers, 'expires')!),
291291
addSeconds(responseDateHeader, responseCCDirectives['max-age'])
292292
)) > 60) {
293293
warning = dedent`
@@ -318,7 +318,7 @@ export function explainCacheability(exchange: HttpExchange): (
318318
};
319319
}
320320

321-
if (lastHeader(response.headers['expires']) !== undefined) {
321+
if (getHeaderValue(response.headers, 'expires') !== undefined) {
322322
// Expires set, but not max-age (checked above).
323323
return {
324324
cacheable: true,
@@ -649,7 +649,7 @@ export function explainCacheLifetime(exchange: HttpExchange): Explanation | unde
649649
const responseCCDirectives = parseCCDirectives(response);
650650

651651
if (request.method === 'OPTIONS') {
652-
const maxAgeHeader = lastHeader(response.headers['access-control-max-age']);
652+
const maxAgeHeader = getHeaderValue(response.headers, 'access-control-max-age');
653653

654654
if (maxAgeHeader) {
655655
const maxAge = parseInt(maxAgeHeader!, 10);
@@ -694,8 +694,8 @@ export function explainCacheLifetime(exchange: HttpExchange): Explanation | unde
694694
};
695695
}
696696

697-
const dateHeader = lastHeader(response.headers['date']);
698-
const expiresHeader = lastHeader(response.headers['expires']);
697+
const dateHeader = getHeaderValue(response.headers, 'date');
698+
const expiresHeader = getHeaderValue(response.headers, 'expires');
699699
const maxAge = responseCCDirectives['max-age'];
700700
const sharedMaxAge = responseCCDirectives['s-maxage'] !== undefined ?
701701
responseCCDirectives['s-maxage'] : maxAge;

src/model/http/exchange-breakpoint.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export abstract class Breakpoint<T extends BreakpointInProgress> {
138138
newValue: newEncodedLength
139139
}) => {
140140
const { rawHeaders } = this.resultMetadata;
141-
const previousContentLength = parseInt(getHeaderValue(rawHeaders, 'Content-Length') || '', 10);
141+
const previousContentLength = parseInt(getHeaderValue(rawHeaders, 'content-length') || '', 10);
142142

143143
// If the content-length was previously correct, keep it correct:
144144
if (previousContentLength === previousEncodedLength) {
@@ -151,8 +151,8 @@ export abstract class Breakpoint<T extends BreakpointInProgress> {
151151
});
152152

153153
// When content-length is first added, default to the correct value
154-
let oldContentLength = getHeaderValue(this.resultMetadata.rawHeaders, 'Content-Length');
155-
reaction(() => getHeaderValue(this.resultMetadata.rawHeaders, 'Content-Length'), (newContentLength) => {
154+
let oldContentLength = getHeaderValue(this.resultMetadata.rawHeaders, 'content-length');
155+
reaction(() => getHeaderValue(this.resultMetadata.rawHeaders, 'content-length'), (newContentLength) => {
156156
if (oldContentLength === undefined && newContentLength === "") {
157157
const { rawHeaders } = this.resultMetadata;
158158
this.updateMetadata({

src/model/http/exchange.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { UnreachableCheck } from '../../util/error';
2525
import { lazyObservablePromise, ObservablePromise, observablePromise } from "../../util/observable";
2626
import {
2727
asHeaderArray,
28-
lastHeader
28+
getHeaderValue
2929
} from '../../util/headers';
3030

3131
import { logError } from '../../errors';
@@ -86,7 +86,7 @@ function addRequestMetadata(request: InputRequest): HtkRequest {
8686
? MANUALLY_SENT_SOURCE
8787
: parseSource(request.headers['user-agent']),
8888
body: new HttpBody(request, request.headers),
89-
contentType: getContentType(lastHeader(request.headers['content-type'])) || 'text',
89+
contentType: getContentType(getHeaderValue(request.headers, 'content-type')) || 'text',
9090
cache: observable.map(new Map<symbol, unknown>(), { deep: false })
9191
}) as HtkRequest;
9292
} catch (e) {
@@ -98,10 +98,7 @@ function addRequestMetadata(request: InputRequest): HtkRequest {
9898
function addResponseMetadata(response: InputResponse): HtkResponse {
9999
return Object.assign(response, {
100100
body: new HttpBody(response, response.headers),
101-
contentType: getContentType(
102-
// There should only ever be one. If we get multiple though, just use the last.
103-
lastHeader(response.headers['content-type'])
104-
) || 'text',
101+
contentType: getContentType(getHeaderValue(response.headers, 'content-type')) || 'text',
105102
cache: observable.map(new Map<symbol, unknown>(), { deep: false })
106103
}) as HtkResponse;
107104
}

src/model/http/har.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from '../../types';
2020

2121
import { stringToBuffer } from '../../util/buffer';
22-
import { getHeaderValues, lastHeader } from '../../util/headers';
22+
import { getHeaderValues, getHeaderValue } from '../../util/headers';
2323
import { ObservablePromise } from '../../util/observable';
2424
import { unreachableCheck } from '../../util/error';
2525

@@ -227,7 +227,7 @@ export function generateHarRequest(
227227
try {
228228
requestEntry.postData = generateHarPostBody(
229229
UTF8Decoder.decode(request.body.decoded),
230-
lastHeader(request.headers['content-type']) || 'application/octet-stream'
230+
getHeaderValue(request.headers, 'content-type') || 'application/octet-stream'
231231
);
232232
} catch (e) {
233233
if (e instanceof TypeError) {
@@ -362,7 +362,7 @@ async function generateHarResponse(
362362
headers: asHarHeaders(response.headers),
363363
content: Object.assign(
364364
{
365-
mimeType: lastHeader(response.headers['content-type']) ||
365+
mimeType: getHeaderValue(response.headers, 'content-type') ||
366366
'application/octet-stream',
367367
size: response.body.decoded?.byteLength || 0
368368
},

src/util/headers.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,18 @@ export const rawHeadersToHeaders = (headers: RawHeaders): Headers =>
4343

4444
/**
4545
* Get the header value for the given header key. Case insensitive. If there are multiple values,
46-
* this will return the last value. If there are no values this returns undefined.
46+
* this will return the last value. If there are no values or the headers themselves aren't defined,
47+
* this returns undefined.
4748
*/
48-
export const getHeaderValue = (headers: Headers | RawHeaders, headerKey: string): string | undefined => {
49+
export function getHeaderValue(
50+
headers: Headers | RawHeaders | undefined,
51+
headerKey: Lowercase<string>
52+
): string | undefined {
4953
if (Array.isArray(headers)) {
50-
headerKey = headerKey.toLowerCase();
5154
const headerPair = _.findLast(headers, ([key]) => key.toLowerCase() === headerKey);
5255
return headerPair?.[1];
5356
} else {
54-
const headerValue = headers[headerKey];
57+
const headerValue = headers?.[headerKey];
5558

5659
if (Array.isArray(headerValue)) {
5760
return headerValue[headerValue.length - 1];
@@ -146,15 +149,6 @@ export const withHeaderValue = <T extends Headers | RawHeaders>(headers: T, head
146149
return headers;
147150
}
148151

149-
// This fairly meaningless override combo seems to be
150-
// required to make it ok to use this when T = X | undefined.
151-
export function lastHeader<T>(val: T | T[]): T;
152-
export function lastHeader<T>(val: T | T[] | undefined): T | undefined;
153-
export function lastHeader<T>(val: T | T[] | undefined): T | undefined {
154-
if (Array.isArray(val)) return val[val.length - 1];
155-
else return val;
156-
}
157-
158152
export function asHeaderArray(val: string | string[] | undefined, sep = ','): string[] {
159153
if (Array.isArray(val)) {
160154
// Split individual values, as multiple headers can still have multiple values

src/util/protobuf.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import parseRawProto from 'rawprotoparse';
22
import { gunzipSync, inflateSync } from 'zlib';
33

44
import { Headers } from '../types';
5-
import { lastHeader } from './headers';
5+
import { getHeaderValue } from './headers';
66

77
export function isProbablyProtobuf(input: Uint8Array) {
88
// Protobuf data starts with a varint, consisting of a
@@ -52,7 +52,9 @@ export const parseRawProtobuf = parseRawProto;
5252
// A value of 0 indicates that no encoding of Message bytes has occurred.
5353
// If the Message-Encoding header is omitted then the Compressed-Flag must be 0.
5454
export const extractProtobufFromGrpc = (input: Buffer, headers: Headers) => {
55-
const grpcEncoding = lastHeader(headers['grpc-encoding'] ?? 'identity').toLocaleLowerCase();
55+
const grpcEncoding = (
56+
getHeaderValue(headers, 'grpc-encoding') ?? 'identity'
57+
).toLocaleLowerCase();
5658
const grpcDecoder = grpcEncoding == 'gzip' ? gunzipSync : grpcEncoding == 'deflate' ? inflateSync : undefined;
5759
const protobufMessages: Buffer[] = [];
5860

0 commit comments

Comments
 (0)