Skip to content

Commit 27ba64c

Browse files
committed
Improve request error handling
See #1532 for more context. - Errored JSON requests will get back the error in JSON instead of using the status text. This seems better to me because it seems more correct to utilize the response body over hijacking the status text. The caller is expecting JSON anyway. Worst of all I never actually set the status text like I thought I did so it wasn't working to begin with. - Allow the update error to propagate for JSON update requests. It was caught to show the error inline instead of an error page when using the update page but for JSON requests it meant there was no error and no error code so it looked like it succeeded. - Make errors for failed requests to GitHub less incomprehensible. Previously they would just be the code which is no context at all.
1 parent c7753f2 commit 27ba64c

File tree

4 files changed

+38
-23
lines changed

4 files changed

+38
-23
lines changed

ci/vscode.patch

+8-10
Original file line numberDiff line numberDiff line change
@@ -541,10 +541,10 @@ index eab8591492..26668701f7 100644
541541
options.logService.error(`${logPrefix} socketFactory.connect() failed. Error:`);
542542
diff --git a/src/vs/server/browser/client.ts b/src/vs/server/browser/client.ts
543543
new file mode 100644
544-
index 0000000000..4f8543d975
544+
index 0000000000..649cf32f0a
545545
--- /dev/null
546546
+++ b/src/vs/server/browser/client.ts
547-
@@ -0,0 +1,266 @@
547+
@@ -0,0 +1,264 @@
548548
+import { Emitter } from 'vs/base/common/event';
549549
+import { URI } from 'vs/base/common/uri';
550550
+import { localize } from 'vs/nls';
@@ -720,11 +720,10 @@ index 0000000000..4f8543d975
720720
+ const response = await fetch(normalize(`${options.base}/update/apply`), {
721721
+ headers: { "content-type": "application/json" },
722722
+ });
723-
+ if (response.status !== 200) {
724-
+ throw new Error(response.statusText);
725-
+ }
726-
+
727723
+ const json = await response.json();
724+
+ if (response.status !== 200 || json.error) {
725+
+ throw new Error(json.error || response.statusText);
726+
+ }
728727
+ (services.get(INotificationService) as INotificationService).info(`Updated to ${json.version}`);
729728
+ };
730729
+
@@ -734,11 +733,10 @@ index 0000000000..4f8543d975
734733
+ const response = await fetch(normalize(`${options.base}/update`), {
735734
+ headers: { "content-type": "application/json" },
736735
+ });
737-
+ if (response.status !== 200) {
738-
+ throw new Error("unexpected response");
739-
+ }
740-
+
741736
+ const json = await response.json();
737+
+ if (response.status !== 200 || json.error) {
738+
+ throw new Error(json.error || response.statusText);
739+
+ }
742740
+ if (json.isLatest) {
743741
+ return;
744742
+ }

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "code-server",
33
"license": "MIT",
4-
"version": "3.1.1",
4+
"version": "3.1.2",
55
"scripts": {
66
"clean": "ci/clean.sh",
77
"vscode": "ci/vscode.sh",

src/node/app/update.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ export class UpdateHttpProvider extends HttpProvider {
8787
public async getRoot(
8888
route: Route,
8989
request: http.IncomingMessage,
90-
appliedUpdate?: string,
91-
error?: Error,
90+
errorOrUpdate?: Update | Error,
9291
): Promise<HttpResponse> {
9392
if (request.headers["content-type"] === "application/json") {
9493
if (!this.enabled) {
@@ -108,8 +107,13 @@ export class UpdateHttpProvider extends HttpProvider {
108107
}
109108
const response = await this.getUtf8Resource(this.rootPath, "src/browser/pages/update.html")
110109
response.content = response.content
111-
.replace(/{{UPDATE_STATUS}}/, appliedUpdate ? `Updated to ${appliedUpdate}` : await this.getUpdateHtml())
112-
.replace(/{{ERROR}}/, error ? `<div class="error">${error.message}</div>` : "")
110+
.replace(
111+
/{{UPDATE_STATUS}}/,
112+
errorOrUpdate && !(errorOrUpdate instanceof Error)
113+
? `Updated to ${errorOrUpdate.version}`
114+
: await this.getUpdateHtml(),
115+
)
116+
.replace(/{{ERROR}}/, errorOrUpdate instanceof Error ? `<div class="error">${errorOrUpdate.message}</div>` : "")
113117
return this.replaceTemplates(route, response)
114118
}
115119

@@ -186,11 +190,16 @@ export class UpdateHttpProvider extends HttpProvider {
186190
const update = await this.getUpdate()
187191
if (!this.isLatestVersion(update)) {
188192
await this.downloadAndApplyUpdate(update)
189-
return this.getRoot(route, request, update.version)
193+
return this.getRoot(route, request, update)
190194
}
191195
return this.getRoot(route, request)
192196
} catch (error) {
193-
return this.getRoot(route, request, undefined, error)
197+
// For JSON requests propagate the error. Otherwise catch it so we can
198+
// show the error inline with the update button instead of an error page.
199+
if (request.headers["content-type"] === "application/json") {
200+
throw error
201+
}
202+
return this.getRoot(route, error)
194203
}
195204
}
196205

@@ -362,7 +371,7 @@ export class UpdateHttpProvider extends HttpProvider {
362371
}
363372

364373
if (!response.statusCode || response.statusCode < 200 || response.statusCode >= 400) {
365-
return reject(new Error(`${response.statusCode || "500"}`))
374+
return reject(new Error(`${uri}: ${response.statusCode || "500"}`))
366375
}
367376

368377
resolve(response)

src/node/http.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -646,11 +646,19 @@ export class HttpServer {
646646
if (code >= HttpCode.ServerError) {
647647
logger.error(error.stack)
648648
}
649-
const payload = await route.provider.getErrorRoot(route, code, code, e.message)
650-
write({
651-
code,
652-
...payload,
653-
})
649+
if (request.headers["content-type"] === "application/json") {
650+
write({
651+
code,
652+
content: {
653+
error: e.message,
654+
},
655+
})
656+
} else {
657+
write({
658+
code,
659+
...(await route.provider.getErrorRoot(route, code, code, e.message)),
660+
})
661+
}
654662
}
655663
}
656664

0 commit comments

Comments
 (0)