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 parameter that is a union of string and string array is incorrectly parsed #1028

Open
harveylee opened this issue Jan 25, 2025 · 3 comments
Labels
bug Something isn't working

Comments

@harveylee
Copy link

What version of Elysia is running?

1.2.10

What platform is your computer?

Linux 5.15.153.1-microsoft-standard-WSL2 x86_64 unknown

What steps can reproduce the bug?

import { treaty } from '@elysiajs/eden'
import { describe, expect, it } from 'bun:test'
import { Elysia, t } from 'elysia'

describe('Failing: string array or string query', async () => {
    const server = new Elysia()
      .get('/query', async ({ query: { tags } }) => {
        console.log(tags) // outputs 'a'
        return { tags }
      }, {
        query: t.Partial(t.Object({
          tags: t.Union([t.Array(t.String()), t.String()]), // string[] | string
        })),
      })
    const api = treaty(server)

    it('query: string array', async () => {
      const res = await api.query.get({ query: { tags: ['a', 'b', 'c'] } })
      if (res.error) throw res.error
      expect(res.data.tags).toEqual(['a', 'b', 'c'])
    }) // instead, res.data.tags === 'a'
})

What is the expected behavior?

query.tags is parsed as ['a', 'b', 'c'] (i.e. an array)

What do you see instead?

query.tags is parsed as 'a' (i.e. just the first value)

Additional information

No response

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

No

@harveylee harveylee added the bug Something isn't working label Jan 25, 2025
@hisamafahri
Copy link
Contributor

My suspicion is that there's a different behavior if you call:

  1. http://localhost:3000/?tags=a&tags=b&&tags=c, and
  2. http://localhost:3000/?tags=a,b,c

I think the "problem" here that if you query it with the first approach, the query function params in the ({ query: { tags } }) => {} will only return the first value.

(note: looks like api.query.get({ query: { tags: ['a', 'b', 'c'] } }) do it in the first approach).

For now, you can either parse it manually (via the request.url) or use the 2nd pattern.

@harveylee
Copy link
Author

harveylee commented Jan 27, 2025

More info:
The issue has to do with the tags: t.Union([t.Array(t.String()), t.String()]) in the query schema. The query parameter is correctly parsed as the full array if the query schema specifies tags: t.Array(t.String()) - but then you can't pass a single string (acceptable workaround in my use case, but perhaps an unnecessary limitation).

@hisamafahri I couldn't find any straightforward way to get Eden Treaty to format query array parameters as a comma-separated list - do you know if there's a way? I saw elysiajs/eden#127 which would help.

But in any case, doesn't seem like Elysia recognises a comma-separated list out of the box:

it('query: string array, non-exploded', async () => {
  server.listen(3099)
  const res = await fetch('http://localhost:3099/query?tags=a,b,c')
  const data = await res.json()
  expect(data.tags).toEqual(['a', 'b', 'c'])
})

...also fails (Elysia parses tags as a single string: 'a,b,c')

@hisamafahri
Copy link
Contributor

hisamafahri commented Jan 28, 2025

to get Eden Treaty to format query array parameters as a comma-separated list

You can do this:

await api.query.get({ query: { tags: ['a', 'b', 'c'].join(",") } })

But in any case, doesn't seem like Elysia recognises a comma-separated list out of the box

Yes, that one is entering an area of debate whether a framework should handle that or not. It's a matter of preference.

But, either way, one of the "hacky" way is by manually parse the request url:

.get('/', async ({ request }) => {
    const url = new URL(request.url)
    const tags = url.searchParams.get('tags')?.split(',')
    return { tags }
  })

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

2 participants