Skip to content

HTTP Server: Request body and query parameter parsing issues in JavaScript #1693

@akapug

Description

@akapug

Context

I'm building a Mastodon-compatible ActivityPub server (Kowloon) using Elide's HTTP server API, with a web frontend (Phanpy) that needs to interact via OAuth 2.0 and REST APIs. The application needs to:

  1. Parse URL-encoded form data from POST request bodies (OAuth app registration)
  2. Parse query parameters from GET requests (OAuth authorization flow)
  3. Maintain state across requests (in-memory Maps for registered apps, tokens, etc.)

Issues Encountered

1. Request Body Parsing

Problem: request.body returns a ReadableByteStream object instead of a string or parsed data.

Code:

router.handle("POST", "/api/v1/apps", (request, response) => {
  console.log("Request body type:", typeof request.body);
  console.log("Request body:", request.body);
  // Output:
  // Request body type: object
  // Request body: elide.runtime.gvm.internals.intrinsics.js.webstreams.ReadableByteStream@7f297125
});

Expected: Either:

  • A string containing the raw body data
  • A parsed object for common content types (application/x-www-form-urlencoded, application/json)
  • Documentation on how to read from the ReadableByteStream

Current workaround: Unable to parse POST body data, so using hardcoded default values.

2. Query Parameter Parsing

Problem: request.uri and request.url contain Kotlin object representations instead of plain strings with query parameters.

Code:

router.handle("GET", "/oauth/authorize", (request, response) => {
  console.log("request.uri:", request.uri);
  console.log("request.url:", request.url);
  // Output:
  // request.uri: http://localhost:3000/oauth/authorize?DefaultUrlParams(pairs=kotlin.sequences.TransformingSequence@454738da)
  // request.url: http://localhost:3000/oauth/authorize?DefaultUrlParams(pairs=kotlin.sequences.TransformingSequence@454738da)
});

Expected: Either:

  • Plain string URLs like http://localhost:3000/oauth/authorize?client_id=abc&redirect_uri=xyz
  • A request.query or request.params object with parsed parameters
  • Access to the underlying Kotlin DefaultUrlParams object to extract parameters

Current workaround: Auto-approving all OAuth requests without validating client_id or other parameters.

3. State Persistence Between Requests

Problem: Global Maps defined at module scope appear to be cleared between requests.

Code:

// At top of file
const registeredApps = new Map();

// In one handler
router.handle("POST", "/api/v1/apps", (request, response) => {
  const clientId = generateRandomString(32);
  const app = { /* ... */ };
  registeredApps.set(clientId, app);
  console.log("Registered app with client_id:", clientId);
  console.log("registeredApps size after set:", registeredApps.size);
  // Output: registeredApps size after set: 1
});

// In another handler (different request)
router.handle("GET", "/oauth/authorize", (request, response) => {
  console.log("registeredApps size:", registeredApps.size);
  // Output: registeredApps size: 0
});

Expected: Module-level variables should persist across requests within the same server instance.

Question: Is this expected behavior? Should state be stored differently in Elide HTTP servers?

Environment

  • Elide version: 1.0.0-beta10-rc5
  • Runtime: GraalVM
  • Platform: Docker (Ubuntu 24.04 base image)
  • Installation: curl -sSL --tlsv1.2 https://elide.sh | bash -s - --yes --install-rev=1.0.0-beta10-rc5

Questions

  1. Request Body: How should we read from ReadableByteStream? Is there documentation or examples?
  2. Query Parameters: Is there a way to access parsed query parameters, or extract them from the Kotlin object?
  3. State Persistence: Is module-level state expected to work, or should we use a different approach?

Possible Solutions

If these are limitations rather than bugs:

  1. Request Body: Provide a helper method like request.body.text() or request.body.json() similar to Fetch API
  2. Query Parameters: Add request.query object with parsed parameters, or expose the Kotlin Params object to JavaScript
  3. State: Document the expected lifecycle and provide guidance on state management

Repository

Full code available at: https://github.com/akapug/kowloon-elide

Thank you for any guidance or fixes!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions