I tried to convert an AJAX API request script into php using Guzzle, however I keep getting a '400 Bad Request' error. The Ajax version works fine.But I'm trying to automate the process in the back end. The script sends a file to the remote API via a 'POST' request and is meant to return a JSON object back which I then save it to a file.
Most of the possible solutions I found(googled for) involved either doing some exception handling or straight deactivating the guzzle errors. None of which worked. I know that the credentials are all correct because I tested with wrong credentials and it returned an authorization error.
This AJAX code works fine, it gets a file from an html form and uploads it to the API server.
$('#btnUploadFile').on('click', function () {
var data = new FormData();
var files = $("#fileUpload").get(0).files;
for (var i = 0; i < files.length; i++) {
data.append("audioFiles", files[i]); }
data.append("scoresTypes", JSON.stringify([46, 47]));
data.append("Flavor", 1);
data.append("AgentUsername", 'person#email.com');
var ajaxRequest = $.ajax({ type: "POST", url: 'https://remoteserver.com/api/',
headers: { 'Authorization': 'Basic ' + btoa('username' + ':' + 'password') },
scoresTypes: "",
contentType: false,
processData: false,
data: data,
success: function (data) { $("#response").html(JSON.stringify(data)); } });
ajaxRequest.done(function (xhr, textStatus) { });
});
});
This is the PHP code that returns the error '400 Bad Request' to the file
public function sendFile($file_path, $file_name){
$client = new Client();
$url = 'https://remoteserver.com/api/';
$credentials = base64_encode('username:password');
$audio = fopen($file_path, 'r');
$data = [];
$data['audioFiles'] = $audio;
$data['scoresTypes'] = json_encode([46, 47]);
$data['Flavor'] = 1;
$data['AgentUsername'] = 'person#email.com';
$json_file = '/path/'.$file_name.'.json';
try{
$response = $client->request('POST', $url, [
'headers' => [
'Authorization' => 'Basic '.$credentials,
],
'scoresTypes' => '',
'contentType' => 'false',
'processData' => false,
'data'=>$data
]);
$response_s = json_encode($response);
}
catch(RequestException $e) {
$response_s = $e->getResponse()->getBody();
}
Storage::disk('disk_name')->put($json_file, $response_s);
So this is the output that the PHP function is saving to the file instead of the expected JSON object.
{"code":14,"message":"There are no values in scoresTypes or JobTypes keys, please insert valid values in one, or both of them.","responseStatusCode":400}
But as you can see the initial data provided to the ajax version seems to be the same as the one I send in the php request.
have you tried setting the Content-Type to multipart/form-data since you are sending files, i think the default header for post request is application/x-www-form-urlencoded
I'm not a guzzle expert but from what i saw on the examples here you can use something like this instead
http://docs.guzzlephp.org/en/latest/quickstart.html?highlight=file#sending-form-files
<?php
$response = $client->request('POST', 'http://httpbin.org/post', [
'multipart' => [
[
'name' => 'field_name',
'contents' => 'abc'
],
[
'name' => 'file_name',
'contents' => fopen('/path/to/file', 'r')
],
[
'name' => 'other_file',
'contents' => 'hello',
'filename' => 'filename.txt',
'headers' => [
'X-Foo' => 'this is an extra header to include'
]
]
]
]);
Related
I want get response from PHP(CODEIGNIER), I am making POST calls to PHP file via URL since, everything is in cloud.
I am using REACT JS as Front-end
PHP FILE
public function let_customer_login(){
$strRequestType = $this->input->method();
var_dump($this->input->post());
$this->_decode_data();
$str_mobile_or_email = $this->input->$strRequestType("sleLoginEmail",true);
die("diers here");
if(is_numeric($str_mobile_or_email)){
$arr_validation_inputs = array('mobilenum'=>'sleLoginEmail','password'=>'sleLoginPassword');
}else{
$arr_validation_inputs = array('email'=>'sleLoginEmail','password'=>'sleLoginPassword');
}
$bln_or_arr_validation_response = $this->validate_inputs($arr_validation_inputs);
if(is_array($bln_or_arr_validation_response)){
$this->Customer_model->save_customer_login_history();
echo json_encode(array('Status' => false, 'id' => $bln_or_arr_validation_response['id'], 'Errors' => $bln_or_arr_validation_response['error']), JSON_PRETTY_PRINT);
}else{
$int_customer_id = $this->Customer_model->customer_login_credentials_check();
if($int_customer_id){
$int_customer_groupid = $this->Customer_model->get_customer_group_based_on_customer_id($int_customer_id);
$this->_set_session_for_customer_info($int_customer_id,$int_customer_groupid);
$this->Customer_model->save_customer_login_history();
echo json_encode(array('Status' => true, 'id' => "sleLoginEmail", 'Errors' => "success", "UserID" => $int_customer_id), JSON_PRETTY_PRINT);
}else{
$this->Customer_model->save_customer_login_history();
if(is_numeric($str_mobile_or_email)){
echo json_encode(array('Status' => false, 'id' => "sleLoginEmail", 'Errors' => "Mobile number and/or password is incorrect. Please try again or create new account."), JSON_PRETTY_PRINT);
}else{
echo json_encode(array('Status' => false, 'id' => "sleLoginEmail", 'Errors' => "Email address and/or password is incorrect. Please try again or create new account."), JSON_PRETTY_PRINT);
}
}
}
}
Here is my React file the below fn. is called when the button is clicked.
REACT FILE
const letUserSignin = () => {
const userCred = {
"sleLoginEmail": formik.values.loginCred,
"sleLoginPassword": formik.values.loginPassword
}
fetch("[url]/controller/let_customer_login",{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userCred),
redirect: 'follow',
mode: 'no-cors'
})
.then( response => response.json())
.then( data => {
debugger; // debugger is not hitting
console.log(data)
})
.catch( err => console.log(err))
}
In console it throws error as
SyntaxError: Unexpected token < in JSON at position 2
GET REQUEST is working for the same file but POST REQUEST is not event hit the front-end
I try to send the file via GuzzleHTTP from my application to external API, I make it like this:
public function storeImagesInAmazon(Request $request) {
$uploadFilePath = 'some/endpoint';
$file = $request->file('file');
$client = new Client();
$response = $client->request('POST', $uploadFilePath, [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data',
],
'multipart' => [
[
'name' => 'file',
'contents' => $file
]
]
]);
$result = json_decode($response->getBody(), true);
return [
'hashedID' => $result['hashedID']
];
}
The error I get is:
Server error: POST some/endpoint resulted in a 500 Internal Server Error response:\n
Errorerror while processing file: Failed to process file: part was null
I tested it via Postman, adding key = 'file', value = 'some_file.pdf' in Body form-data, I am sure file is correct, I mean it isn't damaged, I tried to post different files large one, a small one, pdf or jpg/png.
But I still have this issue and I can't find a solution for this.
I found this solution Guzzle form_params not accepting array
what I'm trying to say is, you need $option as your next param like in that post
$response = $client->post('api', $options);
and that $option is where your headers or multipart or other options goes as per documentation. i already tried using $options and its worked in my case.
I am uploading a file to my API built on laravel. In my code below, the data is sent to the API. But how can i get the file that was uploaded to the API ?
Controller
$file = $request->file('imported-file');
$name = $file->getClientOriginalName();
$path ='/Users/desktop/Folder/laravelapp/public/Voice/';
$client = new \GuzzleHttp\Client();
$fileinfo = array(
'message' => 'Testing content',
'recipient' => "102425",
);
$res = $client->request('POST', $url, [
'multipart' => [
[
'name' => 'FileContents',
'contents' => file_get_contents($path . $name),
'filename' => $name
],
[
'name' => 'FileInfo',
'contents' => json_encode($fileinfo)
]
],
]);
API Controller
if (!empty('FileInfo')) {
return response()->json([
'status' => 'error',
'file_content' => $request->file('FileContents'),
'media'=>$request->hasFile('FileContents'),
]);
}
This is the response, i get "file":null,"file_content":{},"media":true
Why is the file content empty when media is showing true meaning there is a file ?
There can be multiple reasons :
Check your content type. Sometimes we forget to specify multipart/form-data and the request is sent with generic application/x-form-urlencoded etc.
Secondly if you are using jQuery, then set :
contentType: false,
processData: false,
cache: false
This will help your form request no getting converted to string payload and not forcing ajax to set content type. try using FormData.
Update : Found similar answer in this post has detailed answer for this.
i have a node js api that send file like this
exports.myFunction = function(req, res) {
res.sendFile("path_to_file");
}
and in php i try to read the file received like this :
$client = new GuzzleHttp\Client();
$res = $client->post('http://www.example.com',
['headers' => ['Authorization' => 'Bearer my token',
'content-type' => 'application/json'
],
'body' =>json_encode(['id'=>'5bf7c8cfe58e316de4d3ae89', 'type'=>'default'])
]);
echo $res->getBody();
but i don't get the file, and i get this :
�PNG IHDR���f IDATx��w`U���of��g�zo �(�����O=���,�X���b�Į��N�қT!�PI
is working in postman (raw format data with with application/json type)
with guzzle6
url-http://vm.xxxxx.com/v1/hirejob/
{
"company_name":" company_name",
"last_date_apply":"06/12/2015",
"rid":"89498"
}
so am getting response 201 created
but in guzzle
$client = new Client();
$data = array();
$data['company_name'] = "company_name";
$data['last_date_apply'] = "06/12/2015";
$data['rid'] = "89498";
$url='http://vm.xxxxx.com/v1/hirejob/';
$data=json_encode($data);
try {
$request = $client->post($url,array(
'content-type' => 'application/json'
),array());
} catch (ServerException $e) {
//getting GuzzleHttp\Exception\ServerException Server error: 500
}
i am getting error on vendor/guzzlehttp/guzzle/src/Middleware.php
line no 69
? new ServerException("Server error: $code", $request, $response)
You're not actually setting the request body, but arguably the easiest way to transfer JSON data is by using the dedicated request option:
$request = $client->post($url, [
'json' => [
'company_name' => 'company_name',
'last_date_apply' => '06/12/2015',
'rid' => '89498',
],
]);
You need to use json_encode() JSON_FORCE_OBJECT flag as the second argument. Like this:
$data = json_encode($data, JSON_FORCE_OBJECT);
Without the JSON_FORCE_OBJECT flag, it will create a json array with bracket notation instead of brace notation.
Also, try sending a request like this:
$request = $client->post($url, [
'headers' => [ 'Content-Type' => 'application/json' ],
'body' => $data
]);