Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query string parsing error when key specified multiple times and value contains non-ASCII characters 🤔 #929

Open
lehnerpat opened this issue Dec 2, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@lehnerpat
Copy link

lehnerpat commented Dec 2, 2024

What version of Elysia is running?

1.1.25

What platform is your computer?

Darwin 24.1.0 x86_64 i386

What steps can reproduce the bug?

I'm observing an error in Elysia's processing of the query string in a certain combination of a key occurring multiple times in a query string (for multi-valued query parameters) and values containing non-ASCII characters (e.g. Japanese characters which the browser percent-escapes).

Here's a repro example that is as small as I could get it: https://github.com/lehnerpat/elysia-qs-bug-repro

Essentially, it is:

const app = new Elysia()
  .onRequest(({ request }) => {
    console.log("request url:", request.url);
  })
  .get("/", () => "ok", {
    query: t.Object({
      key1: t.Union([t.Array(t.String()), t.String()]),
    }),
  })
  .listen(3000);
  1. Clone the repo above, and bun install it
  2. bun run dev
  3. In a browser, open http://localhost:3000/?key1=ab&key1=cd&z=が (the last character should automatically be escaped by the browser to http://localhost:3000/?key1=ab&key1=cd&z=%E3%81%8C)

What is the expected behavior?

Elysia should parse the query string correctly, resulting in a parsed query object like { key1: ["ab"] } (since Elysia does not support multi-valued query parameters by default, it should ignore additional occurrences of key1)

What do you see instead?

An error response saying:

null is not an object (evaluating 'value.charCodeAt')

Additional information

From my experiments, the issue is triggered by the same key appearing at least twice, and then another parameter containing non-ASCII characters in its value.

Note that the third query parameter is not even defined in the query schema (which is t.Object({ key1: t.Union([t.Array(t.String()), t.String()]) })).

The following similar URLs do work:

  • http://localhost:3000/?key1=ab&z=が (key1 not repeated)
  • http://localhost:3000/?key1=ab&key1=cd&z=x (third parameter value only ASCII characters)
  • http://localhost:3000/?z=が&key1=ab&key1=cd (non-ASCII value before repeated key)
  • http://localhost:3000/?key1=で&key1=が&z=x (non-ASCII characters in other positions)

The failing example also works when the schema of key1 is defined as just t.String() or just t.Array(t.String()) instead.


In my actual setup, I somehow got additional logging output like this:

168 |                                                                                                           deepMemory = url.indexOf('&', start)
169 | 
170 |                                                                                                   let value
171 |                                                                                                   if(deepMemory === -1) value = decodeURIComponent(url.slice(start).replace(/\+/g, ' '))
172 |                                                                                                   else value = decodeURIComponent(url.slice(start, deepMemory).replace(/\+/g, ' '))
173 |                                                                                                   const vStart = value.charCodeAt(0)
                                       ^
TypeError: null is not an object (evaluating 'value.charCodeAt')

Which leads me to conclude the error occurs here:

elysia/src/compose.ts

Lines 815 to 820 in 0240b5a

let value
if(deepMemory === -1) value = decodeURIComponent(url.slice(start).replace(/\\+/g, ' '))
else value = decodeURIComponent(url.slice(start, deepMemory).replace(/\\+/g, ' '))
const vStart = value.charCodeAt(0)
const vEnd = value.charCodeAt(value.length - 1)

I wasn't able to reproduce the same error output in my MWE, unfortunately 🙇


Another note regarding my use case: I currently have to handle optional multi-valued query parameters (i.e. parameter schema like t.Optional(t.Union([t.Array(t.String()), t.String()]))), so I'm using the qs method suggested #344 (comment) to do additional parsing. However, as the MWE shows, this doesn't seem to be related to custom query string processing.

Since I'm not expecting Elysia to handle this multi-valued parameter case, I'd be happy if there were some way to turn off/skip Elysia's parsing of the query string 😅


Thank you for all your great work on Elysia! :bow

Have you try removing the node_modules and bun.lockb and try again yet?

No response

@lehnerpat lehnerpat added the bug Something isn't working label Dec 2, 2024
SaltyAom added a commit that referenced this issue Dec 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant