Commit Graph

14 Commits

Author SHA1 Message Date
Claude Bot
485017f93f fix: correct route registration order for WebSocket handlers
The key issue was understanding how uWebSockets handles WebSocket routes:

When app.ws() is called, it internally registers a GET handler that:
1. Checks for WebSocket upgrade headers (sec-websocket-key)
2. If present → handles WebSocket upgrade via the upgrade callback
3. If absent → calls req->setYield(true) to pass to next handler

This means app.ws() must be registered BEFORE app.method(.GET) for the
same path, so that:
- WebSocket requests → handled by app.ws()
- Regular GET requests → yield and fall through to GET handler

Changes:
- Register upgrade handler FIRST in user_routes_to_build (before method handlers)
- This ensures correct registration order in server.zig
- Removed websocket_only enum variant (not needed with correct ordering)
- Updated test to expect error on server creation (not connection time)
- Validate that route websocket requires upgrade handler

All 8 tests now passing:
✓ route-specific websocket handlers work independently
✓ route-specific websocket with data in upgrade
✓ route-specific websocket with close handler
✓ global websocket handler still works
✓ mix of route-specific and global websocket handlers
✓ route-specific websocket with multiple HTTP methods
✓ route-specific websocket without upgrade handler errors
✓ server.reload() preserves route-specific websocket handlers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 02:56:39 +00:00
Claude Bot
c25c0ab84e feat: add route-specific WebSocket handlers in Bun.serve()
Implements support for per-route WebSocket handlers in Bun.serve() routes.
Routes can now specify their own websocket configuration:

```js
Bun.serve({
  routes: {
    "/api/v1/chat": {
      websocket: {
        open(ws) { ws.send("chat:welcome"); },
        message(ws, data) { ws.send("chat:" + data); },
      },
      upgrade(req, server) {
        return server.upgrade(req);
      },
    },
    "/api/v2/notifications": {
      websocket: {
        open(ws) { ws.send("notif:connected"); },
        message(ws, data) { ws.send("notif:" + data); },
      },
      upgrade(req, server) {
        return server.upgrade(req);
      },
    },
  },
});
```

Implementation details:
- Added route_websocket_contexts ArrayList to server to store per-route WebSocket contexts
- WebSocket routes use id >= 2 (id - 2 = index in route_websocket_contexts array)
- id == 1 continues to mean global WebSocket handler
- id == 0 continues to mean fallback route
- Updated route parsing in ServerConfig to extract websocket field from route objects
- Modified onUpgrade() to select correct WebSocket handler based on route context index
- Properly handles server.reload() by rebuilding route WebSocket contexts
- Global websocket handler continues to work alongside route-specific handlers

