Skip to content

Comments

Fix WebSocket upgrade failure when using app.fetch with deno serve#710

Merged
kitsonk merged 3 commits intomainfrom
copilot/fix-websocket-upgrade-issue
Feb 22, 2026
Merged

Fix WebSocket upgrade failure when using app.fetch with deno serve#710
kitsonk merged 3 commits intomainfrom
copilot/fix-websocket-upgrade-issue

Conversation

Copy link
Contributor

Copilot AI commented Feb 22, 2026

context.upgrade() sets context.respond = false and resolves the internal NativeRequest#response promise with the Deno.upgradeWebSocket() response — but app.fetch (the Cloudflare/deno serve handler) ignored both, always calling context.response.toDomResponse() and returning a plain HTTP response instead of the upgrade response. Deno would then error with "Upgrade response was not returned from callback".

Changes

  • application.ts — In fetch, check context.respond === false after middleware and return contextRequest.response (already resolved with the WS upgrade response) instead of falling through to toDomResponse(). Mirrors the existing pattern in handle().
// Before: always called toDomResponse(), discarding the upgrade response
await this.#getComposed()(context);
const response = await context.response.toDomResponse(); // ❌ wrong for WS upgrades

// After
await this.#getComposed()(context);
if (context.respond === false) {
  context.response.destroy();
  return contextRequest.response; // ✅ returns Deno.upgradeWebSocket() response
}
const response = await context.response.toDomResponse();
  • application.test.ts — Integration test: starts a Deno.serve instance with app.fetch as the handler, connects a WebSocket client, and asserts successful bidirectional message exchange.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.deno.land
    • Triggering command: /usr/bin/curl curl -s REDACTED 53 -j ACCEPT (dns block)
    • Triggering command: /usr/bin/curl curl -s REDACTED (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Bug: deno serve causes websocket upgrade to fail</issue_title>
<issue_description>### Code:

// main.ts
import { Application, Router } from '@oak/oak';

const router = new Router();

router.get('/wss', (context) => {

  const socket = context.upgrade();
  socket.onmessage = (event) => {
    console.log(event.data);
    socket.send('Hello, WebSocket! [Server]');
  };
});

router.get('/', (context) => {
  context.response.body = `
    <h1>Hello, Oak!</h1>
    <script>
      const ws = new WebSocket('ws://localhost:8000/wss');
      ws.onopen = () => {
        console.log('WebSocket connection established!');
        ws.send('Hello, WebSocket!');
      };
      ws.onmessage = (event) => {
        console.log(event.data);
      };
    </script>
  `;
  context.response.type = 'text/html';
});

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

export default { fetch: app.fetch };

deno serve main.ts

Expected Result:

Success

Actual Result:

deno serve: Listening on http://0.0.0.0:8000/
Upgrade response was not returned from callback

Note:

This works correctly when using Hono and following their Deno instructions:

image
</issue_description>

<agent_instructions>As mentioned, oak has never really been tested with deno serve (https://docs.deno.com/runtime/reference/cli/serve/) but ultimately it should work. Please investigate the easiest way to test oak with deno serve as well as investigate what is mentioned in the issue in regards to websocket upgrades.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@kitsonk Thanks for the reproduction (and work around). I have never validated oak against a `deno serve` use case actually but need to do that.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: kitsonk <1282577+kitsonk@users.noreply.github.com>
@CLAassistant
Copy link

CLAassistant commented Feb 22, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ kitsonk
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI changed the title [WIP] Fix websocket upgrade failure during deno serve Fix WebSocket upgrade failure when using app.fetch with deno serve Feb 22, 2026
Copilot AI requested a review from kitsonk February 22, 2026 03:17
Copy link
Member

@kitsonk kitsonk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kitsonk kitsonk marked this pull request as ready for review February 22, 2026 08:52
@kitsonk kitsonk merged commit 185baef into main Feb 22, 2026
2 of 3 checks passed
@kitsonk kitsonk deleted the copilot/fix-websocket-upgrade-issue branch February 22, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: deno serve causes websocket upgrade to fail

3 participants