Git Product home page Git Product logo

Comments (14)

ilukac avatar ilukac commented on June 19, 2024 1

Hi,

Just to confirm I had similar issues with setting the base uri. Finally found this thread and made it work with:

$plugin = new AddHostPlugin(new Uri('https://foo.bar/'), ['replace' => true,]);
$pluginClient = new PluginClient( HttpClientDiscovery::find(), [$plugin] );
$apiClient = Client::create($pluginClient);

but it should be somehow configurable, or at least covered in install docs.

from janephp.

damienalexandre avatar damienalexandre commented on June 19, 2024

I handle this kind of need by providing my own HTTPlug client to the created Client.

Example with Symfony Httplug:

httplug:
    clients:
        api_client_with_host:
            factory: 'httplug.factory.guzzle6'
            plugins:
                - add_host:
                    host: 'acc-preprod-staging.com'
                    replace: true
services:
    MyGeneratedBlaBla\Resource\MyResource:
        arguments:
            - '@httplug.client.api_client_with_host'
            - '@httplug.message_factory'
            - '@foobar.chained_serializer'

At the end, it's only about being able to build the proper HTTPlug client. The fact I use Symfony has nothing to do with it.

You could try this:

$plugin = new AddHostPlugin('domain.com'), [
    'replace' => true,
]));

$pluginClient = new PluginClient(
    HttpClientDiscovery::find(),
    [$plugin]
);

from janephp.

melkamar avatar melkamar commented on June 19, 2024

Thank you for your reply! It's not completely clear to me though. I am using Symfony as well, but as you say, that does not affect anything.

Creating the PluginClient() which includes a HostPlugin is not a problem. Passing that client to the Jane Client (class Client extends \Jane\OpenApiRuntime\Client\Psr7HttplugClient) is where the problem lies.

A part of the Client class is as follows:

class Client extends \Jane\OpenApiRuntime\Client\Psr7HttplugClient
{
    public static function create($httpClient = null)
    {
        if (null === $httpClient) {
            $httpClient = \Http\Discovery\HttpClientDiscovery::find();
            $plugins = array();
            $uri = \Http\Discovery\UriFactoryDiscovery::find()->createUri('http://example.org/some/endpoint');
            $plugins[] = new \Http\Client\Common\Plugin\AddPathPlugin($uri);
            $plugins[] = new \Http\Client\Common\Plugin\AddHostPlugin($uri);
            $httpClient = new \Http\Client\Common\PluginClient($httpClient, $plugins);
        }
        $messageFactory = \Http\Discovery\MessageFactoryDiscovery::find();
        $streamFactory = \Http\Discovery\StreamFactoryDiscovery::find();
        $serializer = new \Symfony\Component\Serializer\Serializer(...);
        return new static($httpClient, $messageFactory, $serializer, $streamFactory);
    }
}

(this is the case when both basePath and host are provided; when host is omitted, the AddHostPlugin() call is dropped)

If I create the PluginClient and pass it to the method, the whole logic if appending the path to the client is skipped. However, this is the part that I want executed, because my PluginClient only contains information about the host, not the basePath.

from janephp.

pyrech avatar pyrech commented on June 19, 2024

I had more or less the same problem with our Slack client so I had to manually readd this logic in our own client, see https://github.com/jolicode/slack-php-api/blob/master/src/ClientFactory.php#L33-L42 for an example 😉

from janephp.

melkamar avatar melkamar commented on June 19, 2024

This requires you to know the host and path to the service though, doesn't it? This does not allow you to change the URL based on the environment you are runnign in. I am trying to have the basePath part of the Client configuration stored in the yaml spec and the host in a configuration file elsewhere.

I could read both those files and then construct the Client by hand, but that seems clunky and redundant, especially since Jane already reads the yaml spec file.

from janephp.

joelwurtz avatar joelwurtz commented on June 19, 2024

You could do what @pyrech have done but instead of hardcoding the hostname passing it to the method as a parameter :

public static function create(string $host, HttpClient $httpClient = null)

Then on symfony you can use env parameters to change the URL passed to this method.

Normally you would use this method (static create) only on prototyping / testing, otherwise i recommend you to create the services chain by using DIC of symfony.

from janephp.

melkamar avatar melkamar commented on June 19, 2024

