Laravel HTTP Client - Posting XML file as application/octet-stream - php

I am trying to post to an external API, that accepts a XML file. The content type is application/octet-stream.
This is my code:
return Http::withToken(config('sproom.auth_token'))
->withHeaders([
'Content-Type' => 'application/octet-stream'
])
->attach('xml', file_get_contents('myfile.xml'), 'myfile')
->post('https://example.org/api/documents')->json();
When posting the above, I get an API error back: Cannot find format for document. No further documentation exists.
I am guessing that the xml file is not being sent correctly as application/octet-stream.
The external API is using Swagger as "documentation", and if I upload the XML file using the Swagger UI, I get a success response. Here in cURL:
curl -X POST "https://example.org/api/documents" -H "accept: */*" -H "Authorization: Bearer vmFrxk2+7......." -H "Content-Type: application/octet-stream" -d {}
I am not sure what I am doing wrong?

I don't think that the content type of the request is application/octet-stream, Also in the curl request you have written above has a -d
curl -X POST "https://example.org/api/documents" -H "accept: */*" -H "Authorization: Bearer vmFrxk2+7......." -H "Content-Type: application/octet-stream" -d {}
This is what is written in man curl
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP
server, in the same way that a browser does when a user has
filled in an HTML form and presses the submit button. This will
cause curl to pass the data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
If you are using ->attach, I guess the request should be multipart/form-data.
So please do see which one you need I guess you can't post files in application/x-www-form-urlencoded.
I don't think there is an option currently to attach content type to a file in attach(), so you can try using guzzle directly. It comes with laravel by default and httpclient is a wrapper over it to reduce the code.
Here is the direct guzzle code
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . config('sproom.auth_token')]]);
$client->request('POST', 'https://example.org/api/documents', [
'headers' => [
'Accept' => '*/*'
],
'multipart' => [
[
'name' => 'myfile',
'contents' => file_get_contents('myfile.xml'),
'headers' => ['Content-Type' => 'application/octet-stream'],
'filename' => 'myfile.xml'
]
]
]);

Ultimately, I ended up using Guzzle directly:
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . config('sproom.auth_token')]]);
try {
return $client->request('POST', config('sproom.api_url') . '/api/documents', [
'body' => file_get_contents('myfile.xml'),
'headers' => [
'Content-Type' => 'application/json',
]
])->getBody();
} catch (RequestException $exception) {
return json_decode($exception->getResponse()->getBody()->getContents());
}

Related

Convert Curl command to PHP Guzzle for multiple file uploads

I wanted to convert following Curl command line to php/curl but for many reasons my customer wants guzzle in PHP.
curl -X POST "https://uploadexample.net/api/upload" -H "accept: application/json" -H "Authorization: bearer: 928292992qwg" -H "Content-Type: multipart/form-data" -F "front_photo=#photo-1-214x300.jpg;type=image/jpeg" -F "back_photo=#photo-2-214x300.jpg;type=image/jpeg"
I have never used guzzle but I tried to manually convert above Curl to this guzzle routine. I get 500 server error. Am I converting correctly?
I was trying to stay as close to original curl as possible.
$headers = [
'Content-type' => 'application/json',
'Content-type' => 'multipart/form-data',
'Accept' => 'application/json',
"Authorization" => "Bearer 928292992qwg"
];
$client = new Client([
Base URI is used with relative requests
'base_uri' => 'https://exampleuploadrx.net',
]);
$response = $client->request('POST', '/api/upload', [
'json' => [
'front_photo' => new CURLFile('photo-1-214x300.jpg;type=image/jpeg'),
'back_photo' => new CURLFile('photo-2-214x300.jpg;type=image/jpeg'),
],
'headers' => $headers,
]
);

How to pass -d (Data) via a symfony curl post request

I was wondering if anyone could point me in the right direction.
We setup an api that will take a curl request such as
curl -X 'POST' 'url target' -H 'accept: application/json' -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=some_user_name&password=some_password
Trying to write ethe request in symfony 6, it seems like i'm setting it up wrong and not placing the -d data into the correct area.
It doesn't appear to go into the user_data field as i get an error 422 back from the server.
$response = $this->client->request('POST', $url_target, [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
'verify_peer' => false,
'verify_host' => false,
'data' => 'username=some_user_name&password=some_password'
]);
I was wondering if someone could point me in the right direction as i'm pretty sure i'm doing something stupid.
You need to pass your data in the body parameter:
$response = $this->client->request('POST', '', [
// other params ...
'body' => ['username' => 'some_user_name', 'password' => 'some_password']
]
);

How to send a file from URL through POST request using Guzzle

The endpoint what I'm using works fine when I tested it in this way:
curl -X POST ".../api/save" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=#test.xlsx;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Now I need to send the file using Guzzle in Laravel, but I got 400 Bad Request from the API endpoint. The file is stored in the public disk, so I'm sending the URL.
This is what I have so far:
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data',
];
$response = $this->client->request('POST', '.../api/save', [
'headers' => $headers,
'multipart' => [
[
'name' => 'image_file',
'contents' => $file->url,
]
]
]);
what you are trying to do is breaking some http protocols.
you can't, in a request, send a ressource link and expect the server to download it before resuming request treatment.
Either you download the file from the url and include its content in your request,
OR
send the url and have the code logic on the server to download it.

Convert a cURL [GET] request to Guzzle

I have this curl request:
curl -k -H"Authorization: Bearer 905290532905902390523905krai20" https://example.com/something?limit=1
Bearer is a token_type ($token_type).
The long string is an access token ($access_token)
How can I convert this to a Guzzle request? I already converted another curl POST request to Guzzle, but this isn't the same deal.
Well, I've never used this library in my life, but after a quick look at the documentation, it seems this should work:
$client = new GuzzleHttp\Client([
'base_uri' => 'https://example.com/something?limit=1'
]);
$client->request('GET', '/get', [
'headers' => [
'Authorization' => 'Bearer 905290532905902390523905krai20',
]
]);

Curl to GuzzleHttp request

I have been given the following curl request:
curl -H "Content-Type:application/json" -H "Api-Key:someapikey" -X -d {"address":"30598 West Street","city":"Oakdale"}' PUT "https://somedomain/api/members/1234567"
I am trying to replicate this with GuzzleHttp like so:
$headers = [
'Api-Key' => $this->apiKey,
'Content-Type' => 'application/json',
];
$client = new Client([
'headers' => $headers,
]);
$res = $client->put("{$this->baseUrl}/members/{$fields['vip_id']}", [
'form_params' => $fields,
]);
I keep on getting a 415 Unsupported Media Type response. From the curl I was given I think I have all my bases covered. However, when I debug it shows that my Content Type is set to application/x-www-form-urlencoded. According to the documentation, the header is set to this only if the Content-Type header isn't already set and form_params is included. As I am already setting this header, it shouldn't be switching right? Please help!
The reason your headers are being overridden is because the form_params option to the request is specifically for sending x-www-form-urlencoded data.
You can omit the Content-Type header from your options completely and instead use the json key in the request to send JSON data.
$headers = [
'Api-Key' => $this->apiKey,
];
$client = new Client([
'headers' => $headers,
]);
$res = $client->put("{$this->baseUrl}/members/{$fields['vip_id']}", [
'json' => $fields, // causes Guzzle to set content type to application/json
// and json_encode your $fields
]);

Categories