Tests cover:
- Independent route-specific WebSocket handlers
- WebSocket upgrade with custom data
- Close handlers
- Mix of global and route-specific handlers
- server.reload() preservation
- 7/8 tests passing (one test with multiple HTTP methods needs investigation)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 02:24:16 +00:00
taylor.fish
7bf67e78d7 Fix incorrect/suspicious uses of ZigString.Slice.cloneIfNeeded (#23937)
`ZigString.Slice.cloneIfNeeded` does *not* guarantee that the returned
slice will have been allocated by the provided allocator, which makes it
very easy to use this method incorrectly.

(For internal tracking: fixes ENG-21284)
2025-10-23 13:17:51 -07:00
taylor.fish
f14f3b03bb Add new bindings generator; port SSLConfig (#23169)
Add a new generator for JS → Zig bindings. The bulk of the conversion is
done in C++, after which the data is transformed into an FFI-safe
representation, passed to Zig, and then finally transformed into
idiomatic Zig types.

In its current form, the new bindings generator supports:

* Signed and unsigned integers
* Floats (plus a “finite” variant that disallows NaN and infinities)
* Strings
* ArrayBuffer (accepts ArrayBuffer, TypedArray, or DataView)
* Blob
* Optional types
* Nullable types (allows null, whereas Optional only allows undefined)
* Arrays
* User-defined string enumerations
* User-defined unions (fields can optionally be named to provide a
better experience in Zig)
* Null and undefined, for use in unions (can more efficiently represent
optional/nullable unions than wrapping a union in an optional)
* User-defined dictionaries (arbitrary key-value pairs; expects a JS
object and parses it into a struct)
* Default values for dictionary members
* Alternative names for dictionary members (e.g., to support both
`serverName` and `servername` without taking up twice the space)
* Descriptive error messages
* Automatic `fromJS` functions in Zig for dictionaries
* Automatic `deinit` functions for the generated Zig types

Although this bindings generator has many features not present in
`bindgen.ts`, it does not yet implement all of `bindgen.ts`'s
functionality, so for the time being, it has been named `bindgenv2`, and
its configuration is specified in `.bindv2.ts` files. Once all
`bindgen.ts`'s functionality has been incorporated, it will be renamed.

This PR ports `SSLConfig` to use the new bindings generator; see
`SSLConfig.bindv2.ts`.

(For internal tracking: fixes STAB-1319, STAB-1322, STAB-1323,
STAB-1324)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Alistair Smith <hi@alistair.sh>
2025-10-03 17:10:28 -07:00
taylor.fish
edf13bd91d Refactor BabyList (#22502)
(For internal tracking: fixes STAB-1129, STAB-1145, STAB-1146,
STAB-1150, STAB-1126, STAB-1147, STAB-1148, STAB-1149, STAB-1158)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-09-09 20:41:10 -07:00
taylor.fish
437e15bae5 Replace catch bun.outOfMemory() with safer alternatives (#22141)
Replace `catch bun.outOfMemory()`, which can accidentally catch
non-OOM-related errors, with either `bun.handleOom` or a manual `catch
|err| switch (err)`.

(For internal tracking: fixes STAB-1070)

---------

Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-08-26 12:50:25 -07:00
robobun
dd7a639a6f fix(serve): correct TLS array validation for SNI (#21796)
## Summary

Fixes a prerequisite issue in #21792 where `Bun.serve()` incorrectly
rejected TLS arrays with exactly 1 object.

The original issue reports a WebSocket crash with multiple TLS configs,
but users first encounter this validation bug that prevents
single-element TLS arrays from working at all.

## Root Cause

The bug was in `ServerConfig.zig:918` where the condition checked for
exactly 1 element and threw an error:

```zig
if (value_iter.len == 1) {
    return global.throwInvalidArguments("tls option expects at least 1 tls object", .{});
}
```

This prevented users from using the syntax: `tls: [{ cert, key,
serverName }]`

## Fix

Updated the validation logic to:
- Empty TLS arrays are ignored (treated as no TLS)  
- Single-element TLS arrays work correctly for SNI
- Multi-element TLS arrays continue to work as before

```zig
if (value_iter.len == 0) {
    // Empty TLS array means no TLS - this is valid
} else {
    // Process the TLS configs...
}
```

## Testing

-  All existing SSL tests still pass (16/16)
-  New comprehensive regression test with 7 test cases 
-  Tests cover empty arrays, single configs, multiple configs, and
error cases

## Note

This fix addresses the validation issue that prevents users from
reaching the deeper WebSocket SNI crash mentioned in #21792. The crash
itself may require additional investigation, but this fix resolves the
immediate blocker that users encounter first.

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-08-15 21:25:54 -07:00
taylor.fish
07cd45deae Refactor Zig imports and file structure (part 1) (#21270)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-07-22 17:51:38 -07:00
pfg
83760fc446 Sort imports in all files (#21119)
Co-authored-by: taylor.fish <contact@taylor.fish>
2025-07-21 13:26:47 -07:00
Jarred Sumner
55a9cccac0 bun.sh -> bun.com (#20909) 2025-07-10 00:10:43 -07:00
Meghan Denny
f9712ce309 make node:buffer,zlib,stream,fs exception checker clear (#20494) 2025-06-25 18:36:08 -07:00
Jarred Sumner
633f4f593d Ahead-of-time frontend bundling support for HTML imports & bun build (#20511)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-06-20 19:55:52 -07:00
190n
346e97dde2 fix bugs found by exception scope verification (#20285)
Co-authored-by: 190n <7763597+190n@users.noreply.github.com>
2025-06-18 23:08:19 -07:00
Jarred Sumner
d9cf836b67 Split server.zig into more files (#20139)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-06-03 01:38:26 -07:00