Coder Social home page Coder Social logo

guzzle / guzzle-services Goto Github PK

View Code? Open in Web Editor NEW
251.0 251.0 77.0 311 KB

Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.

License: MIT License

Makefile 0.01% PHP 99.95% HTML 0.04%
api guzzle guzzle-services http rest

guzzle-services's Introduction

Guzzle

Guzzle, PHP HTTP client

Latest Version Build Status Total Downloads

Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.

  • Simple interface for building query strings, POST requests, streaming large uploads, streaming large downloads, using HTTP cookies, uploading JSON data, etc...
  • Can send both synchronous and asynchronous requests using the same interface.
  • Uses PSR-7 interfaces for requests, responses, and streams. This allows you to utilize other PSR-7 compatible libraries with Guzzle.
  • Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients.
  • Abstracts away the underlying HTTP transport, allowing you to write environment and transport agnostic code; i.e., no hard dependency on cURL, PHP streams, sockets, or non-blocking event loops.
  • Middleware system allows you to augment and compose client behavior.
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');

echo $response->getStatusCode(); // 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'

// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});

$promise->wait();

Help and docs

We use GitHub issues only to discuss bugs and new features. For support please refer to:

Installing Guzzle

The recommended way to install Guzzle is through Composer.

composer require guzzlehttp/guzzle

Version Guidance

Version Status Packagist Namespace Repo Docs PSR-7 PHP Version
3.x EOL (2016-10-31) guzzle/guzzle Guzzle v3 v3 No >=5.3.3,<7.0
4.x EOL (2016-10-31) guzzlehttp/guzzle GuzzleHttp v4 N/A No >=5.4,<7.0
5.x EOL (2019-10-31) guzzlehttp/guzzle GuzzleHttp v5 v5 No >=5.4,<7.4
6.x EOL (2023-10-31) guzzlehttp/guzzle GuzzleHttp v6 v6 Yes >=5.5,<8.0
7.x Latest guzzlehttp/guzzle GuzzleHttp v7 v7 Yes >=7.2.5,<8.4

Security

If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.

License

Guzzle is made available under the MIT License (MIT). Please see License File for more information.

For Enterprise

Available as part of the Tidelift Subscription

The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

guzzle-services's People

Contributors

asa1-et-jenkins avatar bakura10 avatar bolid1 avatar bonndan avatar cordoval avatar danieledangeli avatar danizord avatar deshmukhsn avatar dragonwize avatar forevermatt avatar fuhry avatar grahamcampbell avatar igorsantos07 avatar jeremeamia avatar jwcobb avatar konafets avatar magnetik avatar mtdowling avatar my2ter avatar nyholm avatar peterfox avatar rfink avatar siwinski avatar sprak3000 avatar stovak avatar sy-records avatar tianyiw2013 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

guzzle-services's Issues

Updating the description

Hi,

In Guzzle 3, there was a setDescription method. This is useful in some cases. I'm using this for my Stripe wrapper, so that depending on the version you want of Stripe, it loads a different descriptor.

What is the currently recommended way to do it? If there's no reason, I will do a PR to add it :).

Thanks!

XmlLocation response not handling multiple tags of the same name correctly

Working with the XML returned from here, the XML returned contains multiple tags of the same name:

<cast gid="1324597141" lang="DE">
  <role>Daisuke Jigen</role>
  <person id="22762">Tilo Schmitz</person>
</cast>
<cast gid="1413111110" lang="DE">
  <role>Inspector Zenigata</role>
  <person id="28552">Stefan Staudinger</person>
</cast>
<cast gid="4109027170" lang="DE">
  <role>Hardyman/Arsene Lupin</role>
  <person id="30167">Tommi Piper</person>
</cast>

