Skip to content

Commit 19453a4

Browse files
committed
Merge pull request #42 from php-http/body
Add Body implementations
2 parents 6a04619 + 7ecdd59 commit 19453a4

15 files changed

+567
-154
lines changed

src/Body.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Http\Client;
4+
5+
use Psr\Http\Message\StreamInterface;
6+
7+
/**
8+
* Allows a more input types for body data
9+
*
10+
* @author Márk Sági-Kazár <[email protected]>
11+
*/
12+
interface Body
13+
{
14+
/**
15+
* Returns a set of headers which is needed to correctly send the body
16+
*
17+
* Note: these headers SHOULD be overwritten if any matching header is passed manually
18+
*
19+
* Content-Length is calculated automatically if possible
20+
*
21+
* @return array
22+
*/
23+
public function getContentHeaders();
24+
25+
/**
26+
* Convert data to a format which can be used to create a proper PSR-7 Stream
27+
*
28+
* @return string|StreamInterface
29+
*
30+
* @throws Exception
31+
*/
32+
public function toStreamable();
33+
}

src/Body/CombinedMultipart.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
/**
6+
* Data and files converted to multipart form body
7+
*
8+
* @author Márk Sági-Kazár <[email protected]>
9+
*/
10+
class CombinedMultipart extends Multipart
11+
{
12+
/**
13+
* @var MultipartData
14+
*/
15+
protected $data;
16+
17+
/**
18+
* @var Files
19+
*/
20+
protected $files;
21+
22+
/**
23+
* @param array $data
24+
* @param array $files
25+
* @param string|null $boundary
26+
*/
27+
public function __construct(array $data, array $files, $boundary = null)
28+
{
29+
parent::__construct($boundary);
30+
31+
$this->data = new MultipartData($data, $this->boundary);
32+
$this->files = new Files($files, $this->boundary);
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function toStreamable()
39+
{
40+
$body = $this->data->toStreamable();
41+
$body .= $this->files->toStreamable();
42+
43+
return $body;
44+
}
45+
}

src/Body/Files.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
use Http\Client\Exception\RuntimeException;
6+
7+
/**
8+
* Files converted to multipart form body
9+
*
10+
* @author Márk Sági-Kazár <[email protected]>
11+
*/
12+
class Files extends Multipart
13+
{
14+
/**
15+
* @var array
16+
*/
17+
protected $files;
18+
19+
/**
20+
* @param array $files
21+
* @param string|null $boundary
22+
*/
23+
public function __construct(array $files, $boundary = null)
24+
{
25+
$this->files = $files;
26+
27+
parent::__construct($boundary);
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function toStreamable()
34+
{
35+
$body = '';
36+
37+
foreach ($this->files as $name => $file) {
38+
if (!is_file($file)) {
39+
throw new RuntimeException(sprintf('File "%s" does not exist', $file));
40+
}
41+
42+
$body .= sprintf(
43+
"--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n\r\n%s\r\n",
44+
$this->boundary,
45+
$name,
46+
basename($file),
47+
file_get_contents($file)
48+
);
49+
}
50+
51+
return $body;
52+
}
53+
}

src/Body/Multipart.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
use Http\Client\Body;
6+
7+
/**
8+
* Basic multipart body
9+
*
10+
* @author Márk Sági-Kazár <[email protected]>
11+
*/
12+
abstract class Multipart implements Body
13+
{
14+
/**
15+
* @var string
16+
*/
17+
protected $boundary;
18+
19+
/**
20+
* @param string|null $boundary
21+
*/
22+
public function __construct($boundary = null)
23+
{
24+
if (is_null($boundary)) {
25+
$boundary = sha1(microtime());
26+
}
27+
28+
$this->boundary = $boundary;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function getContentHeaders()
35+
{
36+
return [
37+
'Content-Type' => 'multipart/form-data; boundary='.$this->boundary,
38+
];
39+
}
40+
}

src/Body/MultipartData.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
/**
6+
* Data converted to multipart form body
7+
*
8+
* @author Márk Sági-Kazár <[email protected]>
9+
*/
10+
class MultipartData extends Multipart
11+
{
12+
/**
13+
* @var array
14+
*/
15+
protected $data;
16+
17+
/**
18+
* @param array $data
19+
* @param string|null $boundary
20+
*/
21+
public function __construct(array $data, $boundary = null)
22+
{
23+
$this->data = $data;
24+
25+
parent::__construct($boundary);
26+
}
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function toStreamable()
32+
{
33+
return $this->prepareData(null, $this->data);
34+
}
35+
36+
/**
37+
* @param string|integer|null $name
38+
* @param mixed $data
39+
*
40+
* @return string
41+
*/
42+
protected function prepareData($name, $data)
43+
{
44+
$body = '';
45+
46+
if (is_array($data)) {
47+
foreach ($data as $subName => $subData) {
48+
if (!is_null($name)) {
49+
$subName = sprintf('%s[%s]', $name, $subName);
50+
}
51+
52+
$body .= $this->prepareData($subName, $subData);
53+
}
54+
55+
return $body;
56+
}
57+
58+
$body .= sprintf(
59+
"--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n",
60+
$this->files->getBoundary(),
61+
$name,
62+
$data
63+
);
64+
65+
return $body;
66+
}
67+
}

src/Body/PlainText.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
use Http\Client\Body;
6+
7+
/**
8+
* Plain text body
9+
*
10+
* @author Márk Sági-Kazár <[email protected]>
11+
*/
12+
class PlainText implements Body
13+
{
14+
/**
15+
* @var string
16+
*/
17+
protected $string;
18+
19+
/**
20+
* @param string $string
21+
*/
22+
public function __construct($string)
23+
{
24+
$this->string = $string;
25+
}
26+
27+
/**
28+
* {@inheritdoc}
29+
*/
30+
public function getContentHeaders()
31+
{
32+
return [
33+
'Content-Type' => 'text/plain',
34+
];
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
public function toStreamable()
41+
{
42+
return $this->string;
43+
}
44+
}

src/Body/UrlencodedData.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Http\Client\Body;
4+
5+
use Http\Client\Body;
6+
7+
/**
8+
* @author Márk Sági-Kazár <[email protected]>
9+
*/
10+
class UrlencodedData implements Body
11+
{
12+
/**
13+
* @var array
14+
*/
15+
protected $data;
16+
17+
/**
18+
* @param array $data
19+
*/
20+
public function __construct(array $data)
21+
{
22+
$this->data = $data;
23+
}
24+
25+
/**
26+
* {@inheritdoc}
27+
*/
28+
public function getContentHeaders()
29+
{
30+
return [
31+
'Content-Type' => 'application/x-www-form-urlencoded',
32+
];
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function toStreamable()
39+
{
40+
return http_build_query($this->data, null, '&');
41+
}
42+
}

src/Client.php

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/Exception/HttpClientException.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
namespace Http\Client\Exception;
44

5-
use Http\Client\Exception;
65
use Psr\Http\Message\RequestInterface;
76
use Psr\Http\Message\ResponseInterface;
87

98
/**
109
* @author GeLo <[email protected]>
1110
*/
12-
class HttpClientException extends \RuntimeException implements Exception
11+
class HttpClientException extends RuntimeException
1312
{
1413
/**
1514
* @var RequestInterface|null

src/Exception/MultiHttpClientException.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
namespace Http\Client\Exception;
44

5-
use Http\Client\Exception;
65
use Psr\Http\Message\ResponseInterface;
76

87
/**
98
* @author GeLo <[email protected]>
109
*/
11-
class MultiHttpClientException extends \RuntimeException implements Exception
10+
class MultiHttpClientException extends RuntimeException
1211
{
1312
/**
1413
* @var HttpClientException[]

0 commit comments

Comments
 (0)