4 * This file is part of the Goutte package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
14 use GuzzleHttp\Client as GuzzleClient;
15 use GuzzleHttp\ClientInterface as GuzzleClientInterface;
16 use GuzzleHttp\Cookie\CookieJar;
17 use GuzzleHttp\Exception\RequestException;
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\UriInterface;
20 use Symfony\Component\BrowserKit\Client as BaseClient;
21 use Symfony\Component\BrowserKit\Request;
22 use Symfony\Component\BrowserKit\Response;
27 * @author Fabien Potencier <fabien.potencier@symfony-project.com>
28 * @author Michael Dowling <michael@guzzlephp.org>
29 * @author Charles Sarrazin <charles@sarraz.in>
30 * @author Kévin Dunglas <dunglas@gmail.com>
32 class Client extends BaseClient
36 private $headers = array();
39 public function setClient(GuzzleClientInterface $client)
41 $this->client = $client;
44 * @var $baseUri UriInterface
46 if (null !== $this->getServerParameter('HTTP_HOST', null) || null === $baseUri = $client->getConfig('base_uri')) {
50 $path = $baseUri->getPath();
51 if ('' !== $path && '/' !== $path) {
52 throw new \InvalidArgumentException('Setting a path in the Guzzle "base_uri" config option is not supported by Goutte yet.');
55 if (null === $this->getServerParameter('HTTPS', null) && 'https' === $baseUri->getScheme()) {
56 $this->setServerParameter('HTTPS', 'on');
59 $host = $baseUri->getHost();
60 if (null !== $port = $baseUri->getPort()) {
64 $this->setServerParameter('HTTP_HOST', $host);
69 public function getClient()
72 $this->client = new GuzzleClient(array('allow_redirects' => false, 'cookies' => true));
78 public function setHeader($name, $value)
80 $this->headers[strtolower($name)] = $value;
85 public function removeHeader($name)
87 unset($this->headers[strtolower($name)]);
90 public function resetHeaders()
92 $this->headers = array();
100 public function restart()
107 public function setAuth($user, $password = '', $type = 'basic')
109 $this->auth = array($user, $password, $type);
114 public function resetAuth()
122 * @param Request $request
126 protected function doRequest($request)
129 foreach ($request->getServer() as $key => $val) {
130 $key = strtolower(str_replace('_', '-', $key));
131 $contentHeaders = array('content-length' => true, 'content-md5' => true, 'content-type' => true);
132 if (0 === strpos($key, 'http-')) {
133 $headers[substr($key, 5)] = $val;
135 // CONTENT_* are not prefixed with HTTP_
136 elseif (isset($contentHeaders[$key])) {
137 $headers[$key] = $val;
141 $cookies = CookieJar::fromArray(
142 $this->getCookieJar()->allRawValues($request->getUri()),
143 parse_url($request->getUri(), PHP_URL_HOST)
146 $requestOptions = array(
147 'cookies' => $cookies,
148 'allow_redirects' => false,
149 'auth' => $this->auth,
152 if (!in_array($request->getMethod(), array('GET', 'HEAD'))) {
153 if (null !== $content = $request->getContent()) {
154 $requestOptions['body'] = $content;
156 if ($files = $request->getFiles()) {
157 $requestOptions['multipart'] = [];
159 $this->addPostFields($request->getParameters(), $requestOptions['multipart']);
160 $this->addPostFiles($files, $requestOptions['multipart']);
162 $requestOptions['form_params'] = $request->getParameters();
167 if (!empty($headers)) {
168 $requestOptions['headers'] = $headers;
171 $method = $request->getMethod();
172 $uri = $request->getUri();
174 foreach ($this->headers as $name => $value) {
175 $requestOptions['headers'][$name] = $value;
178 // Let BrowserKit handle redirects
180 $response = $this->getClient()->request($method, $uri, $requestOptions);
181 } catch (RequestException $e) {
182 $response = $e->getResponse();
183 if (null === $response) {
188 return $this->createResponse($response);
191 protected function addPostFiles(array $files, array &$multipart, $arrayName = '')
197 foreach ($files as $name => $info) {
198 if (!empty($arrayName)) {
199 $name = $arrayName.'['.$name.']';
206 if (is_array($info)) {
207 if (isset($info['tmp_name'])) {
208 if ('' !== $info['tmp_name']) {
209 $file['contents'] = fopen($info['tmp_name'], 'r');
210 if (isset($info['name'])) {
211 $file['filename'] = $info['name'];
217 $this->addPostFiles($info, $multipart, $name);
221 $file['contents'] = fopen($info, 'r');
224 $multipart[] = $file;
228 public function addPostFields(array $formParams, array &$multipart, $arrayName = '')
230 foreach ($formParams as $name => $value) {
231 if (!empty($arrayName)) {
232 $name = $arrayName.'['.$name.']';
235 if (is_array($value)) {
236 $this->addPostFields($value, $multipart, $name);
240 'contents' => $value,
246 protected function createResponse(ResponseInterface $response)
248 return new Response((string) $response->getBody(), $response->getStatusCode(), $response->getHeaders());