Skip to content

Commit bcea009

Browse files
feat(dx): add default message for missing handler
This commit adds a default message for the HTTP handler to the 500 that is returned when the event loop has run but the request is still not being responded to via the fetch-event integration. In these cases, the user would normally receive a 500 with no information on what went wrong (e.g. if run with `wasmtime serve`), so with this PR we can do a little more to point towards the issue.
1 parent f53dece commit bcea009

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

builtins/web/fetch/fetch_event.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,40 @@ bool FetchEvent::respondWithError(JSContext *cx, JS::HandleObject self) {
337337
return send_response(response, self, FetchEvent::State::respondedWithError);
338338
}
339339

340+
/**
341+
* @brief Responds with an error that contains some text for the HTTP response body
342+
*
343+
* @param cx The Javascript context
344+
* @param self A handle to the `FetchEvent` object
345+
* @param body_text The text to send as the body
346+
*
347+
* @return True if the response was sent successfully
348+
* @throws None directly, but surfaces errors to JS via `HANDLE_ERROR`
349+
*/
350+
bool FetchEvent::respondWithErrorString(JSContext *cx, JS::HandleObject self, std::string_view body_text) {
351+
MOZ_RELEASE_ASSERT(state(self) == State::unhandled || state(self) == State::waitToRespond);
352+
353+
auto headers = std::make_unique<host_api::HttpHeaders>();
354+
auto header_set_res = headers->set("content-type", "text/plain");
355+
if (auto *err = header_set_res.to_err()) {
356+
HANDLE_ERROR(cx, *err);
357+
return false;
358+
}
359+
360+
auto *response = host_api::HttpOutgoingResponse::make(500, std::move(headers));
361+
362+
auto body_res = response->body();
363+
if (auto *err = body_res.to_err()) {
364+
HANDLE_ERROR(cx, *err);
365+
return false;
366+
}
367+
368+
auto body = std::move(body_res.unwrap());
369+
body->write(reinterpret_cast<const uint8_t*>(body_text.data()), body_text.length());
370+
371+
return send_response(response, self, FetchEvent::State::respondedWithError);
372+
}
373+
340374
// Steps in this function refer to the spec at
341375
// https://w3c.github.io/ServiceWorker/#wait-until-method
342376
bool FetchEvent::waitUntil(JSContext *cx, unsigned argc, JS::Value *vp) {
@@ -468,6 +502,8 @@ static void dispatch_fetch_event(HandleObject event, double *total_compute) {
468502
EventTarget::dispatch_event(ENGINE->cx(), event_target, event_val, &rval);
469503
}
470504

505+
constexpr const char DEFAULT_NO_HANDLER_ERROR[] = "ERROR: no fetch-event handler triggered, was one registered?";
506+
471507
bool handle_incoming_request(host_api::HttpIncomingRequest *request) {
472508
#ifdef DEBUG
473509
fprintf(stderr, "Warning: Using a DEBUG build. Expect things to be SLOW.\n");
@@ -504,7 +540,9 @@ bool handle_incoming_request(host_api::HttpIncomingRequest *request) {
504540
}
505541

506542
if (!FetchEvent::response_started(fetch_event)) {
507-
FetchEvent::respondWithError(ENGINE->cx(), fetch_event);
543+
// If at this point no fetch event handler has run, we can
544+
// send a specific error indicating that there is likely no handler registered
545+
FetchEvent::respondWithErrorString(ENGINE->cx(), fetch_event, std::string_view(DEFAULT_NO_HANDLER_ERROR_MSG));
508546
return true;
509547
}
510548

builtins/web/fetch/fetch_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class FetchEvent final : public BuiltinNoConstructor<FetchEvent> {
5858
host_api::HttpIncomingRequest *req);
5959

6060
static bool respondWithError(JSContext *cx, JS::HandleObject self);
61+
static bool respondWithErrorString(JSContext *cx, JS::HandleObject self, std::string_view body_text);
6162
static bool is_active(JSObject *self);
6263

6364
static State state(JSObject *self);

0 commit comments

Comments
 (0)