Commit e6575fb3 authored by Aaron Froehlich's avatar Aaron Froehlich Committed by Aaron Bauman
Browse files

Issue #3226511 by a-fro, jeffam: Allow RestClient to handle non-JSON data

parent bae985a1
Loading
Loading
Loading
Loading
+21 −10
Changes for src/Rest/RestClient.php: 21 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -117,6 +117,13 @@ class RestClient implements RestClientInterface {
   */
  protected $httpClientOptions;

  /**
   * Default HTTP headers.
   *
   * @var array
   */
  protected $defaultHeaders;

  const CACHE_LIFETIME = 300;
  const LONGTERM_CACHE_LIFETIME = 86400;

@@ -151,6 +158,9 @@ class RestClient implements RestClientInterface {
    $this->authProvider = $authManager->getProvider();
    $this->authConfig = $authManager->getConfig();
    $this->authToken = $authManager->getToken();
    $this->defaultHeaders = [
      'Content-type' => 'application/json',
    ];
    return $this;
  }

@@ -180,7 +190,7 @@ class RestClient implements RestClientInterface {
  /**
   * {@inheritdoc}
   */
  public function apiCall($path, array $params = [], $method = 'GET', $returnObject = FALSE) {
  public function apiCall($path, $params = [], $method = 'GET', $returnObject = FALSE, array $headers = []) {
    if (!$this->isInit()) {
      throw new RestException(NULL, $this->t('RestClient is not initialized.'));
    }
@@ -193,7 +203,7 @@ class RestClient implements RestClientInterface {
    }

    try {
      $this->response = new RestResponse($this->apiHttpRequest($url, $params, $method));
      $this->response = new RestResponse($this->apiHttpRequest($url, $params, $method, $headers));
    }
    catch (RequestException $e) {
      // RequestException gets thrown for any response status but 2XX.
@@ -211,7 +221,7 @@ class RestClient implements RestClientInterface {
      // throws anything but a RequestException, let it bubble up.
      $this->authToken = $this->authManager->refreshToken();
      try {
        $this->response = new RestResponse($this->apiHttpRequest($url, $params, $method));
        $this->response = new RestResponse($this->apiHttpRequest($url, $params, $method, $headers));
      }
      catch (RequestException $e) {
        $this->response = $e->getResponse();
@@ -243,10 +253,12 @@ class RestClient implements RestClientInterface {
   *
   * @param string $url
   *   Fully-qualified URL to resource.
   * @param array $params
   * @param array|string $params
   *   Parameters to provide.
   * @param string $method
   *   Method to initiate the call, such as GET or POST.  Defaults to GET.
   * @param array $headers
   *   The http headers to merge into the request.
   *
   * @return \GuzzleHttp\Psr7\Response
   *   Response object.
@@ -254,18 +266,17 @@ class RestClient implements RestClientInterface {
   * @throws \Exception
   * @throws \GuzzleHttp\Exception\RequestException
   */
  protected function apiHttpRequest($url, array $params, $method) {
  protected function apiHttpRequest($url, $params, $method, array $headers = []) {
    if (!$this->authToken) {
      throw new \Exception($this->t('Missing OAuth Token'));
    }

    $headers = [
      'Authorization' => 'OAuth ' . $this->authToken->getAccessToken(),
      'Content-type' => 'application/json',
    ];
    $headers['Authorization'] = 'OAuth ' . $this->authToken->getAccessToken();
    $headers = array_merge($this->defaultHeaders, $headers);

    $data = NULL;
    if (!empty($params)) {
      $data = $this->json->encode($params);
      $data = is_array($params) ? $this->json->encode($params) : $params;
    }
    return $this->httpRequest($url, $data, $headers, $method);
  }
+4 −2
Changes for src/Rest/RestClientInterface.php: 4 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ interface RestClientInterface {
   *   example, to issue an API call to a custom Apex Rest endpoint.
   *   If $path does not begin with a slash, the resource will be considered
   *   relative and the Rest API Endpoint will be pre-pended.
   * @param array $params
   * @param array|string $params
   *   Parameters to provide.
   * @param string $method
   *   Method to initiate the call, such as GET or POST.  Defaults to GET.
@@ -41,13 +41,15 @@ interface RestClientInterface {
   *   If true, return a Drupal\salesforce\Rest\RestResponse;
   *   Otherwise, return json-decoded response body only.
   *   Defaults to FALSE for backwards compatibility.
   * @param array $headers
   *   The http headers to merge into the request.
   *
   * @return mixed
   *   Response object or response data.
   *
   * @throws \GuzzleHttp\Exception\RequestException
   */
  public function apiCall($path, array $params = [], $method = 'GET', $returnObject = FALSE);
  public function apiCall($path, $params = [], $method = 'GET', $returnObject = FALSE, array $headers = []);

  /**
   * Return raw response content from given URL.
+19 −1
Changes for src/Rest/RestResponse.php: 19 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -41,8 +41,14 @@ class RestResponse extends Response {
  public function __construct(ResponseInterface $response) {
    $this->response = $response;
    parent::__construct($response->getStatusCode(), $response->getHeaders(), $response->getBody(), $response->getProtocolVersion(), $response->getReasonPhrase());

    if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) {
      $this->handleJsonResponse();
    }
    else {
      $this->handleRawResponse();
    }
  }

  /**
   * Magic getter method to return the given property.
@@ -70,7 +76,7 @@ class RestResponse extends Response {
   *
   * @throws \Drupal\salesforce\Rest\RestException
   */
  private function handleJsonResponse() {
  protected function handleJsonResponse() {
    $this->data = '';
    $response_body = $this->getBody()->getContents();
    if (empty($response_body)) {
@@ -108,4 +114,16 @@ class RestResponse extends Response {
    return $this;
  }

  /**
   * Helper function to set data to the raw response.
   *
   * @return $this
   *
   * @throws \Drupal\salesforce\Rest\RestException
   */
  protected function handleRawResponse() {
    $this->data = $this->getBody()->getContents();
    return $this;
  }

}
+1 −1
Changes for src/Tests/TestRestClient.php: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ class TestRestClient extends RestClient {
  /**
   * Short-circuit api calls.
   */
  public function apiCall($path, array $params = [], $method = 'GET', $returnObject = FALSE) {
  public function apiCall($path, $params = [], $method = 'GET', $returnObject = FALSE, array $headers = []) {
  }

  /**
+29 −5
Changes for tests/src/Unit/RestClientTest.php: 29 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -133,7 +133,31 @@ class RestClientTest extends UnitTestCase {

    // Test that an apiCall returns a json-decoded value.
    $body = ['foo' => 'bar'];
    $response = new GuzzleResponse(200, [], json_encode($body));
    $response = new GuzzleResponse(200, ['Content-Type' => 'application/json'], json_encode($body));

    $this->client->expects($this->any())
      ->method('httpRequest')
      ->willReturn($response);

    $result = $this->client->apiCall('');
    $this->assertEquals($result, $body);
  }

  /**
   * @covers ::apiCall
   */
  public function testNonJsonApiCall() {
    $this->initClient();

    // Test that an apiCall returns a CSV string value.
    $body = <<<EOT
    "Id","Name"
    "005R0000000UyrWIAS","Johnny B. Goode"
    "005R0000000GiwjIAC","Prince Rogers Nelson"
    "005R0000000GiwoIAC","Robert Allen Zimmerman"
    EOT;

    $response = new GuzzleResponse(200, ['Content-Type' => 'text/csv'], $body);

    $this->client->expects($this->any())
      ->method('httpRequest')
@@ -256,7 +280,7 @@ class RestClientTest extends UnitTestCase {
    $name = $this->randomMachineName();
    // @TODO this is fugly, do we need a refactor on RestResponse?
    $restResponse = new RestResponse(
      new GuzzleResponse('200', [], json_encode([
      new GuzzleResponse('200', ['Content-Type' => 'application/json'], json_encode([
        'name' => $name,
        'fields' => [
          [
@@ -309,7 +333,7 @@ class RestClientTest extends UnitTestCase {
  public function testObjectCreate() {
    $this->initClient(array_merge($this->methods, ['apiCall']));
    $restResponse = new RestResponse(
      new GuzzleResponse('200', [], json_encode([
      new GuzzleResponse('200', ['Content-Type' => 'application/json'], json_encode([
        'id' => $this->salesforce_id,
      ]))
      );
@@ -333,7 +357,7 @@ class RestClientTest extends UnitTestCase {
      'objectReadbyExternalId',
    ]));
    $createResponse = new RestResponse(
      new GuzzleResponse('200', [], json_encode([
      new GuzzleResponse('200', ['Content-Type' => 'application/json'], json_encode([
        'id' => $this->salesforce_id,
      ])));

@@ -451,7 +475,7 @@ class RestClientTest extends UnitTestCase {
    $this->initClient(array_merge($this->methods, [
      'apiCall',
    ]));
    $restResponse = new RestResponse(new GuzzleResponse('204', [], json_encode([
    $restResponse = new RestResponse(new GuzzleResponse('204', ['Content-Type' => 'application/json'], json_encode([
      'foo' => 'bar',
      'zee' => 'bang',
    ])));