Previous: Segments Up: URLs Home: Next: Normalization

Params

While the query is specified as a plain string, it is usually interpreted as a set of key-value pairs commonly referred to as URL Parameters, although here we use the term query parameters or params for short. There is no official, standard specification of the query parameters format, but the W3C recommendations and HTML 5 have this to say:

  • The query string is composed of a series of key-value pairs.

  • Within each pair, the field name and value are separated by an equals sign, "=".

  • The series of pairs is separated by the ampersand, "&".

  • Most web frameworks allow multiple values to have the same key.

  • Key comparisons are usually case-sensitive, but the receiving authority is ultimately responsible for deciding this.

This URL has two query parameters, first and last whose values are "John" and "Doe" respectively:

https://www.example.com?first=John&last=Doe

Like the path, the library permits access to the params as using these separate, bidirectional view types which reference the underlying URL:

Type Accessor Description

params_view

params

A read-only range of decoded params.

params_ref

params

A modifiable range of decoded params.

params_encoded_view

encoded_params

A read-only range of params.

params_encoded_ref

encoded_params

A modifiable range of params.

A param always has a key, even if it is the empty string. The value is optional; an empty string is distinct from no value. To represent individual params the library uses these types, distinguished by their ownership model and whether or not percent-escapes are possible:

Type String Type Description

param

std::string

A key-value pair with ownership of the strings. This can be used to hold decoded strings, or to allow the caller to take ownership of a param by making a copy.

param_view

string_view

A key-value pair without percent-escapes, referencing externally managed character buffers.

param_pct_view

pct_string_view

A key-value pair which may contain percent-escapes, referencing externally managed character buffers.

Param types can be constructed from initializer lists, allowing for convenient notation. To represent a missing value, the constant no_value or nullptr may be used. This table shows some examples of initializer lists used to construct a param type, and the resulting data members:

Statement qp.key qp.value qp.has_value

cpp:param qp = { "first", "John" };[]

"First"

"John"

true

cpp:param qp = { "first", "" };[]

undefined["First"]

""

true

cpp:param qp = { "first", no_value };[]

undefined["First"]

undefined[""]

false

cpp:param qp = { "", "Doe" };[]

undefined[""]

"Doe"

true

To understand the relationship between the query and the resulting range of params, first we define this function parms which returns a list of params corresponding to the elements in a container of params:

auto parms( core::string_view s ) -> std::list< param >
{
    url_view u( s );
    std::list< param > seq;
    for( auto qp : u.params() )
        seq.push_back( qp );
    return seq;
}

In the table below we show the result of invoking parms with different queries. This demonstrates how the syntax of the query maps to the parameter structure:

s cpp:parms( s )[]

"?first=John&last=Doe"

cpp:{ { "first", "John" }, { "last", "Doe" } }[]

"?id=42&unsorted"

cpp:{ { "id", "42" }, { "last", no_value } }[]

"?col=cust&row="

cpp:{ { "col", "cust" }, { "row", "" } }[]

"?justify=left&"

cpp:{ { "justify", "left" }, { "", no_value } }[]

undefined["?"]

cpp:{ { "", no_value } }[]

undefined[""]

cpp:{ }[]

It may be surprising that an empty query string ("?") produces a sequence with one empty param. This is by design, otherwise the sequence would not be distinguishable from the case where there is no query string (last two rows of the table above).

For complete details on containers used to represent query strings as params please view the reference.