thephpleague / oauth2-client

Easy integration with OAuth 2.0 service providers.
http://oauth2-client.thephpleague.com
MIT License
3.63k stars 751 forks source link

Create multipart/form-data requests? #985

Open Lindstromer opened 1 year ago

Lindstromer commented 1 year ago

I'm having issues creating a request with an attached file. Tried a lot of different alternatives but always end up with issues.

Seems like Guzzle in itself handles this, but the oauth2-client is limiting the getAuthenticatedRequest method to using only " Any of "headers", "body", and "protocolVersion".".

Example where it says to not specify form-data: https://stackoverflow.com/questions/47550801/multiple-files-uploaded-via-guzzle-multipart-form-data-request-are-not-recognize

Another discussion regarding this, I tried following it but cannot get it to work. Guzzle complains about it being an invalid resource type "array" while doing so: https://stackoverflow.com/questions/58736361/replicate-curl-multipart-form-data-request-with-guzzle-league-oauth2-client?rq=1

Error is thrown in the streamFor method found in Utils.php located in guzzlehttp vendor/psr7/src/Utils.php.

Anyone tried this and got it to work? Any help would be very appreciated.

fverry commented 1 year ago

You can make it work with this following extra code :

if (isset($options['multipart']))
{
    $multipartStream = new GuzzleHttp\Psr7\MultipartStream($options['multipart']);
    $boundary = $multipartStream->getBoundary();
    $options['headers']['content-type'] = "multipart/form-data; boundary={$boundary}";
    $options['body'] = $multipartStream;
    unset($options['multipart']);
}

It is inspired from GuzzleHttp\Client::applyOptions() which you should read.

As stated by this stackoverflow answer, the only keys allowed in League\OAuth2\Client\Provider\AbstractProvider::getAuthenticatedRequest()'s $options are "headers", "body", and "protocolVersion".

Thus in the following code, the "multipart" key in the $options array will be ignored.

$multipart = [];
$multipart[] = [
    'name'     => "documents[{$key}]",
    'contents' => GuzzleHttp\Psr7\Utils::tryFopen($file['tmp_name'], 'r'),
    'filename' => $file['name'],
];
$options['multipart'] = $multipart;
$request = $provider->getAuthenticatedRequest($method, $url, $token, $options);