Skip to content

Commit f2122c8

Browse files
committed
Explain more HTTP errors (unparseable responses + client disconnect)
1 parent 1e96c4b commit f2122c8

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

src/components/view/http/http-error-header.tsx

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ type ErrorType =
2525
| 'dns-error'
2626
| 'connection-refused'
2727
| 'connection-reset'
28+
| 'client-abort'
2829
| 'server-timeout'
2930
| 'client-timeout'
3031
| 'invalid-http-version'
3132
| 'invalid-method'
32-
| 'unparseable-url'
33-
| 'unparseable'
33+
| 'client-unparseable-url'
34+
| 'client-unparseable'
35+
| 'server-unparseable'
3436
| 'header-overflow'
3537
| 'invalid-headers'
3638
| 'unknown';
@@ -70,17 +72,25 @@ export function tagsToErrorType(tags: string[]): ErrorType | undefined {
7072
if (tags.includes("passthrough-error:ECONNREFUSED")) return 'connection-refused';
7173
if (tags.includes("passthrough-error:ECONNRESET")) return 'connection-reset';
7274
if (tags.includes("passthrough-error:ETIMEDOUT")) return 'server-timeout';
75+
if (
76+
tags.includes("passthrough-error:HPE_INVALID_CONSTANT") ||
77+
tags.includes("passthrough-error:ERR_INVALID_HTTP_TOKEN") ||
78+
tags.includes("passthrough-error:ERR_HTTP_INVALID_STATUS_CODE") ||
79+
tags.includes("passthrough-error:ERR_INVALID_CHAR")
80+
) {
81+
return 'server-unparseable';
82+
}
7383

7484
if (tags.includes("http-2") || tags.includes("client-error:HPE_INVALID_VERSION")) {
7585
return 'invalid-http-version';
7686
}
7787

7888
if (tags.includes("client-error:HPE_INVALID_METHOD")) return 'invalid-method'; // QWE / HTTP/1.1
79-
if (tags.includes("client-error:HPE_INVALID_URL")) return 'unparseable-url'; // http://<unicode>
89+
if (tags.includes("client-error:HPE_INVALID_URL")) return 'client-unparseable-url'; // http://<unicode>
8090
if (
8191
tags.includes("client-error:HPE_INVALID_CONSTANT") || // GET / HTTQ <- incorrect constant char
8292
tags.includes("client-error:HPE_INVALID_EOF_STATE") // Unexpected 0-length packet in parser
83-
) return 'unparseable'; // ABC/1.1
93+
) return 'client-unparseable'; // ABC/1.1
8494
if (tags.includes("client-error:HPE_HEADER_OVERFLOW")) return 'header-overflow'; // More than ~80KB of headers
8595
if (
8696
tags.includes("client-error:HPE_INVALID_CONTENT_LENGTH") ||
@@ -91,6 +101,10 @@ export function tagsToErrorType(tags: string[]): ErrorType | undefined {
91101
) return 'invalid-headers';
92102

93103
if (tags.includes("client-error:ERR_HTTP_REQUEST_TIMEOUT")) return 'client-timeout';
104+
if (
105+
tags.includes("client-error:ECONNABORTED") ||
106+
tags.includes("client-error:EPIPE")
107+
) return 'client-abort';
94108

95109
if (
96110
tags.filter(t => t.startsWith("passthrough-error:")).length > 0 ||
@@ -108,15 +122,15 @@ function typeCheck<T extends string>(types: readonly T[]) {
108122
const isInitialRequestError = typeCheck([
109123
'invalid-http-version',
110124
'invalid-method',
111-
'unparseable',
112-
'unparseable-url',
125+
'client-unparseable',
126+
'client-unparseable-url',
113127
'header-overflow',
114128
'invalid-headers'
115129
]);
116130

117131
const isClientBug = typeCheck([
118-
'unparseable',
119-
'unparseable-url',
132+
'client-unparseable',
133+
'client-unparseable-url',
120134
'invalid-headers'
121135
]);
122136

@@ -132,6 +146,11 @@ const wasNotForwarded = typeCheck([
132146
'connection-refused'
133147
]);
134148

149+
const wasResponseIssue = typeCheck([
150+
'server-unparseable',
151+
'connection-reset'
152+
]);
153+
135154
const wasTimeout = typeCheck([
136155
'client-timeout',
137156
'server-timeout'
@@ -192,11 +211,11 @@ export const HttpErrorHeader = (p: {
192211
? 'used an unsupported HTTP version'
193212
: p.type === 'invalid-headers'
194213
? 'included an invalid or unparseable header'
195-
: p.type === 'unparseable-url'
214+
: p.type === 'client-unparseable-url'
196215
? 'included an unparseable URL'
197216
: p.type === 'header-overflow'
198217
? 'headers were too large to be processed'
199-
: p.type === 'unparseable'
218+
: p.type === 'client-unparseable'
200219
? 'could not be parsed'
201220
: new UnreachableCheck(p.type)
202221
}, so HTTP Toolkit did not handle this request.
@@ -233,15 +252,25 @@ export const HttpErrorHeader = (p: {
233252
: new UnreachableCheck(p.type)
234253
}
235254
</>
236-
: p.type === 'unknown' || p.type === 'connection-reset'
255+
: p.type === 'client-abort'
256+
? <>
257+
The client unexpectedly disconnected during the request, so
258+
the response could not be completed.
259+
</>
260+
: wasResponseIssue(p.type)
237261
? <>
238-
The request failed because {
262+
The upstream request failed because {
239263
p.type === 'connection-reset'
240264
? 'the connection to the server was reset'
241-
: p.type === 'unknown'
242-
? 'of an unknown error'
265+
: p.type === 'server-unparseable'
266+
? 'the response from the server was unparseable'
243267
: new UnreachableCheck(p.type)
244-
}, so HTTP Toolkit could not return a response.
268+
}, so HTTP Toolkit could not return a response to the client.
269+
</>
270+
: p.type === 'unknown'
271+
? <>
272+
The request failed because of an unknown error,
273+
so HTTP Toolkit could not return a response.
245274
</>
246275
: new UnreachableCheck(p.type)
247276
}
@@ -336,6 +365,12 @@ export const HttpErrorHeader = (p: {
336365
the request. You can also mock requests like this, to avoid sending them upstream
337366
at all.
338367
</HeaderText>
368+
: p.type === 'client-abort'
369+
? <HeaderText>
370+
This could be due to connection issues, general problems in the client, or that
371+
the client simply no longer wanted to receive the response and closed the
372+
connection intentionally.
373+
</HeaderText>
339374
: p.type === 'client-timeout'
340375
? <HeaderText>
341376
This could be due to connection issues, general problems in the client, or delays
@@ -355,6 +390,12 @@ export const HttpErrorHeader = (p: {
355390
not follow the HTTP spec. That suggests either a major bug in the client, or that
356391
they're not sending HTTP at all.
357392
</HeaderText>
393+
: p.type === 'server-unparseable'
394+
? <HeaderText>
395+
This means the server sent HTTP Toolkit some fundamentally invalid data that does
396+
not follow the HTTP spec. That suggests either a major bug in the server, or that
397+
they're not sending HTTP at all.
398+
</HeaderText>
358399
: p.type === 'header-overflow'
359400
? <HeaderText>
360401
{ desktopVersion.value && advancedHeaderOverflowSupported

0 commit comments

Comments
 (0)