Skip to content

Support repeated and ordered query and form parameters #119

Description

@ZilvinasKucinskas

Priority: P1

Describe the issue

The query: and URL-encoded form: options currently accept only a map whose values are scalar booleans, platform-sized integers, floats, or strings. They reject both common Ruby representations of repeated fields:

  • a hash with an array value; and
  • an enumerable of key-value pairs.

Repeated keys are ordinary HTTP API input (tag=a&tag=b, facets, filters, and multi-select fields). An ordered pair list is also needed when duplicate keys or exact field order must be preserved.

Reproduction

Tested with wreq 1.2.4:

require "wreq"

client = Wreq::Client.new

client.get("https://example.com", query: {tag: %w[ruby http]})
# RuntimeError: data did not match any variant of untagged enum ParamValue

client.get(
  "https://example.com",
  query: [["tag", "ruby"], ["tag", "http"]]
)
# TypeError: expected a map, got sequence

client.get("https://example.com", query: {id: 2**63})
# RangeError: bignum too big to convert into `long long'

The equivalent shapes fail for form: as well.

Proposed Ruby API

Keep query: and form: for compatibility, but accept the same two shapes as Ruby's URL-encoding APIs:

client.get(
  "https://example.com/search",
  query: {tag: %w[ruby http], page: 2}
)
# GET /search?tag=ruby&tag=http&page=2

client.post(
  "https://example.com/search",
  form: [
    [:tag, "ruby"],
    [:tag, "http"],
    [:page, 2]
  ]
)
# body: tag=ruby&tag=http&page=2

Encoding semantics

  • Hash array values expand to one field per element.
  • Enumerable pairs preserve input order and duplicate keys.
  • String and Symbol keys are accepted and encoded by their string value.
  • Scalar String, Symbol, Integer, Float, boolean, and nil values follow documented URI.encode_www_form-compatible conversion. Ruby Integers are stringified without narrowing to the native platform integer range.
  • Invalid pair shapes raise ArgumentError before network I/O.
  • This issue covers application/x-www-form-urlencoded data only. Multipart file uploads remain tracked by #86.

Acceptance criteria

  • Both options accept a Hash and an enumerable of pairs.
  • Duplicate keys reach the wire without being collapsed.
  • Pair order is stable.
  • Hash array values produce repeated fields.
  • Existing scalar hashes remain backward compatible.
  • Tests cover spaces, Unicode, reserved characters, blank strings, nil, booleans, arbitrary-precision Integers, duplicate keys, array values, and invalid entries for both query and form encoding.

Ruby ecosystem precedent

  • Ruby's URI.encode_www_form accepts any enumerable, accepts hashes, expands array values into repeated keys, and preserves enumerable order.
  • HTTPX::Request accepts hashes or arrays of key-value pairs for query and form parameters.
  • Net::HTTPHeader#set_form accepts hash and pair-list form data.
  • wreq-python accepts mappings or ordered sequences of pairs for query and form input over the same Rust client. Ruby array-value expansion remains a Ruby-specific URI.encode_www_form convention.

Relevant wreq-ruby source

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions