{"action":"created","issue":{"url":"https://api.github.com/repos/php-fig/fig-standards/issues/515","labels_url":"https://api.github.com/repos/php-fig/fig-standards/issues/515/labels{/name}","comments_url":"https://api.github.com/repos/php-fig/fig-standards/issues/515/comments","events_url":"https://api.github.com/repos/php-fig/fig-standards/issues/515/events","html_url":"https://github.com/php-fig/fig-standards/issues/515","id":68063111,"number":515,"title":"Sending requests with query/request params, cookies and files","user":{"login":"webmozart","id":176399,"avatar_url":"https://avatars.githubusercontent.com/u/176399?v=3","gravatar_id":"","url":"https://api.github.com/users/webmozart","html_url":"https://github.com/webmozart","followers_url":"https://api.github.com/users/webmozart/followers","following_url":"https://api.github.com/users/webmozart/following{/other_user}","gists_url":"https://api.github.com/users/webmozart/gists{/gist_id}","starred_url":"https://api.github.com/users/webmozart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/webmozart/subscriptions","organizations_url":"https://api.github.com/users/webmozart/orgs","repos_url":"https://api.github.com/users/webmozart/repos","events_url":"https://api.github.com/users/webmozart/events{/privacy}","received_events_url":"https://api.github.com/users/webmozart/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2015-04-13T10:24:23Z","updated_at":"2015-04-13T18:41:36Z","closed_at":null,"body":"Consider you are building some sort of library that takes a PSR-7 request, adds a query parameter and a file to the request and finally sends the request with an HTTP client such as Guzzle:\r\n\r\n```php\r\n$queryParams = array_replace($request->getQueryParams(), array('is_upload' => '1'));\r\n\r\n$request = $request->withQueryParams($queryParams)\r\n    ->withUploadedFiles(array('file' => new File('/path/to/file'));\r\n\r\n$client->send($request);\r\n```\r\n\r\nThe above cannot be implemented at the moment, since `withQueryParams()` et al. don't exist in `RequestInterface`, only in `ServerRequestInterface`, which states:\r\n\r\n> Representation of an incoming, server-side HTTP request.\r\n\r\nHence `ServerRequestInterface` is not appropriate for modeling client side requests.\r\n\r\nI think that we should move the following methods to `RequestInterface` in order to facilitate building of requests on the client side:\r\n\r\n* `*CookieParams()`\r\n* `*QueryParams()`\r\n* `*ParsedBody()`\r\n* `*UploadedFiles()`\r\n\r\nDoing this exposes a further weakness: `withParsedBody()` cannot be used on the client, as the PSR currently does not expect implementations to update the stream returned by `getBody()` when `withParsedBody()` is called. However, that's probably a separate issue."},"comment":{"url":"https://api.github.com/repos/php-fig/fig-standards/issues/comments/92456435","html_url":"https://github.com/php-fig/fig-standards/issues/515#issuecomment-92456435","issue_url":"https://api.github.com/repos/php-fig/fig-standards/issues/515","id":92456435,"user":{"login":"mtdowling","id":190930,"avatar_url":"https://avatars.githubusercontent.com/u/190930?v=3","gravatar_id":"","url":"https://api.github.com/users/mtdowling","html_url":"https://github.com/mtdowling","followers_url":"https://api.github.com/users/mtdowling/followers","following_url":"https://api.github.com/users/mtdowling/following{/other_user}","gists_url":"https://api.github.com/users/mtdowling/gists{/gist_id}","starred_url":"https://api.github.com/users/mtdowling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mtdowling/subscriptions","organizations_url":"https://api.github.com/users/mtdowling/orgs","repos_url":"https://api.github.com/users/mtdowling/repos","events_url":"https://api.github.com/users/mtdowling/events{/privacy}","received_events_url":"https://api.github.com/users/mtdowling/received_events","type":"User","site_admin":false},"created_at":"2015-04-13T18:41:36Z","updated_at":"2015-04-13T18:41:36Z","body":"Sure. Here's an example of [query string handling](https://github.com/guzzle/psr7/blob/master/src/Uri.php#L235) from the [tests](https://github.com/guzzle/psr7/blob/master/tests/UriTest.php#L159):\r\n\r\n```php\r\n$uri = new Uri('http://foo.com/bar');\r\n$uri = Uri::withQueryValue($uri, 'a', 'b');\r\n$uri = Uri::withQueryValue($uri, 'c', 'd');\r\n$uri = Uri::withQueryValue($uri, 'e', null);\r\n$this->assertEquals('a=b&c=d&e', $uri->getQuery());\r\n\r\n$uri = Uri::withoutQueryValue($uri, 'c');\r\n$uri = Uri::withoutQueryValue($uri, 'e');\r\n$this->assertEquals('a=b', $uri->getQuery());\r\n$uri = Uri::withoutQueryValue($uri, 'a');\r\n$uri = Uri::withoutQueryValue($uri, 'a');\r\n$this->assertEquals('', $uri->getQuery());\r\n```\r\n\r\nApplication specific middlewares that might be modifying the query string or request body parameters multiple times could potentially pass around an application specific context to prevent the need to parse the query string between each middleware.\r\n\r\nIn practice in the SDK, we typically build up the query string and serialize it before associating it with a request: https://github.com/aws/aws-sdk-php/blob/abstract-http/src/Api/Serializer/QuerySerializer.php\r\n\r\nIn some cases, we're given a request that may have application/x-www-form-urlencoded parameters in the body. In this case, we parse the body to modify the parameters: https://github.com/aws/aws-sdk-php/blob/abstract-http/src/Signature/SignatureV2.php#L18\r\n\r\nFor super performance critical things with lots of mutations, we build up a request using a mutable representation and then serialize it as a PSR-7 request: https://github.com/aws/aws-sdk-php/blob/abstract-http/src/Signature/SignatureV4.php#L77\r\n\r\nOne thing that we don't want to do is couple our HTTP message abstractions with PHP specific assumptions. For example, some APIs allow query string values to be represented using the same key multiple times (i.e., \"foo=1&foo=2\"). How would we differentiate repeated key serialization from PHP style serialization (i.e., \"foo[0]=1&foo[1]=2\") or languages that represent this as \"foo[]=1&foo[]=2\" without overly-complicating the spec? I also think abstractions on the message for specific stream serializations is a code smell as well. Why have \"form\" related methods when we don't have JSON, XML, Yaml, ... etc... methods? (to be clear, I am not suggesting we add these methods)"}}