Skip to content

Commit 58b6042

Browse files
feat(dx): add default message for missing handler (#264)
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 8125ed6 commit 58b6042

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

builtins/web/fetch/fetch_event.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <iostream>
1717
#include <memory>
18+
#include <optional>
1819

1920
using builtins::web::event::Event;
2021
using builtins::web::event::EventTarget;
@@ -32,6 +33,8 @@ JSString *fetch_type_atom;
3233
JS::PersistentRootedObject INSTANCE;
3334
host_api::HttpOutgoingBody *STREAMING_BODY;
3435

36+
constexpr const std::string_view DEFAULT_NO_HANDLER_ERROR_MSG = "ERROR: no fetch-event handler triggered, was one registered?";
37+
3538
void inc_pending_promise_count(JSObject *self) {
3639
MOZ_ASSERT(FetchEvent::is_instance(self));
3740
auto count = JS::GetReservedSlot(self, FetchEvent::Slots::PendingPromiseCount).toInt32();
@@ -322,10 +325,18 @@ bool FetchEvent::respondWith(JSContext *cx, unsigned argc, JS::Value *vp) {
322325
return true;
323326
}
324327

325-
bool FetchEvent::respondWithError(JSContext *cx, JS::HandleObject self) {
328+
bool FetchEvent::respondWithError(JSContext *cx, JS::HandleObject self, std::optional<std::string_view> body_text) {
326329
MOZ_RELEASE_ASSERT(state(self) == State::unhandled || state(self) == State::waitToRespond);
327330

328331
auto headers = std::make_unique<host_api::HttpHeaders>();
332+
if (body_text) {
333+
auto header_set_res = headers->set("content-type", "text/plain");
334+
if (auto *err = header_set_res.to_err()) {
335+
HANDLE_ERROR(cx, *err);
336+
return false;
337+
}
338+
}
339+
329340
auto *response = host_api::HttpOutgoingResponse::make(500, std::move(headers));
330341

331342
auto body_res = response->body();
@@ -334,6 +345,11 @@ bool FetchEvent::respondWithError(JSContext *cx, JS::HandleObject self) {
334345
return false;
335346
}
336347

348+
if (body_text) {
349+
auto body = std::move(body_res.unwrap());
350+
body->write(reinterpret_cast<const uint8_t*>(body_text->data()), body_text->length());
351+
}
352+
337353
return send_response(response, self, FetchEvent::State::respondedWithError);
338354
}
339355

@@ -504,7 +520,9 @@ bool handle_incoming_request(host_api::HttpIncomingRequest *request) {
504520
}
505521

506522
if (!FetchEvent::response_started(fetch_event)) {
507-
FetchEvent::respondWithError(ENGINE->cx(), fetch_event);
523+
// If at this point no fetch event handler has run, we can
524+
// send a specific error indicating that there is likely no handler registered
525+
FetchEvent::respondWithError(ENGINE->cx(), fetch_event, DEFAULT_NO_HANDLER_ERROR_MSG);
508526
return true;
509527
}
510528

builtins/web/fetch/fetch_event.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "../event/event.h"
99

10+
#include <optional>
11+
1012
namespace builtins::web::fetch::fetch_event {
1113

1214
class FetchEvent final : public BuiltinNoConstructor<FetchEvent> {
@@ -57,7 +59,19 @@ class FetchEvent final : public BuiltinNoConstructor<FetchEvent> {
5759
static bool init_incoming_request(JSContext *cx, JS::HandleObject self,
5860
host_api::HttpIncomingRequest *req);
5961

60-
static bool respondWithError(JSContext *cx, JS::HandleObject self);
62+
/**
63+
* @brief Responds with an error that contains some text for the HTTP response body
64+
*
65+
* @param cx The Javascript context
66+
* @param self A handle to the `FetchEvent` object
67+
* @param body_text optional text to send as the body
68+
*
69+
* @return True if the response was sent successfully
70+
* @throws None directly, but surfaces errors to JS via `HANDLE_ERROR`
71+
*/
72+
static bool respondWithError(JSContext *cx,
73+
JS::HandleObject self,
74+
std::optional<std::string_view> body_text = std::nullopt);
6175
static bool is_active(JSObject *self);
6276

6377
static State state(JSObject *self);

0 commit comments

Comments
 (0)