I recommend you to create the services chain by using DIC of symfony

Good to know. I think it's worth documenting in some "best practices" way.

Pardon my ignorance, but I am still not getting it.

First, in order to change the static create() function I would have to manually edit the generated code. That would get overwritten whenever the underlying spec changes. I want to be able to re-generate the code and use it with no manual edits on my part.

Second, let's say I don't use the create() factory method at all. I construct the HttpClient object myself and pass it into the generated Client. It has to already have both host and basePath plugins/properties provided, correct? And I do not see a way to be able to read the basePath property from the generated code. Here I am trying to avoid having to re-read and parse the spec file.

Are my assumptions correct?

from janephp.

joelwurtz avatar joelwurtz commented on June 19, 2024

First, in order to change the static create() function I would have to manually edit the generated code. That would get overwritten whenever the underlying spec changes. I want to be able to re-generate the code and use it with no manual edits on my part.

You should not edit the generated code but instead create your own class which can extend the existing one and which have the static method.

Second, let's say I don't use the create() factory method at all. I construct the HttpClient object myself and pass it into the generated Client. It has to already have both host and basePath plugins/properties provided, correct? And I do not see a way to be able to read the basePath property from the generated code. Here I am trying to avoid having to re-read and parse the spec file.

There is no way to read it without parsing the spec file, you are correct.

It may be something to add (like having some methods returning base path / etc ...) but AFAIK updating the host in the spec is very rare so just writing it down in your env without parsing it is fine most of the time.

We use a lot Jane in our projects and we never trust those value and instead use our own configured by the DIC of Symfony.

from janephp.

melkamar avatar melkamar commented on June 19, 2024

It may be something to add (like having some methods returning base path / etc ...) but AFAIK updating the host in the spec is very rare so just writing it down in your env without parsing it is fine most of the time.

I agree. We want the host to be defined in our parameters, so that we can control where requests are being made in which environment.

We use a lot Jane in our projects and we never trust those value and instead use our own configured by the DIC of Symfony.

We use the spec files provided to use by a third party with which we integrate. The base path should not change much, but if it did, I would expect that change to be in the provider's jurisdiction. And as such, it makes sense to me to "trust" that value. Maybe not the host, which can be behind proxies or something, but the basePath seems that it should be "stable".

In any case, to conclude - I will define both host and basePath in config files and fetch from DIC. Feature request would be storing the parsed basePath (and maybe host as well) in a protected member variable instead of hardcoding that string in the create() method.

I can make a MR if I find some free time. Thank you!

from janephp.

Korbeil avatar Korbeil commented on June 19, 2024

Actually you can set it through the servers field in your OpenApi spec, see https://github.com/janephp/janephp/blob/master/src/OpenApi/Tests/fixtures/client-psr18/swagger.json#L15-L22 for an example (only one url is needed to generate it)

If you have multiple server urls, there is actually no way to set it through OpenApi spec, so you have to use your own plugin 👍

from janephp.

ilukac avatar ilukac commented on June 19, 2024

Hm, I am not in control of the json openapi file, I just read it :/

from janephp.

Korbeil avatar Korbeil commented on June 19, 2024

So you have to use the plugin like you said in your last comment.
About docs, we use plugins from php-http, you can see their docs here: http://docs.php-http.org/en/latest/plugins/index.html

from janephp.

letharion avatar letharion commented on June 19, 2024

Actually you can set it through the servers field in your OpenApi spec, see https://github.com/janephp/janephp/blob/master/src/OpenApi/Tests/fixtures/client-psr18/swagger.json#L15-L22 for an example (only one url is needed to generate it)

If you have multiple server urls, there is actually no way to set it through OpenApi spec, so you have to use your own plugin +1

It seems to me like the OpenAPI spec does support multiple servers listed, or am I misunderstanding something?

from janephp.

Korbeil avatar Korbeil commented on June 19, 2024

It seems to me like the OpenAPI spec does support multiple servers listed, or am I misunderstanding something?

Sorry, I was talking about Jane support of servers field, since we don't have a way to know which server we should use, we only take the first one.

I'm gonna close this issue since it's an old one and doesn't have a clear meaning actually, feel free to open a new one if needed.

from janephp.

Related Issues (20)

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.