Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

http_build_query function's excessive urlencoding

Why when building a query string with http_build_query function, it urlencodes square brackets [] outside values and how do get rid of it?

$query = array("var" => array("foo" => "value", "bar" => "encodedBracket["));
$queryString = http_build_query($query, "", "&");
var_dump($queryString);
var_dump("urldecoded: " . urldecode($queryString));

outputs:

var%5Bfoo%5D=value&var%5Bbar%5D=encodedBracket%5B
urldecoded: var[foo]=value&var[bar]=encodedBracket[

The function correctly urlencoded a [ in encodedBracket[ in the first line of the output but what was the reason to encode square brackets in var[foo]= and var[bar]=? As you can see, urldecoding the string also decoded reserved characters in values, encodedBracket%5B should have stayed as was for the query string to be correct and not become encodedBracket[.

According to section 2.2 Reserved Characters of Uniform Resource Identifier (URI): Generic Syntax

URIs include components and subcomponents that are delimited by characters in the "reserved" set. These characters are called "reserved" because they may (or may not) be defined as delimiters by the generic syntax, by each scheme-specific syntax, or by the implementation-specific syntax of a URI's dereferencing algorithm. If data for a URI component would conflict with a reserved character's purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed.

reserved = gen-delims / sub-delims

gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

So shouldn't http_build_query really produce more readable output with characters like [] urlencoded only where it's required? How do I make it produce such output?

like image 908
Desmond Hume Avatar asked Jan 10 '14 14:01

Desmond Hume


People also ask

What does Http_build_query do in PHP?

The http_build_query() function is an inbuilt function in PHP which is used to generate URL-encoded query string from the associative (or indexed) array.

Are brackets allowed in URLs?

That means do not use commas, brackets or other non-standard URL encoding in your URL structure.

How do you put square brackets in URL?

Making links with square bracket tags The simplest example is to surround the url (which should start with https://) with square brackets. For example, [http://google.com] will make a link like this: http://google.com.

What is a query string in PHP?

A query string is a part of a uniform resource locator (URL) that assigns values to specified parameters.


1 Answers

Here's a quick function I wrote to produce nicer query strings. It not only doesn't encode square brackets but will also omit the array key if it matches the index. Note it doesn't support objects or the additional options of http_build_query. The $prefix argument is used for recursion and should be omitted for the initial call.

function http_clean_query(array $query_data, string $prefix=null): string {
    $parts = [];
    $i = 0;
    foreach ($query_data as $key=>$value) {
        if ($prefix === null) {
            $key = rawurlencode($key);
        } else if ($key === $i) {
            $key = $prefix.'[]';
            $i++;
        } else {
            $key = $prefix.'['.rawurlencode($key).']';
        }
        if (is_array($value)) {
            if (!empty($value)) $parts[] = http_clean_query($value, $key);
        } else {
            $parts[] = $key.'='.rawurlencode($value);
        }
    }
    return implode('&', $parts);
}
like image 151
Gannet Avatar answered Nov 04 '22 18:11

Gannet