Skip to content

Commit

Permalink
fix: respond with 500 Internal Server Error when an unhandled error h…
Browse files Browse the repository at this point in the history
…as occured and no response has already been sent to the client
  • Loading branch information
JakeChampion committed Nov 2, 2022
1 parent 7c9648b commit e5982d8
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 3 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/main.yml
Expand Up @@ -244,6 +244,7 @@ jobs:
- e2e-async-select
- e2e-byte-repeater
- e2e-edge-dictionary
- e2e-error
- e2e-geoip
- e2e-hello-world
- e2e-object-store
Expand Down Expand Up @@ -419,6 +420,17 @@ jobs:
with:
fixture: 'edge-dictionary'
fastly-api-token: ${{ secrets.FASTLY_API_TOKEN }}
e2e-error:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v2
with:
submodules: false
- uses: ./.github/actions/e2e
with:
fixture: 'error'
fastly-api-token: ${{ secrets.FASTLY_API_TOKEN }}
e2e-geoip:
runs-on: ubuntu-latest
needs: [build]
Expand Down
16 changes: 13 additions & 3 deletions c-dependencies/js-compute-runtime/js-compute-runtime.cpp
Expand Up @@ -418,10 +418,11 @@ static void dispatch_fetch_event(JSContext *cx, HandleObject event, double *tota
handler.setObject(*(*FETCH_HANDLERS)[i]);
if (!JS_CallFunctionValue(cx, GLOBAL, handler, argsv, &rval)) {
DumpPendingException(cx, "dispatching FetchEvent\n");
JS_ClearPendingException(cx);
break;
}
if (FetchEvent::state(event) != FetchEvent::State::unhandled)
if (FetchEvent::state(event) != FetchEvent::State::unhandled) {
break;
}
}

FetchEvent::stop_dispatching(event);
Expand Down Expand Up @@ -528,8 +529,17 @@ int main(int argc, const char *argv[]) {

// Respond with status `500` if any promise rejections were left unhandled
// and no response was ever sent.
if (!FetchEvent::response_started(fetch_event))
if (!FetchEvent::response_started(fetch_event)) {
FetchEvent::respondWithError(cx, fetch_event);
}
}

// Respond with status `500` if an exception is pending
// and no response was ever sent.
if (JS_IsExceptionPending(cx)) {
if (!FetchEvent::response_started(fetch_event)) {
FetchEvent::respondWithError(cx, fetch_event);
}
}

auto end = system_clock::now();
Expand Down
38 changes: 38 additions & 0 deletions integration-tests/js-compute/fixtures/error/bin/index.js
@@ -0,0 +1,38 @@
/* global fastly */

addEventListener("fetch", ()=>{
console.log(1)
})

addEventListener("fetch", event => {
event.respondWith(app(event))
})

/**
* @param {FetchEvent} event
* @returns {Response}
*/
async function app(event) {
try {
const path = (new URL(event.request.url)).pathname;
console.log(`path: ${path}`)
console.log(`FASTLY_SERVICE_VERSION: ${fastly.env.get('FASTLY_SERVICE_VERSION')}`)
if (routes.has(path)) {
const routeHandler = routes.get(path);
return await routeHandler()
}
return fail(`${path} endpoint does not exist`)
} catch (error) {
return fail(`The routeHandler threw an error: ${error.message}` + '\n' + error.stack)
}
}

const routes = new Map();
routes.set('/', () => {
routes.delete('/');
let test_routes = Array.from(routes.keys())
return new Response(JSON.stringify(test_routes), { 'headers': { 'content-type': 'application/json' } });
});
routes.set("/error", async () => {
throw new Error('uh oh')
});
13 changes: 13 additions & 0 deletions integration-tests/js-compute/fixtures/error/fastly.toml.in
@@ -0,0 +1,13 @@
# This file describes a Fastly Compute@Edge package. To learn more visit:
# https://developer.fastly.com/reference/fastly-toml/

authors = ["jchampion@fastly.com"]
description = ""
language = "other"
manifest_version = 2
name = "empty"
service_id = ""

[scripts]
build = "../../../../target/release/js-compute-runtime"

12 changes: 12 additions & 0 deletions integration-tests/js-compute/fixtures/error/tests.json
@@ -0,0 +1,12 @@
{
"GET /error": {
"environments": ["viceroy", "c@e"],
"downstream_request": {
"method": "GET",
"pathname": "/error"
},
"downstream_response": {
"status": 500
}
}
}

0 comments on commit e5982d8

Please sign in to comment.