The resulting model contains this:

                    [cast] => Array
                        (
                            [role] => Daisuke Jigen
                            [person] => Array
                                (
                                    [@attributes] => Array
                                        (
                                            [id] => 22762
                                        )

                                    [value] => Tilo Schmitz
                                )

                            [0] => Array
                                (
                                    [role] => Inspector Zenigata
                                    [person] => Array
                                        (
                                            [@attributes] => Array
                                                (
                                                    [id] => 28552
                                                )

                                            [value] => Stefan Staudinger
                                        )

                                )

                            [1] => Array
                                (
                                    [role] => Hardyman/Arsene Lupin
                                    [person] => Array
                                        (
                                            [@attributes] => Array
                                                (
                                                    [id] => 30167
                                                )

                                            [value] => Tommi Piper
                                        )

                                )

...

Expected: That first cast tag in the XML would have its contents encapsulated into item 0 in the array returned by getting the model's cast key.

e.g.,

                    [cast] => Array
                        (
                            [0] => Array
                                (
                                    [role] => Daisuke Jigen
                                    [person] => Array
                                        (
                                            [@attributes] => Array
                                                (
                                                    [id] => 22762
                                                )

                                            [value] => Tilo Schmitz
                                        )

                                )

                            [1] => Array
                                (
                                    [role] => Inspector Zenigata
                                    [person] => Array
                                        (
                                            [@attributes] => Array
                                                (
                                                    [id] => 28552
                                                )

                                            [value] => Stefan Staudinger
                                        )

                                )

...

Returning mock responses

I try to write a test for a guzzle client which uses service descriptions.
The response is mocked like described in the current guzzle documentation

use GuzzleHttp\Subscriber\Mock
...
// $client is a \GuzzleHttp\Command\Guzzle\GuzzleClient
$mock = new Mock([$fixturePath]);
$client->getHttpClient()->getEmitter()->attach($mock);
...
$result = $client->doStuff(); // calls the doStuff operation from the service description

This works fine and I could confirm that the mock is actually used.
However the $result is always an empty array even though the underlying transaction got the correct response.

Since I do only want to make test assertions on the request, this issue has not become a problem yet but I wonder if I am doing the tests correctly. Am I missing something here? Any help would be much appreciated

Also I wondered why I could not attach the response mock to the emitter of my client directly but had to use the underlying client implementation (using getHttpClient()).

Exceptions Thrown From Subscribers Are Ignored?

ph4kkhi
For some reason the code continues without throwing this exception at a later point? This used to work in guzzle 4. I've done some debugging, and this exception is definitely thrown from this subscriber, but for some reason guzzle ignores it, and continues anyway?

Regression of Issue #51 - XmlLocation response not handling multiple tags of the same name correctly

Issue #51 was closed as fixed, but it appears there is a regression that has cropped up around it. It is back to the same behavior seen before; the first node is off on its own instead of encapsulated as item 0 in the array for the tag.

It looks like a bit of code from my original fix got nerfed at some point; the else if out of the fix (src/ResponseLocation/XmlLocation.php method xmlToArray) got nerfed:

// A child element with this name exists so we're assuming
// that the node contains a list of elements
if (!is_array($result[$name])) {
  $result[$name] = [$result[$name]];
}

should be

// A child element with this name exists so we're assuming
// that the node contains a list of elements
if (!is_array($result[$name])) {
  $result[$name] = [$result[$name]];
}  else if (!isset($result[$name][0])) {
  // Convert the first child into the first element of a numerically indexed array
  $firstResult = $result[$name];
  $result[$name] = [];
  $result[$name][] = $firstResult;
}

I've tried patching this locally, and it clears up my issue. I'll get a PR going.

Requesting a new version tag

0.3.0 doesn't contain this fix: #43

Therefore I still get the described error when I pull in the library via composer. I'd like to avoid pinning to dev-master if possible.

PUT requests with parameters with location of "postField" result in Exception

I'm using v0.5 of this service. I have a Service Description with a operation that uses 'httpMethod' => 'PUT':

$api = new GuzzleHttp\Command\Guzzle\Description([
            'baseUrl' => $myBaseUrl,
            'operations' => [
                'SubscriberChangeEmail' => [
                    'httpMethod' => 'PUT',
                    'uri' => '/myapp/api/subscriber/changeEmail',
                    'responseModel' => 'changeEmailOutput',
                    'parameters' => [
                        'oldEmail' => [
                            'location' => 'postField',
                        ],
                        'newEmail' => [
                            'location' => 'postField',
                        ],
                    ],
                ],
                ...

When I try to consume the API I get an exception due to my use of 'location' => 'postField':

exception 'RuntimeException' with message 'Must be a POST body interface' in /var/www/apisupertasker/vendor/guzzlehttp/guzzle-services/src/RequestLocation/PostFieldLocation.php:23
Stack trace:
#0 /var/www/apisupertasker/vendor/guzzlehttp/guzzle-services/src/Serializer.php(94): GuzzleHttp\Command\Guzzle\RequestLocation\PostFieldLocation->visit(Object(GuzzleHttp\Command\Command), Object(GuzzleHttp\Message\Request), Object(GuzzleHttp\Command\Guzzle\Parameter), Array)
#1 /var/www/apisupertasker/vendor/guzzlehttp/guzzle-services/src/Serializer.php(57): GuzzleHttp\Command\Guzzle\Serializer->prepareRequest(Object(GuzzleHttp\Command\CommandTransaction), Object(GuzzleHttp\Message\Request))
#2 /var/www/apisupertasker/vendor/guzzlehttp/guzzle-services/src/GuzzleClient.php(101): GuzzleHttp\Command\Guzzle\Serializer->__invoke(Object(GuzzleHttp\Command\CommandTransaction))
#3 /var/www/apisupertasker/vendor/guzzlehttp/command/src/AbstractClient.php(221): GuzzleHttp\Command\Guzzle\GuzzleClient->serializeRequest(Object(GuzzleHttp\Command\CommandTransaction))
#4 /var/www/apisupertasker/vendor/guzzlehttp/command/src/AbstractClient.php(81): GuzzleHttp\Command\AbstractClient->initTransaction(Object(GuzzleHttp\Command\Command))
#5 /var/www/apisupertasker/vendor/guzzlehttp/command/src/AbstractClient.php(76): GuzzleHttp\Command\AbstractClient->execute(Object(GuzzleHttp\Command\Command))

I tried 'location' => 'putField' but that didn't work. I think this was fixed in a previous incarnation of the code, see guzzle/guzzle#278 (but this is in a different git repo - I'm pretty confused about the versions, please excuse me for that ๐Ÿ˜• ).

Parameter type validation is too strict

This is an operation I defined:

'users' => [
    'httpMethod'    => 'GET',
    'uri'           => 'users/{id}',
    'responseModel' => 'users',
    'parameters'    => [
        'id' => [
            'type'     => 'integer',
            'location' => 'uri',
            'required' => TRUE
        ]
    ]
]

When I'm calling the operation this way:
$data = $client->users(['id' => '1574083']);
this error comes up:
Fatal error: Uncaught exception 'GuzzleHttp\Command\Exception\CommandException' with message 'Validation errors: [id] must be of type integer'

Shouldn't an integer-like value be fine, although it's given as string?

Cannot add Autorization header to my requests

Hi guys, I have following code:

Client class

<?php namespace Solidoptics;

use GuzzleHttp\Client;
use GuzzleHttp\Command\Guzzle\GuzzleClient;
use GuzzleHttp\Command\Guzzle\Description;

class ApiClient extends Client
{
    public static function factory($config = array())
    {
        $client = new Client();

        $config = array_merge($config, json_decode(file_get_contents(__DIR__.'/Resources/config/client.json'), TRUE));

        $guzzleClient = new GuzzleClient(new Client(), new Description($config));

        return $guzzleClient;
    }
}

Config settings

   {
    "operations": {
        "me":{
            "description": "Returns user profile details",
            "httpMethod": "GET",
            "uri": "users/me",
            "parameters": {
                "token": {
                    "type":"string",
                    "location": "header",
                    "sentAs": "Authorization"
                }
            }
        }
    }
}

Usage

$config = [
    'baseUrl' => 'http://localhost/api/v1/'
];
$api_client = ApiClient::factory($config);

$token   = 'Bearer V6tBMG6FKL7wLxZh116IGdvfDUtOvlFIJI61nrHp';
$result = $api_client->me(array(
    'token' => $token
));

And I want add custom Autorizarion Bearer header to all requests, how I can do that? Add header to $client doesn't help cuz $result after call me method is NULL.

Thanks

Description factory

Hi,

I'm currently upgrading one app from Guzzle 3 to Guzzle 4. It seems that the static factory method has disappeared from the Description class, what's the best way to create a description from a file now ?

Thanks in advance.

XmlLocation not adding attributes to non-leaf child nodes

Here is a snippet of the XML returned from here:

<cast gid="1324597141" lang="DE">
  <role>Daisuke Jigen</role>
  <person id="22762">Tilo Schmitz</person>
</cast>
<cast gid="1413111110" lang="DE">
  <role>Inspector Zenigata</role>
  <person id="28552">Stefan Staudinger</person>
</cast>
<cast gid="4109027170" lang="DE">
  <role>Hardyman/Arsene Lupin</role>
  <person id="30167">Tommi Piper</person>
</cast>

The resulting model contains this:

                    [cast] => Array
                        (
                            [role] => Daisuke Jigen
                            [person] => Array
                                (
                                    [@attributes] => Array
                                        (
                                            [id] => 22762
                                        )

                                    [value] => Tilo Schmitz
                                )

                            [0] => Array
                                (
                                    [role] => Inspector Zenigata
                                    [person] => Array
                                        (
                                            [@attributes] => Array
                                                (
                                                    [id] => 28552
                                                )

                                            [value] => Stefan Staudinger
                                        )

                                )

...

Expected: The non-leaf elements should have an @attributes key containing all the attribute key/value pairs.

Automatically returns array from command?

Hi,

I've never used the "Model" feature of Guzzle, but rather only relied on the fact it returns response data as array. I've tried to switch a library to Guzzle 4, and now when I call a command:

$response = $guzzleClient->foo();

$response is always null. It seems that I have to explicitly create a "getResponse" model (as in the doc), and add the "responseModel" property to all my commands. Can't Guzzle default to returning data as array?

allow default 'location' on Model

In starting to work with guzzle-services I've been annoyed and surprised that I have to specify location for each property of an object-type Model. Is it so crazy to assume that all properties of a Model with "location": "json" also have json locations?

Arrays nested under objects in JSON response broken?

Not sure if this is a bug or to be expected. I am trying to write a descriptor for a data structure like following:

{
    "some_attrib": "Foo",
    "some_array": [
        {
            "attrib": "Bar"
        },
        {
            "attrib": "Baz"
        }
    ]
}

So basically nesting an array under an object. The descriptor would look along the lines of:

new Description([
    'baseUrl'    => 'http://localhost/',
    'operations' => [
        'op' => [
            'responseModel' => 'Foo',
            // .. 
        ],
    ],
    'models'     => [
        'Foo' => [
            'type'       => 'object',
            'properties' => [
                'some_attrib' => [
                    'type'     => 'string',
                    'location' => 'json'
                ],
                'some_array'  => [
                    'location' => 'json',
                    'type'     => 'array',
                    'items'    => [
                        'type'       => 'object',
                        'properties' => [
                            'attrib'   => [
                                'type'     => 'string',
                                'location' => 'json'
                            ]
                        ]
                    ]
                ]
            ]
        ],
    ]
]);

The model response dumped as json gives me:

{
    "some_attrib": "Foo",
    "some_array": [
        "Foo",
        []
    ]
}

In the tests (JsonLocationTest::testVisitsTopLevelArrays) I've found a variant of nested arrays, which does work without problems. Here a Gist to compare both of the nested variants: https://gist.github.com/ukautz/04ea325ef40f6b6c97a6

The fix I came up with destroys the "other kind" of nested array and before digging deeper I'd like to confirm whether this is expected or indeed a bug.

Allow primitive response types for operations

Right now, only objects and arrays are allowed as responseModel types, but there are many APIs where a raw data type is return, such as a string or number. Would it be possible to implement this? I believe old guzzle service descriptions allowed that.

Old responseClass behaviour

I'm porting some services to Guzzle 5 from Guzzle 3. Most of our workflow is based on service descriptions. For the responses we used classes like that:

<?php

return array(
    'operations' => array(
        'abstract.base' => array(
            'responseClass' => '\\Test\\Foo\\Model\\BaseResponse',
            'responseType' => 'class',
        ),
    ),
);

And...

<?php

namespace Test\Foo\Model;

use Guzzle\Service\Command\ResponseClassInterface;
use Guzzle\Service\Command\OperationCommand;
use Guzzle\Service\Command\DefaultResponseParser;

class Response implements ResponseClassInterface
{
    public static function fromCommand(OperationCommand $command)
    {
        $parser = DefaultResponseParser::getInstance();
        $response = $parser->parse($command);

        // Custom logic on the constructor
        return new self($response);
    }

    // ...
}

Is this possible in Guzzle 5 yet or will it be anytime soon? If it's a missing feature, can I work on it or has it been discarded for a new way of doing that?

Assigning data to the "root" of result?

I am making a service for API that returns (sometimes) serialized PHP in response bodies.

This is model I have so far for them:

'serialized' => [
    'type'       => 'object',
    'properties' => [
        'body' => [
            'location' => 'body',
            'type'     => 'string',
            'filters'  => [ 'unserialize', 'get_object_vars' ],
        ],
    ],

But since I am not interested in anything else in response I would like to get rid of pointless "body" level in resulting array. additionalProperties approach doesn't seem to work here as it does with JSON or I can't figure out how to apply it.

improve exception message

GuzzleHttp\Exception\RequestException: Error executing command: Will not follow more than 6 redirects in /Users/cordoval/Sites/project/vendor/guzzlehttp/guzzle/src/Client.php on line 191

is not very conveying of what is wrong

Validation Bug

There is an issue with guzzle services as found here: https://github.com/GrahamCampbell/Laravel-CloudFlare-API/issues/9.

Note that the issue is that guzzle is not throwing the correct exception when type validation fails.

I've replicated this issue, and generated a stack trace:

Stack trace:
#0 C:\[REMOVED]\vendor\guzzlehttp\command\src\Exception\CommandException.php(21): Illuminate\Exception\Handler->handleError(4096, 'Argument 2 pass...', 'C:\\Program File...', 21, Array)
#1 C:\[REMOVED]\vendor\guzzlehttp\guzzle-services\src\Subscriber\ValidateInput.php(73): GuzzleHttp\Command\Exception\CommandException->__construct('Validation erro...', Object(GuzzleHttp\Command\Guzzle\GuzzleClient), Object(GuzzleHttp\Command\Guzzle\Command))
#2 C:\[REMOVED]\vendor\guzzlehttp\guzzle\src\Event\Emitter.php(105): GuzzleHttp\Command\Guzzle\Subscriber\ValidateInput->onPrepare(Object(GuzzleHttp\Command\Event\PrepareEvent), 'prepare')
#3 C:\[REMOVED]\vendor\guzzlehttp\command\src\Event\CommandEvents.php(28): GuzzleHttp\Event\Emitter->emit('prepare', Object(GuzzleHttp\Command\Event\PrepareEvent))
#4 C:\[REMOVED]\vendor\guzzlehttp\command\src\AbstractClient.php(71): GuzzleHttp\Command\Event\CommandEvents::prepare(Object(GuzzleHttp\Command\CommandTransaction))
#5 C:\[REMOVED]\vendor\guzzlehttp\command\src\AbstractClient.php(65): GuzzleHttp\Command\AbstractClient->execute(Object(GuzzleHttp\Command\Guzzle\Command))
#6 C:\[REMOVED]\vendor\graham-campbell\core-api\src\Models\AbstractModel.php(113): GuzzleHttp\Command\AbstractClient->__call('recNew', Array)
#7 C:\[REMOVED]\vendor\graham-campbell\core-api\src\Models\AbstractModel.php(113): GuzzleHttp\Command\Guzzle\GuzzleClient->recNew(Array)
#8 C:\[REMOVED]\vendor\graham-campbell\cloudflare-api\src\Models\Zone.php(575): GrahamCampbell\CoreAPI\Models\AbstractModel->action('recNew', Array, 'recLoadAll')
#9 C:\[REMOVED]\app\storage\views\2181841fb1f253970aaa117d3cacc182(57) : eval()'d code(9): GrahamCampbell\CloudFlareAPI\Models\Zone->createRecord(Array)
#10 C:\[REMOVED]\app\storage\views\2181841fb1f253970aaa117d3cacc182(57): eval()
#11 C:\[REMOVED]\bootstrap\compiled.php(9745): include('C:\\Program File...')
#12 C:\[REMOVED]\vendor\laravel\framework\src\Illuminate\View\Engines\CompilerEngine.php(56): Illuminate\View\Engines\PhpEngine->evaluatePath('C:\\Program File...', Array)
#13 C:\[REMOVED]\bootstrap\compiled.php(9624): Illuminate\View\Engines\CompilerEngine->get('C:\\Program File...', Array)
#14 C:\[REMOVED]\bootstrap\compiled.php(9611): Illuminate\View\View->getContents()
#15 C:\[REMOVED]\bootstrap\compiled.php(9602): Illuminate\View\View->renderContents()
#16 C:\[REMOVED]\bootstrap\compiled.php(10300): Illuminate\View\View->render()
#17 C:\[REMOVED]\bootstrap\compiled.php(9831): Illuminate\Http\Response->setContent(Object(Illuminate\View\View))
#18 C:\[REMOVED]\bootstrap\compiled.php(5195): Symfony\Component\HttpFoundation\Response->__construct(Object(Illuminate\View\View))
#19 C:\[REMOVED]\bootstrap\compiled.php(5003): Illuminate\Routing\Router->prepareResponse(Object(Illuminate\Http\Request), Object(Illuminate\View\View))
#20 C:\[REMOVED]\bootstrap\compiled.php(4989): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#21 C:\[REMOVED]\bootstrap\compiled.php(717): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#22 C:\[REMOVED]\bootstrap\compiled.php(698): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#23 C:\[REMOVED]\vendor\barryvdh\laravel-debugbar\src\Barryvdh\Debugbar\Middleware.php(34): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#24 C:\[REMOVED]\bootstrap\compiled.php(7711): Barryvdh\Debugbar\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#25 C:\[REMOVED]\bootstrap\compiled.php(8314): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#26 C:\[REMOVED]\bootstrap\compiled.php(8261): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#27 C:\[REMOVED]\bootstrap\compiled.php(10900): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#28 C:\[REMOVED]\bootstrap\compiled.php(659): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#29 C:\[REMOVED]\public\index.php(57): Illuminate\Foundation\Application->run()
#30 {main}

Next exception 'ErrorException' with message 'Argument 2 passed to GuzzleHttp\Command\Exception\CommandException::__construct() must be an instance of GuzzleHttp\Command\CommandTransaction, instance of GuzzleHttp\Command\Guzzle\GuzzleClient given, called in C:\[REMOVED]\vendor\guzzlehttp\guzzle-services\src\Subscriber\ValidateInput.php on line 73 and defined (View: C:\[REMOVED]\app\views\pages\show.blade.php)' in C:\[REMOVED]\vendor\guzzlehttp\command\src\Exception\CommandException.php:21
Stack trace:
#0 C:\[REMOVED]\bootstrap\compiled.php(9747): Illuminate\View\Engines\CompilerEngine->handleViewException(Object(ErrorException))
#1 C:\[REMOVED]\vendor\laravel\framework\src\Illuminate\View\Engines\CompilerEngine.php(56): Illuminate\View\Engines\PhpEngine->evaluatePath('C:\\Program File...', Array)
#2 C:\[REMOVED]\bootstrap\compiled.php(9624): Illuminate\View\Engines\CompilerEngine->get('C:\\Program File...', Array)
#3 C:\[REMOVED]\bootstrap\compiled.php(9611): Illuminate\View\View->getContents()
#4 C:\[REMOVED]\bootstrap\compiled.php(9602): Illuminate\View\View->renderContents()
#5 C:\[REMOVED]\bootstrap\compiled.php(10300): Illuminate\View\View->render()
#6 C:\[REMOVED]\bootstrap\compiled.php(9831): Illuminate\Http\Response->setContent(Object(Illuminate\View\View))
#7 C:\[REMOVED]\bootstrap\compiled.php(5195): Symfony\Component\HttpFoundation\Response->__construct(Object(Illuminate\View\View))
#8 C:\[REMOVED]\bootstrap\compiled.php(5003): Illuminate\Routing\Router->prepareResponse(Object(Illuminate\Http\Request), Object(Illuminate\View\View))
#9 C:\[REMOVED]\bootstrap\compiled.php(4989): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#10 C:\[REMOVED]\bootstrap\compiled.php(717): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#11 C:\[REMOVED]\bootstrap\compiled.php(698): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#12 C:\[REMOVED]\vendor\barryvdh\laravel-debugbar\src\Barryvdh\Debugbar\Middleware.php(34): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#13 C:\[REMOVED]\bootstrap\compiled.php(7711): Barryvdh\Debugbar\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#14 C:\[REMOVED]\bootstrap\compiled.php(8314): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#15 C:\[REMOVED]\bootstrap\compiled.php(8261): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#16 C:\[REMOVED]\bootstrap\compiled.php(10900): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#17 C:\[REMOVED]\bootstrap\compiled.php(659): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#18 C:\[REMOVED]\public\index.php(57): Illuminate\Foundation\Application->run()
#19 {main} [] []

Request parameter PathLocation

I have to retrieve a REST subresource at /foo/{id}/bars?someParam=baz, i.e. the path contains a parameter. QueryLocation does not help here, so how can I send the proper query?

My plan is to add a PathLocation to the PrepareRequest subscriber, but how?

class PathLocation extends AbstractLocation
{
    public function visit(
        GuzzleCommandInterface $command,
        RequestInterface $request,
        Parameter $param,
        array $context
    ) {
        $value = $this->prepareValue(
            $command[$param->getName()],
            $param
        );
        $this->replaceParam($request, $param->getWireName(), $value);
    }

    public function after(
        GuzzleCommandInterface $command,
        RequestInterface $request,
        Operation $operation,
        array $context
    ) {
        $additional = $operation->getAdditionalParameters();
        if ($additional && $additional->getLocation() == $this->locationName) {
            foreach ($command->toArray() as $key => $value) {
                if (!$operation->hasParam($key)) {
                    $this->replaceParam($request, $key, $this->prepareValue(
                        $value,
                        $additional
                    ));
                }
            }
        }
    }

    private function replaceParam(RequestInterface $request, $name, $value)
    {
        $path = str_replace('{' . $name . '}', $value, $request->getPath());
        $request->setPath($path);
    }
}

typehints for operations property

should they be typehinted as both arrays and objects? is there any instance where they are accessed before they get turned into objects?

CommandException doesn't contain response data

What we do:

try {
            $item = $client->storeItem([
                    'any' => 'data'
            ]);
        } catch (CommandException $ex) {
            return $this->respondCommandException(
                  $exception->getTransaction()->getResponse()->json(),
                  $exception->getTransaction()->getResponse()->getStatusCode()
            );
        }

We're receiving errors from API and pass them to view. But $exception->getTransaction()->getResponse() is null.

Is there a way to create an XML string element with attributes?

Is there a way to create a service configuration for a string element with attributes like this with two parameters name (as an attribute) and value (as the element content)?
In my case it is an array of elements, but that's not the point.

<Request>
  <Item name="foo">bar</Item>
  <Item name="buzz">bar</Item>
</Request>

I tried a lot of variation but the closest I got is this:

'Item' => [
    'required' => false,
    'type' => 'array',
    'data' => [
        'xmlFlattened' => true
    ],
    'items' => [
        'required' => false,
        'type' => 'object',
        'sentAs' => 'Item',
        'properties' => [
            'name' => [
                'required' => true,
                'type' => 'string',
                'description' => 'Item name',
                'data'   => [
                    'xmlAttribute' => true
                ]
            ],
            'value' => [
                'required' => true,
                'type' => 'string',
                'description' => 'Item value'
            ]
        ]
    ]
]
<Request>
  <Item name="foo"><value>bar</value></Item>
  <Item name="buzz"><value>bar</value></Item>
</Request>

Thank you very much in advance for any hint!

Map a json-array into a Model

Hello,

I am trying to find a way to map a json-array to an array of Model with a json service description.

The json returned by the API is quite simple:

[
    {
        "id": "2017335",
        "name": "A"
    },
    {
        "id": "2017338",
        "name": "B"
    },
    {
        "id": "20173357",
        "name": "C"
    }
]

but although I have tried a lot of different ways, such as:

    "models": {
        "getMultipleOutput": {
            "type": "object",
            "additionalProperties": {
                "location": "json",
                "$ref": "SimpleOutput"
            }
        },
        "SimpleOutput": {
            "type": "object",
            "properties": {
                "id": {
                    "location": "json",
                    "type": "integer"
                },
                "name": {
                    "location": "json",
                    "type": "string"
                }
            }
        }
    }
    "models": {
        "getMultipleOutput": {
            "type": "object",
            "additionalProperties": {
                "location": "json",
                "type": "object",
                "properties": {
                    "id": {
                        "location": "json",
                        "type": "integer"
                    },
                    "name": {
                        "location": "json",
                        "type": "string"
                    }
                }
            }
        }
    }
    "models": {
        "getMultipleOutput": {
            "type": "object",
            "location": "json",
            "additionalProperties": {
                "location": "json",
                "type": "object",
                "properties": {
                    "id": {
                        "location": "json",
                        "type": "integer"
                    },
                    "name": {
                        "location": "json",
                        "type": "string"
                    }
                }
            }
        }
    }

and also

    "models": {
        "getMultipleOutput": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "location": "json",
                        "type": "integer"
                    },
                    "name": {
                        "location": "json",
                        "type": "string"
                    }
                }
            }
        }
    }

None of this works, some will return an empty array, other a GuzzleHttp\Exception\ParseException: Unable to parse JSON data: JSON_ERROR_SYNTAX - Syntax error, malformed JSON.

Could you tell me if this is possible with guzzle-services ?

Thank you very much in advance for any hint !

Totally Broken With Guzzle 5

[2014-10-24 16:16:42] production.CRITICAL: exception 'ErrorException' with message 'Argument 4 passed to GuzzleHttp\Command\Guzzle\Subscriber\ProcessResponse::visitOuterObject() must implement interface GuzzleHttp\Message\ResponseInterface, null given, called in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php on line 101 and defined' in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php:143
Stack trace:
#0 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php(143): Illuminate\Exception\Handler->handleError(4096, 'Argument 4 pass...', 'C:\\Program File...', 143, Array)
#1 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php(101): GuzzleHttp\Command\Guzzle\Subscriber\ProcessResponse->visitOuterObject(Object(GuzzleHttp\Command\Guzzle\Parameter), Array, Object(GuzzleHttp\Command\Command), NULL, Array)
#2 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php(90): GuzzleHttp\Command\Guzzle\Subscriber\ProcessResponse->visit(Object(GuzzleHttp\Command\Guzzle\Parameter), Object(GuzzleHttp\Command\Event\ProcessEvent))
#3 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Event\Emitter.php(109): GuzzleHttp\Command\Guzzle\Subscriber\ProcessResponse->onProcess(Object(GuzzleHttp\Command\Event\ProcessEvent), 'process')
#4 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(271): GuzzleHttp\Event\Emitter->emit('process', Object(GuzzleHttp\Command\Event\ProcessEvent))
#5 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(255): GuzzleHttp\Command\AbstractClient->emitProcess(Object(GuzzleHttp\Command\CommandTransaction))
#6 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Event\Emitter.php(109): GuzzleHttp\Command\AbstractClient->GuzzleHttp\Command\{closure}(Object(GuzzleHttp\Event\EndEvent), 'end')
#7 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(206): GuzzleHttp\Event\Emitter->emit('end', Object(GuzzleHttp\Event\EndEvent))
#8 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(91): GuzzleHttp\RequestFsm->end(Object(GuzzleHttp\Transaction))
#9 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RingBridge.php(121): GuzzleHttp\RequestFsm->__invoke(Object(GuzzleHttp\Transaction))
#10 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(140): GuzzleHttp\RingBridge::completeRingResponse(Object(GuzzleHttp\Transaction), Array, Object(GuzzleHttp\Message\MessageFactory), Object(GuzzleHttp\RequestFsm))
#11 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\react\promise\src\FulfilledPromise.php(24): GuzzleHttp\RequestFsm->GuzzleHttp\{closure}(Array)
#12 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\ringphp\src\Future\CompletedFutureValue.php(55): React\Promise\FulfilledPromise->then(Object(Closure), NULL, NULL)
#13 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Message\FutureResponse.php(43): GuzzleHttp\Ring\Future\CompletedFutureValue->then(Object(Closure), NULL, NULL)
#14 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(143): GuzzleHttp\Message\FutureResponse::proxy(Object(GuzzleHttp\Ring\Future\CompletedFutureArray), Object(Closure))
#15 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(91): GuzzleHttp\RequestFsm->send(Object(GuzzleHttp\Transaction))
#16 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Client.php(256): GuzzleHttp\RequestFsm->__invoke(Object(GuzzleHttp\Transaction))
#17 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(88): GuzzleHttp\Client->send(Object(GuzzleHttp\Message\Request))
#18 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(76): GuzzleHttp\Command\AbstractClient->execute(Object(GuzzleHttp\Command\Command))
#19 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\AbstractModel.php(92): GuzzleHttp\Command\AbstractClient->__call('stats', Array)
#20 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\AbstractModel.php(92): GuzzleHttp\Command\Guzzle\GuzzleClient->stats(Array)
#21 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\Zone.php(602): GrahamCampbell\CloudFlareAPI\Models\AbstractModel->get('stats', Array, '20')
#22 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\Zone.php(73): GrahamCampbell\CloudFlareAPI\Models\Zone->stat(20, 'trafficBreakdow...')
#23 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare\src\Controllers\CloudFlareController.php(96): GrahamCampbell\CloudFlareAPI\Models\Zone->getTraffic()
#24 [internal function]: GrahamCampbell\CloudFlare\Controllers\CloudFlareController->getData()
#25 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\laravel\framework\src\Illuminate\Routing\Controller.php(231): call_user_func_array(Array, Array)
#26 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5776): Illuminate\Routing\Controller->callAction('getData', Array)
#27 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5764): Illuminate\Routing\ControllerDispatcher->call(Object(GrahamCampbell\CloudFlare\Controllers\CloudFlareController), Object(Illuminate\Routing\Route), 'getData')
#28 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4971): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'GrahamCampbell\\...', 'getData')
#29 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#30 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5329): call_user_func_array(Object(Closure), Array)
#31 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4996): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#32 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4984): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#33 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(715): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#34 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(696): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#35 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\barryvdh\laravel-debugbar\src\Middleware.php(33): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#36 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(7744): Barryvdh\Debugbar\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#37 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(8351): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#38 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(8298): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#39 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(10957): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#40 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(657): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#41 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\public\index.php(57): Illuminate\Foundation\Application->run()
#42 {main}

Next exception 'GuzzleHttp\Command\Exception\CommandException' with message 'Error executing command: Argument 4 passed to GuzzleHttp\Command\Guzzle\Subscriber\ProcessResponse::visitOuterObject() must implement interface GuzzleHttp\Message\ResponseInterface, null given, called in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle-services\src\Subscriber\ProcessResponse.php on line 101 and defined' in C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php:171
Stack trace:
#0 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(275): GuzzleHttp\Command\AbstractClient->createCommandException(Object(GuzzleHttp\Command\CommandTransaction))
#1 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(255): GuzzleHttp\Command\AbstractClient->emitProcess(Object(GuzzleHttp\Command\CommandTransaction))
#2 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Event\Emitter.php(109): GuzzleHttp\Command\AbstractClient->GuzzleHttp\Command\{closure}(Object(GuzzleHttp\Event\EndEvent), 'end')
#3 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(206): GuzzleHttp\Event\Emitter->emit('end', Object(GuzzleHttp\Event\EndEvent))
#4 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(91): GuzzleHttp\RequestFsm->end(Object(GuzzleHttp\Transaction))
#5 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RingBridge.php(121): GuzzleHttp\RequestFsm->__invoke(Object(GuzzleHttp\Transaction))
#6 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(140): GuzzleHttp\RingBridge::completeRingResponse(Object(GuzzleHttp\Transaction), Array, Object(GuzzleHttp\Message\MessageFactory), Object(GuzzleHttp\RequestFsm))
#7 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\react\promise\src\FulfilledPromise.php(24): GuzzleHttp\RequestFsm->GuzzleHttp\{closure}(Array)
#8 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\ringphp\src\Future\CompletedFutureValue.php(55): React\Promise\FulfilledPromise->then(Object(Closure), NULL, NULL)
#9 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Message\FutureResponse.php(43): GuzzleHttp\Ring\Future\CompletedFutureValue->then(Object(Closure), NULL, NULL)
#10 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(143): GuzzleHttp\Message\FutureResponse::proxy(Object(GuzzleHttp\Ring\Future\CompletedFutureArray), Object(Closure))
#11 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\RequestFsm.php(91): GuzzleHttp\RequestFsm->send(Object(GuzzleHttp\Transaction))
#12 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\guzzle\src\Client.php(256): GuzzleHttp\RequestFsm->__invoke(Object(GuzzleHttp\Transaction))
#13 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(88): GuzzleHttp\Client->send(Object(GuzzleHttp\Message\Request))
#14 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\guzzlehttp\command\src\AbstractClient.php(76): GuzzleHttp\Command\AbstractClient->execute(Object(GuzzleHttp\Command\Command))
#15 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\AbstractModel.php(92): GuzzleHttp\Command\AbstractClient->__call('stats', Array)
#16 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\AbstractModel.php(92): GuzzleHttp\Command\Guzzle\GuzzleClient->stats(Array)
#17 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\Zone.php(602): GrahamCampbell\CloudFlareAPI\Models\AbstractModel->get('stats', Array, '20')
#18 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare-api\src\Models\Zone.php(73): GrahamCampbell\CloudFlareAPI\Models\Zone->stat(20, 'trafficBreakdow...')
#19 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\graham-campbell\cloudflare\src\Controllers\CloudFlareController.php(96): GrahamCampbell\CloudFlareAPI\Models\Zone->getTraffic()
#20 [internal function]: GrahamCampbell\CloudFlare\Controllers\CloudFlareController->getData()
#21 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\laravel\framework\src\Illuminate\Routing\Controller.php(231): call_user_func_array(Array, Array)
#22 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5776): Illuminate\Routing\Controller->callAction('getData', Array)
#23 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5764): Illuminate\Routing\ControllerDispatcher->call(Object(GrahamCampbell\CloudFlare\Controllers\CloudFlareController), Object(Illuminate\Routing\Route), 'getData')
#24 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4971): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'GrahamCampbell\\...', 'getData')
#25 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#26 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(5329): call_user_func_array(Object(Closure), Array)
#27 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4996): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#28 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(4984): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#29 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(715): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#30 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(696): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#31 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\vendor\barryvdh\laravel-debugbar\src\Middleware.php(33): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#32 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(7744): Barryvdh\Debugbar\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#33 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(8351): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#34 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(8298): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#35 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(10957): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#36 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\bootstrap\compiled.php(657): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#37 C:\Program Files (x86)\EasyPHP-DevServer-14.1VC11\data\localweb\public\index.php(57): Illuminate\Foundation\Application->run()
#38 {main} [] []

The interesting guzzle stuff happens in here: https://github.com/GrahamCampbell/Laravel-CloudFlare-API/blob/a7ae6e2cfe30af64f967d8235548b62327b2f850/src/Factories/ClientFactory.php.

This used to work with guzzle 4.2 and guzzle services 0.3.0 with guzzle command 0.6.0.

I am currently using guzzle 5.0.1 with guzzle services @0ad83bfcfdf53ee48de506ce8256a85d5d7aff3a and guzzle command 0.7.0.

Resouce Itterators

When will these be returning to guzzle 4? Could you suggest an alternative that would work with guzzle 4?

Parameter validation fails for union types

This exception comes up:

<br />
<b>Fatal error</b>:  Uncaught exception 'GuzzleHttp\Command\Exception\CommandException' with message 'Validation errors: [type] must be of type video or image' in /cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/guzzle-services/src/Subscriber/ValidateInput.php:69
Stack trace:
#0 /cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/guzzle/src/Event/Emitter.php(105): GuzzleHttp\Command\Guzzle\Subscriber\ValidateInput-&gt;onPrepare(Object(GuzzleHttp\Command\Event\PrepareEvent), 'prepare')
#1 /cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/command/src/Event/EventWrapper.php(38): GuzzleHttp\Event\Emitter-&gt;emit('prepare', Object(GuzzleHttp\Command\Event\PrepareEvent))
#2 /cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/command/src/AbstractClient.php(62): GuzzleHttp\Command\Event\EventWrapper::prepareCommand(Object(GuzzleHttp\Command\Guzzle\Command), Object(GuzzleHttp\Command\Guzzle\GuzzleClient))
#3 /cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/command/src/AbstractClient.php(56): GuzzleHttp\Command\AbstractCl in <b>/cygdrive/s/Project/streamly.clients/vendor/guzzlehttp/guzzle-services/src/Subscriber/ValidateInput.php</b> on line <b>69</b><br />

I've double checked that the parameter type is valid, in my case it is set to video but it still throws the exception above.

Question?

Is there an easy way to add custom transformers to yield objects other than Command\Model? I know I can use events, but that would be a bit hacky if I am using Services\Description. For example, if I were to do this:

$description = new Description([
    'baseUrl' => 'http://127.0.0.1:8080/',
    'operations' => [
        'users' => [
            'httpMethod' => 'GET',
            'uri' => '/api/users',
            'responseModel' => 'users'
        ]
    ],
    'models' => [
        'users' => [
            'type' => 'object',
            'additionalProperties' => [
                'location' => 'json'
            ]
        ]
    ]
]);

I'd like to be able to return a collection of users, not a "Model".

I hope I'm not missing something obvious. I'm fairly new to guzzle.

Question: Mocking a Response does not throw exception

Hi,
I'm currently trying to Test Error-Repsonses for my service-client and came accors the following issue.
If I create a Mock-Response according to the documentation:

$mock = new Mock(
    new Response(404, [], Stream::factory('Not found'))
);
$client->getEmitter()->attach($mock);

and after that I execute a command as described in a service-description I'm getting a response containing the body 'Not Found'

If I on the other hand make the same call on a real-life-server a

    GuzzleHttp\Command\Exception\CommandClientException

How do I get the mocked call to also create the same CommandClientException?

Allow to provide Post Body as an Array

I've been learning Guzzle for the last week, and figured out a lot of stuff, but can`t make my service description to use the passed parameters array and take the parameters tagged for location 'body' and combine into an string, using postFiled for location, almost do it, but interpolates the & symbol, it would be nice to pass the body parameters just like the request body option array.

http://docs.guzzlephp.org/en/latest/clients.html#request-options

Thank you, i'm eager to know about the production ready tag.

Where's the ServiceDescriptionLoader/AbstractConfigLoader?

I'm trying to upgrade from guzzle/service 3.x and noticed that ServiceDescription class has been removed. I've seen #15 and #18 regarding the upgrade path. However, the new Description class in guzzle/guzzle-services lacks support for the JSDL "includes" parameter (formerly handled by AbstractConfigLoader). With Guzzle3 the JSDL abstraction was absolutely critical to make the JSON files maintainable (especially to set default "errorResponses" parameter which AFAIK had to be set for each individual status code; see example below). Is there another package I should be referring to for this functionality?

e.g. MainServiceDesc.json:

    "includes": [
        "CommonModels.json"
    ],
    "operations": {
        "GetStuff": {
            "extends": "CommonServiceOperation",
            "uri": "stuff",
            "summary": "Display a list of stuff"
        },

and CommonModels.json:

{
    "name": "CommonModels",
    "apiVersion": "1.0",
    "description": "Common model and operations for the api",
    "operations": {
        "CommonServiceOperation": {
            "httpMethod": "GET",
            "errorResponses": [
                {
                    "code": 400,
                    "class": "My\\Api\\CustomResponseException"
                },
                {
                    "code": 401,
                    "class": "My\\Api\\CustomResponseException"
                },

References:

Unify `extraData` in Descriptions

I stumbled upon the fact that Descriptions use any information provided in the configuration array and add all keys it doesn't know to Description::$extraData. Operations on the other hand neglect these additional keys unless they are provided in $config['data'].
With this issue I would like to ask you, @mtdowling, for your reasoning behind this and whether you think that a unified API would make sense here.
I'm implementing a custom response parsing mechanism which requires an additional attribute in each Operation. At the moment, I have to pass this attribute via $config['data'].

GuzzleHTTP/Command Dependency fail

Hi,

There are a problem with guzzlehttp/command dependency.

In composer.json guzzlehttp/guzzle-services require guzzlehttp/command: ~0.2

so i got the 0.7 version.

But this version has a BC with version 0.2

Fatal error: Class GuzzleHttp\Command\Guzzle\GuzzleClient contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (GuzzleHttp\Command\AbstractClient::serializeRequest

Can you adapt with the new version of GuzzleHttp/Command or require stric 0.2 version.

Thx for reply,

support to load service description from file

Guzzle 3.7 had ConfigLoader to load service description from json file but config loading from file has been removed in services module. It would be nice to have that feature back which provided a good way to manage all the descriptions in one place.

Testing Guzzle Services doesn't work

Hi,

I'm trying to test a Guzzle Service I created:

The class I'm testing is the following

class DummyClient extends GuzzleClient
{
    /**
     * @param array $config
     *
     * @return GuzzleClient
     */
    public static function factory($config = array())
    {
        $client = new Client();
        $resource = __DIR__ . "resource.json";
        $jsonDescription=json_decode(file_get_contents($resource),true);
        $description = new Description($jsonDescription);
        return new GuzzleClient($client, $description);
    }

}

The test I wrote is the following:

    public function testListApps()
    {
        $client=DummyClient::factory();

        $stream=Stream::factory('{
                    "count" : 1,
                    "items" : [
                        {
                            "runtime_type" : "php",
                            "region" : "eu1",
                            "name" : "foobar",
                            "type":"hello",
                            "hostname" : "foobar.eu1.domain.net",
                            "created_at" : "2014-04-23 13:46:56",
                            "updated_at" : "2014-04-23 13:46:56",
                            "user" : {
                            "reference" : "jamkir853311",
                                "email": "[email protected]",
                                "created_at": "2014-04-23 13:46:56",
                                "updated_at": "2014-04-23 13:46:56",
                                "gravatar" : "d99e5294051d4d3d30a94f8ca5e510d3",
                                "forename" : "James",
                                "surname" : "Kirk"
                            },
                            "primary_domain" : "foobar.eu1.domain.net",
                            "storage_type" : "persistent"
                        }
                    ]}');

        // Create a mock subscriber and queue one response.
        $response = new Response(200, [], $stream);
        $mock = new Mock([
            $response
        ]);

        //var_export($response->json()); //This shows the JSON correctly

        // Add the mock subscriber to the client.
        // The first request is intercepted with the first response.
        $client->getHttpClient()->getEmitter()->attach($mock);

        //$result=$client->getHttpClient()->get('appsajiofj')->json(); //This works too
        $result=$client->listApps();

        var_export($result); // but this shows "NULL"
    }

Do you have any idea why the var_export shows null ?

Thanks in advance

query location array can be comma separated

I think it would be great if there could be a setting to switch the query location behavior to be comma separated rather than array based.

<?php
$description = [
    'operations' => [
        'GetData' => [
            'httpMethod' => 'GET',
            'responseModel' => 'getResponse',
            'parameters' => [
                'ids' => [
                    'type' => 'array',
                    'location' => 'query'
                ]
            ]
        ]
    ],
    'models' => [
        'getResponse' => [
            'type' => 'object',
            'additionalProperties' => [
                'location' => 'json'
            ]
        ]
    ]
];

It would be nice to be able to do something like this

$client = new Client();
$client->GetData(['ids' => ['one', 'two']]);

This would output ?ids=one,two

errorResposnes from operation is never used

Hi,

In the Operation descriptor, there is a "errorResponses" hash that is supposed to be used. While it's read by the operation, it seems to be never used elsewhere in the code. As a consequence, user defined exception are never triggered.

Did I miss something or is the doc outdated? :)

Thanks!

[Fix included] XmlLocation requires text value to have attributes

Hi,

The XmlLocation requires the xml to have a "text" value to have the content of the attributes.

Thus, xml like:

<foo bar="12" />

Won't work.

Easy fix: move the line 240: $result = array_merge($attributes, $result);, outside the if ($text !== null).

I can fork and make pull request if needed.

Where did the documentation go?

I wrote code using Guzzle 4 services about 6 months ago and used documentation of the service description array options, however, I now can no longer find this documentation any where.

Where is the documentation for the description array options?

Tag version 0.4.0

Please tag a new version, presumably 0.4.0.

It seems that 0.3.0 is broken, and the current README.md already recommends

"guzzlehttp/guzzle-services": "0.4.*"

Question

How do I set parameters to go into the url in a Description. I know I can set them as query parameters as documented on the readme, but how do I inject parameters into the url itself?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.