Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/Writing/PostmanCollectionWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ protected function generateUrlObject(OutputEndpointData $endpointData): array
}
} else {
$query[] = [
'key' => urlencode($name),
'value' => $parameterData->example !== null ? urlencode($parameterData->example) : '',
'key' => $name,
'value' => $parameterData->example !== null ? (string) $parameterData->example : '',
'description' => strip_tags($parameterData->description),
// Default query params to disabled if they aren't required and have empty values
'disabled' => ! $parameterData->required && empty($parameterData->example),
Expand All @@ -329,9 +329,12 @@ protected function generateUrlObject(OutputEndpointData $endpointData): array

$base['query'] = $query;

// Create raw url-parameter (Insomnia uses this on import)
// Create raw url-parameter (Insomnia uses this on import).
// Per Postman Collection v2.1, query[].key/value are stored raw and the client
// encodes them when sending. The raw URL string still needs encoding to be a
// syntactically valid URL, so we only encode it here.
$queryString = collect($base['query'])->map(function ($queryParamData) {
return $queryParamData['key'].'='.$queryParamData['value'];
return rawurlencode($queryParamData['key']).'='.rawurlencode($queryParamData['value']);
})->implode('&');
$base['raw'] = sprintf('%s/%s%s', $base['host'], $base['path'], $queryString ? "?{$queryString}" : null);

Expand All @@ -344,7 +347,7 @@ protected function generateUrlObject(OutputEndpointData $endpointData): array
return [
'id' => $name,
'key' => $name,
'value' => urlencode($parameter->example),
'value' => $parameter->example,
'description' => $parameter->description,
];
})->values()->toArray();
Expand Down
4 changes: 2 additions & 2 deletions tests/Fixtures/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,12 @@
},
{
"key": "url_encoded",
"value": "%2B+%5B%5D%26%3D",
"value": "+ []&=",
"description": "Used for testing that URL parameters will be URL-encoded where needed.",
"disabled": false
}
],
"raw": "{{baseUrl}}/api/withQueryParameters?location_id=architecto&user_id=me&page=4&filters=architecto&url_encoded=%2B+%5B%5D%26%3D"
"raw": "{{baseUrl}}/api/withQueryParameters?location_id=architecto&user_id=me&page=4&filters=architecto&url_encoded=%2B%20%5B%5D%26%3D"
},
"method": "GET",
"header": [
Expand Down
58 changes: 58 additions & 0 deletions tests/Unit/PostmanCollectionWriterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,64 @@ public function query_parameters_are_disabled_with_no_value_when_not_required()
], $variableData);
}

/** @test */
public function query_parameter_keys_and_values_are_not_pre_url_encoded()
{
// Per Postman Collection v2.1 spec, query[].key/value are stored as raw strings
// and the Postman client encodes them when sending. Pre-encoding here causes
// a double-encode on send (e.g. `,` → `%2C` → `%252C` at the server).
$endpointData = $this->createMockEndpointData('fake/{id}');
$endpointData->urlParameters['id'] = new Parameter([
'name' => 'id',
'description' => '',
'required' => true,
'example' => 'foo bar',
]);
$endpointData->queryParameters = [
'include' => new Parameter([
'name' => 'include',
'type' => 'string',
'description' => 'Comma-separated relationships',
'required' => false,
'example' => 'customer,reward',
]),
'filter[email]' => new Parameter([
'name' => 'filter[email]',
'type' => 'string',
'description' => 'Filter',
'required' => false,
'example' => 'test@example.com',
]),
];
$endpointData->cleanQueryParameters = Extractor::cleanParams($endpointData->queryParameters);

$endpoints = $this->createMockEndpointGroup([$endpointData]);
$collection = $this->generate(endpoints: [$endpoints]);

$url = data_get($collection, 'item.0.item.0.request.url');

// Query objects keep raw values — Postman encodes on send.
$this->assertContains([
'key' => 'include',
'value' => 'customer,reward',
'description' => 'Comma-separated relationships',
'disabled' => false,
], $url['query']);
$this->assertContains([
'key' => 'filter[email]',
'value' => 'test@example.com',
'description' => 'Filter',
'disabled' => false,
], $url['query']);

// URL variables also stored raw.
$this->assertSame('foo bar', $url['variable'][0]['value']);

// Raw URL is encoded for HTTP validity.
$this->assertStringContainsString('include=customer%2Creward', $url['raw']);
$this->assertStringContainsString('filter%5Bemail%5D=test%40example.com', $url['raw']);
}

/** @test */
public function auth_info_is_added_correctly()
{
Expand Down