saloonphp / saloon

🤠 Build beautiful API integrations and SDKs with Saloon
https://docs.saloon.dev
MIT License
2.03k stars 105 forks source link

Cannot Have Request with `headers` #376

Closed davidhemphill closed 5 months ago

davidhemphill commented 6 months ago

Hi! I'm using Saloon to create an SDK for a project. I have a request class I would like to have this API:

namespace Project;

use Saloon\Contracts\Body\HasBody;
use Saloon\Enums\Method;
use Saloon\Http\Request;
use Saloon\Traits\Body\HasJsonBody;

class CreateRequest extends Request implements HasBody
{
    use HasJsonBody;

    protected Method $method = Method::POST;

    public function __construct(public string $name, public array $headers = [], public array $payload = [])
    {
    }

    public function resolveEndpoint(): string
    {
        return '/endpoint';
    }

    public function defaultBody(): array
    {
        return [
            'name' => $this->name,
            'headers' => $this->headers,
            'payload' => $this->payload,
        ];
    }
}
$connector = new ProjectConnector;

$request = CreateRequest::make(
    name: 'test',
    headers: ['foo', 'bar'],
    payload: ['boo' => 'baz'],
);

$response = $connector->send($request);

I'm not able to use this as it causes a type error since headers is already defined on Request via HasHeaders using a different type.

I would love to find a way around this since it makes most sense for my users to be able to use the header parameter name.

Thank you!

davidhemphill commented 6 months ago

Upon looking further, if I wanted to switch payload to be named body, I would run into this problem again.

I understand it's probably an esoteric problem due to my project's nature, but maybe not?

Sammyjo20 commented 6 months ago

Hey @davidhemphill I hope you are well!

I think you may just be a little unlucky in this scenario where you have run into property names that are already being used by Saloon behind the scenes. You would need to change the names of the properties in your constructor for it to work, Sadly. Sorry!

For headers you could have:

Or you could use a DTO to pass in the fields?

public function __construct(public CreateRequestData $data)
{
}

public function defaultBody(): array
{
    return [
        'name' => $this->data->name,
        'headers' => $this->data->headers,
        'payload' => $this->data->payload,
    ];
}

With the DTO approach, you could have the same names!

Sammyjo20 commented 5 months ago

Hey @davidhemphill I hope you're doing well. Did my last response help resolve the issue you were having?

davidhemphill commented 5 months ago

Hi @Sammyjo20, I wound up resolving this by using a DTO. Thanks!