mirror of
https://github.com/retailcrm/mailgun-php.git
synced 2025-02-06 08:19:25 +03:00
Introduce a request builder. (#217)
* Introduce a request builder. We inject every dependency (eg RequestFactory and MultipartStreamBuilder) and we do not have to use postMultipart. * code style * Use uppercase on http verbs * Added setters and use getters * Added tests * style
This commit is contained in:
parent
5535803031
commit
9bd6732efd
@ -163,7 +163,7 @@ class Domain extends HttpApi
|
||||
'password' => $password,
|
||||
];
|
||||
|
||||
$response = $this->httpPostMultipart(sprintf('/v3/domains/%s/credentials', $domain), $params);
|
||||
$response = $this->httpPost(sprintf('/v3/domains/%s/credentials', $domain), $params);
|
||||
|
||||
return $this->deserializer->deserialize($response, CreateCredentialResponse::class);
|
||||
}
|
||||
@ -188,14 +188,7 @@ class Domain extends HttpApi
|
||||
'password' => $pass,
|
||||
];
|
||||
|
||||
$response = $this->httpPutMultipart(
|
||||
sprintf(
|
||||
'/v3/domains/%s/credentials/%s',
|
||||
$domain,
|
||||
$login
|
||||
),
|
||||
$params
|
||||
);
|
||||
$response = $this->httpPut(sprintf('/v3/domains/%s/credentials/%s', $domain, $login), $params);
|
||||
|
||||
return $this->deserializer->deserialize($response, UpdateCredentialResponse::class);
|
||||
}
|
||||
|
@ -2,16 +2,11 @@
|
||||
|
||||
namespace Mailgun\Api;
|
||||
|
||||
use Http\Client\Common\HttpMethodsClient;
|
||||
use Http\Client\Exception as HttplugException;
|
||||
use Http\Client\HttpClient;
|
||||
use Http\Discovery\MessageFactoryDiscovery;
|
||||
use Http\Discovery\StreamFactoryDiscovery;
|
||||
use Http\Message\MultipartStream\MultipartStreamBuilder;
|
||||
use Http\Message\RequestFactory;
|
||||
use Mailgun\Assert;
|
||||
use Mailgun\Deserializer\ResponseDeserializer;
|
||||
use Mailgun\Exception\HttpServerException;
|
||||
use Mailgun\RequestBuilder;
|
||||
use Mailgun\Resource\Api\ErrorResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
@ -23,7 +18,7 @@ abstract class HttpApi
|
||||
/**
|
||||
* The HTTP client.
|
||||
*
|
||||
* @var HttpMethodsClient
|
||||
* @var HttpClient
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
@ -33,13 +28,19 @@ abstract class HttpApi
|
||||
protected $serializer;
|
||||
|
||||
/**
|
||||
* @param HttpClient $httpClient
|
||||
* @param RequestFactory $requestFactory
|
||||
* @param ResponseDeserializer $serializer
|
||||
* @var RequestBuilder
|
||||
*/
|
||||
public function __construct(HttpClient $httpClient, RequestFactory $requestFactory, ResponseDeserializer $deserializer)
|
||||
protected $requestBuilder;
|
||||
|
||||
/**
|
||||
* @param HttpClient $httpClient
|
||||
* @param RequestBuilder $requestBuilder
|
||||
* @param ResponseDeserializer $deserializer
|
||||
*/
|
||||
public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, ResponseDeserializer $deserializer)
|
||||
{
|
||||
$this->httpClient = new HttpMethodsClient($httpClient, $requestFactory);
|
||||
$this->httpClient = $httpClient;
|
||||
$this->requestBuilder = $requestBuilder;
|
||||
$this->deserializer = $deserializer;
|
||||
}
|
||||
|
||||
@ -78,7 +79,9 @@ abstract class HttpApi
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->get($path, $requestHeaders);
|
||||
$response = $this->httpClient->sendRequest(
|
||||
$this->requestBuilder->create('GET', $path, $requestHeaders)
|
||||
);
|
||||
} catch (HttplugException\NetworkException $e) {
|
||||
throw HttpServerException::networkError($e);
|
||||
}
|
||||
@ -100,25 +103,11 @@ abstract class HttpApi
|
||||
return $this->httpPostRaw($path, $this->createJsonBody($parameters), $requestHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a POST request with parameters encoded as multipart-stream form data.
|
||||
*
|
||||
* @param string $path Request path.
|
||||
* @param array $parameters POST parameters to be mutipart-stream-encoded.
|
||||
* @param array $requestHeaders Request headers.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
protected function httpPostMultipart($path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
return $this->doMultipart('POST', $path, $parameters, $requestHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a POST request with raw data.
|
||||
*
|
||||
* @param string $path Request path.
|
||||
* @param string $body Request body.
|
||||
* @param array|string $body Request body.
|
||||
* @param array $requestHeaders Request headers.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
@ -126,7 +115,9 @@ abstract class HttpApi
|
||||
protected function httpPostRaw($path, $body, array $requestHeaders = [])
|
||||
{
|
||||
try {
|
||||
$response = $this->httpClient->post($path, $requestHeaders, $body);
|
||||
$response = $this->httpClient->sendRequest(
|
||||
$this->requestBuilder->create('POST', $path, $requestHeaders, $body)
|
||||
);
|
||||
} catch (HttplugException\NetworkException $e) {
|
||||
throw HttpServerException::networkError($e);
|
||||
}
|
||||
@ -146,7 +137,9 @@ abstract class HttpApi
|
||||
protected function httpPut($path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
try {
|
||||
$response = $this->httpClient->put($path, $requestHeaders, $this->createJsonBody($parameters));
|
||||
$response = $this->httpClient->sendRequest(
|
||||
$this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createJsonBody($parameters))
|
||||
);
|
||||
} catch (HttplugException\NetworkException $e) {
|
||||
throw HttpServerException::networkError($e);
|
||||
}
|
||||
@ -154,20 +147,6 @@ abstract class HttpApi
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a PUT request with parameters encoded as multipart-stream form data.
|
||||
*
|
||||
* @param string $path Request path.
|
||||
* @param array $parameters PUT parameters to be mutipart-stream-encoded.
|
||||
* @param array $requestHeaders Request headers.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
protected function httpPutMultipart($path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
return $this->doMultipart('PUT', $path, $parameters, $requestHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a DELETE request with JSON-encoded parameters.
|
||||
*
|
||||
@ -180,7 +159,9 @@ abstract class HttpApi
|
||||
protected function httpDelete($path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
try {
|
||||
$response = $this->httpClient->delete($path, $requestHeaders, $this->createJsonBody($parameters));
|
||||
$response = $this->httpClient->sendRequest(
|
||||
$this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createJsonBody($parameters))
|
||||
);
|
||||
} catch (HttplugException\NetworkException $e) {
|
||||
throw HttpServerException::networkError($e);
|
||||
}
|
||||
@ -188,60 +169,6 @@ abstract class HttpApi
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a DELETE request with parameters encoded as multipart-stream form data.
|
||||
*
|
||||
* @param string $path Request path.
|
||||
* @param array $parameters DELETE parameters to be mutipart-stream-encoded.
|
||||
* @param array $requestHeaders Request headers.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
protected function httpDeleteMultipart($path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
return $this->doMultipart('DELETE', $path, $parameters, $requestHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request with parameters encoded as multipart-stream form data.
|
||||
*
|
||||
* @param string $type Request type. (POST, PUT, etc.)
|
||||
* @param string $path Request path.
|
||||
* @param array $parameters POST parameters to be mutipart-stream-encoded.
|
||||
* @param array $requestHeaders Request headers.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
protected function doMultipart($type, $path, array $parameters = [], array $requestHeaders = [])
|
||||
{
|
||||
Assert::oneOf(
|
||||
$type,
|
||||
[
|
||||
'DELETE',
|
||||
'POST',
|
||||
'PUT',
|
||||
]
|
||||
);
|
||||
|
||||
$streamFactory = StreamFactoryDiscovery::find();
|
||||
$builder = new MultipartStreamBuilder($streamFactory);
|
||||
foreach ($parameters as $k => $v) {
|
||||
$builder->addResource($k, $v);
|
||||
}
|
||||
|
||||
$multipartStream = $builder->build();
|
||||
$boundary = $builder->getBoundary();
|
||||
|
||||
$request = MessageFactoryDiscovery::find()->createRequest(
|
||||
$type,
|
||||
$path,
|
||||
['Content-Type' => 'multipart/form-data; boundary='.$boundary],
|
||||
$multipartStream
|
||||
);
|
||||
|
||||
return $this->httpClient->sendRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JSON encoded version of an array of parameters.
|
||||
*
|
||||
|
@ -11,8 +11,6 @@ namespace Mailgun;
|
||||
|
||||
use Http\Client\Common\HttpMethodsClient;
|
||||
use Http\Client\HttpClient;
|
||||
use Http\Discovery\MessageFactoryDiscovery;
|
||||
use Http\Message\RequestFactory;
|
||||
use Mailgun\Connection\RestClient;
|
||||
use Mailgun\Constants\ExceptionMessages;
|
||||
use Mailgun\Lists\OptInHandler;
|
||||
@ -50,9 +48,9 @@ class Mailgun
|
||||
private $deserializer;
|
||||
|
||||
/**
|
||||
* @var RequestFactory
|
||||
* @var RequestBuilder
|
||||
*/
|
||||
private $requestFactory;
|
||||
private $requestBuilder;
|
||||
|
||||
/**
|
||||
* @param string|null $apiKey
|
||||
@ -60,13 +58,15 @@ class Mailgun
|
||||
* @param string $apiEndpoint
|
||||
* @param ResponseDeserializer|null $deserializer
|
||||
* @param HttpClientConfigurator|null $clientConfigurator
|
||||
* @param RequestBuilder|null $requestBuilder
|
||||
*/
|
||||
public function __construct(
|
||||
$apiKey = null,
|
||||
HttpClient $httpClient = null, /* Deprecated, will be removed in 3.0 */
|
||||
$apiEndpoint = 'api.mailgun.net', /* Deprecated, will be removed in 3.0 */
|
||||
ResponseDeserializer $deserializer = null,
|
||||
HttpClientConfigurator $clientConfigurator = null
|
||||
HttpClientConfigurator $clientConfigurator = null,
|
||||
RequestBuilder $requestBuilder = null
|
||||
) {
|
||||
$this->apiKey = $apiKey;
|
||||
$this->restClient = new RestClient($apiKey, $apiEndpoint, $httpClient);
|
||||
@ -88,7 +88,7 @@ class Mailgun
|
||||
$clientConfigurator->setApiKey($apiKey);
|
||||
|
||||
$this->httpClient = $clientConfigurator->createConfiguredClient();
|
||||
$this->requestFactory = MessageFactoryDiscovery::find();
|
||||
$this->requestBuilder = $requestBuilder ?: new RequestBuilder();
|
||||
$this->deserializer = $deserializer ?: new ModelDeserializer();
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ class Mailgun
|
||||
*/
|
||||
public function getStatsApi()
|
||||
{
|
||||
return new Api\Stats($this->httpClient, $this->requestFactory, $this->deserializer);
|
||||
return new Api\Stats($this->httpClient, $this->requestBuilder, $this->deserializer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,6 +266,6 @@ class Mailgun
|
||||
*/
|
||||
public function getDomainApi()
|
||||
{
|
||||
return new Api\Domain($this->httpClient, $this->requestFactory, $this->deserializer);
|
||||
return new Api\Domain($this->httpClient, $this->requestBuilder, $this->deserializer);
|
||||
}
|
||||
}
|
||||
|
113
src/Mailgun/RequestBuilder.php
Normal file
113
src/Mailgun/RequestBuilder.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Mailgun;
|
||||
|
||||
use Http\Discovery\MessageFactoryDiscovery;
|
||||
use Http\Message\MultipartStream\MultipartStreamBuilder;
|
||||
use Http\Message\RequestFactory;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
||||
*/
|
||||
class RequestBuilder
|
||||
{
|
||||
/**
|
||||
* @var RequestFactory
|
||||
*/
|
||||
private $requestFactory;
|
||||
|
||||
/**
|
||||
* @var MultipartStreamBuilder
|
||||
*/
|
||||
private $multipartStreamBuilder;
|
||||
|
||||
/**
|
||||
* Creates a new PSR-7 request.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @param array $headers
|
||||
* @param array|string|null $body Request body. If body is an array we will send a as multipart stream request.
|
||||
* If array, each array *item* MUST look like:
|
||||
* array (
|
||||
* 'content' => string|resource|StreamInterface,
|
||||
* 'name' => string,
|
||||
* 'filename'=> string (optional)
|
||||
* 'headers' => array (optinal) ['header-name' => 'header-value']
|
||||
* )
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function create($method, $uri, array $headers = [], $body = null)
|
||||
{
|
||||
if (!is_array($body)) {
|
||||
return $this->getRequestFactory()->createRequest($method, $uri, $headers, $body);
|
||||
}
|
||||
|
||||
$builder = $this->getMultipartStreamBuilder();
|
||||
foreach ($body as $item) {
|
||||
$name = $item['name'];
|
||||
$content = $item['content'];
|
||||
unset($item['name']);
|
||||
unset($item['content']);
|
||||
|
||||
$builder->addResource($name, $content, $item);
|
||||
}
|
||||
|
||||
$multipartStream = $builder->build();
|
||||
$boundary = $builder->getBoundary();
|
||||
|
||||
$headers['Content-Type'] = 'multipart/form-data; boundary='.$boundary;
|
||||
|
||||
return $this->getRequestFactory()->createRequest($method, $uri, $headers, $multipartStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RequestFactory
|
||||
*/
|
||||
private function getRequestFactory()
|
||||
{
|
||||
if ($this->requestFactory === null) {
|
||||
$this->requestFactory = MessageFactoryDiscovery::find();
|
||||
}
|
||||
|
||||
return $this->requestFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RequestFactory $requestFactory
|
||||
*
|
||||
* @return RequestBuilder
|
||||
*/
|
||||
public function setRequestFactory($requestFactory)
|
||||
{
|
||||
$this->requestFactory = $requestFactory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MultipartStreamBuilder
|
||||
*/
|
||||
private function getMultipartStreamBuilder()
|
||||
{
|
||||
if ($this->multipartStreamBuilder === null) {
|
||||
$this->multipartStreamBuilder = new MultipartStreamBuilder();
|
||||
}
|
||||
|
||||
return $this->multipartStreamBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MultipartStreamBuilder $multipartStreamBuilder
|
||||
*
|
||||
* @return RequestBuilder
|
||||
*/
|
||||
public function setMultipartStreamBuilder($multipartStreamBuilder)
|
||||
{
|
||||
$this->multipartStreamBuilder = $multipartStreamBuilder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -47,8 +47,8 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||
->expects($this->any())
|
||||
->method('sendRequest');
|
||||
|
||||
$requestClient = $this->getMockBuilder('Http\Message\MessageFactory')
|
||||
->setMethods(['createRequest', 'createResponse'])
|
||||
$requestClient = $this->getMockBuilder('Mailgun\RequestBuilder')
|
||||
->setMethods(['create'])
|
||||
->getMock();
|
||||
|
||||
$deserializer = $this->getMockBuilder('Mailgun\Deserializer\ResponseDeserializer')
|
||||
@ -56,14 +56,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||
->getMock();
|
||||
|
||||
return $this->getMockBuilder($this->getApiClass())
|
||||
->setMethods(
|
||||
[
|
||||
'httpGet',
|
||||
'httpPost', 'httpPostRaw', 'postMultipart',
|
||||
'httpDelete', 'deleteMultipart',
|
||||
'httPut', 'putMultipart',
|
||||
]
|
||||
)
|
||||
->setMethods(['httpGet', 'httpPost', 'httpPostRaw', 'httpDelete', 'httPut'])
|
||||
->setConstructorArgs([$httpClient, $requestClient, $deserializer])
|
||||
->getMock();
|
||||
}
|
||||
|
38
tests/RequestBuilderTest.php
Normal file
38
tests/RequestBuilderTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Mailgun\Tests;
|
||||
|
||||
use Mailgun\RequestBuilder;
|
||||
|
||||
class RequestBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreateSimpleStream()
|
||||
{
|
||||
$builder = new RequestBuilder();
|
||||
$request = $builder->create('GET', 'http://foo.bar', ['Content-Type' => 'application/json'], 'content');
|
||||
|
||||
$body = $request->getBody()->__toString();
|
||||
$contentType = $request->getHeaderLine('Content-Type');
|
||||
|
||||
$this->assertContains('content', $body);
|
||||
$this->assertEquals('application/json', $contentType);
|
||||
}
|
||||
|
||||
public function testCreateMultipartStream()
|
||||
{
|
||||
$item0 = ['content' => 'foobar', 'name' => 'username'];
|
||||
$item1 = ['content' => 'Stockholm', 'name' => 'city'];
|
||||
|
||||
$builder = new RequestBuilder();
|
||||
$request = $builder->create('GET', 'http://foo.bar', ['Content-Type' => 'application/json'], [$item0, $item1]);
|
||||
|
||||
$body = $request->getBody()->__toString();
|
||||
$contentType = $request->getHeaderLine('Content-Type');
|
||||
|
||||
$this->assertContains('foobar', $body);
|
||||
$this->assertContains('username', $body);
|
||||
$this->assertContains('Stockholm', $body);
|
||||
$this->assertContains('city', $body);
|
||||
$this->assertRegExp('|^multipart/form-data; boundary=[0-9a-z]+$|si', $contentType);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user