Sending form data with guzzle throws server error - php

I'm sending form data, "packed" in URL using Guzzle to my JasperReports which is installed on another server. URL consists of form data and it's super long.
All the time, I'm receiving 500 Internal Server Error.
$headers = [
'url' => $url,
];
this->client = new Client(['base_uri' => 'http://localhost:8080/jasper-r/report.jsp?id=0']);
try {
$promise = $this->client->request('POST', ["headers" => $headers]);
return response($promise->message_id);
} catch (RequestException $e) {
return abort($e->getMessage());

Related

Laravel eloquent in Lumen api dont save when data comes from HTTP Client Laravel, but when i test with Postman that works

I have a page with send data to an Lumen API. I send the data using the Laravel Http Client, like this:
$url = env('API_ADDRESS');
$data= [
'p1' => $request->input('p1'),
'p2' => $request->input('p2')
];
$headers = [
'key' => env('API_KEY')
];
$req = Http::withHeaders($headers)->post($url, $data);
The status code from this request is 200.
In my API, i have a code like to receive the data and save it:
public function SaveReq(Request $request)
{
$data = [
'status'=> 'success',
'msg'=> ''
];
try {
$req = new Requisition();
$req->p1 = $request->input('p1');
$req->p2 = $request->input('p2');
$req->save();
} catch (ErrorException $e) {
$data['status'] = 'error';
$data['msg'] = $e->getMessage();
} finally {
return json_encode($data);
}
}
In my application that send the request, i can see the json of the api returns, but the api dont save the data, but if i send a request with this same data using Postman, my api save the data.
What am i doing wrong in the application that sends the data?
check http method in your application and postman be same
before save data , use dd($request->all()); to sure data
send correctly

Guzzle does not send a post request

i'm using PHP with Guzzle.
I have this code:
$client = new Client();
$request = new \GuzzleHttp\Psr7\Request('POST', 'http://localhost/async-post/tester.php',[
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
'form_params' => [
'action' => 'TestFunction'
],
]);
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
For some reason Guzzle Doesn't send the POST Parameters.
Any suggestion?
Thanks :)
I see 2 things.
The parameters have to go as string (json_encode)
And you were also including them as part of the HEADER, not the BODY.
Then i add a function to handle the response as ResponseInterface
$client = new Client();
$request = new Request('POST', 'https://google.com', ['Content-Type' => 'application/x-www-form-urlencoded'], json_encode(['form_params' => ['s' => 'abc',] ]));
/** #var Promise\PromiseInterface $response */
$response = $client->sendAsync($request);
$response->then(
function (ResponseInterface $res) {
echo $res->getStatusCode() . "\n";
},
function (RequestException $e) {
echo $e->getMessage() . "\n";
echo $e->getRequest()->getMethod();
}
);
$response->wait();
In this test Google responds with a
Client error: POST https://google.com resulted in a 405 Method Not Allowed
But is ok. Google doesn't accepts request like this.
Guzzle isn't truely asynchronous. It's more of multi-threading. That is why you have the wait() line to prevent the your current PHP script from closing until all multiple spun threads finish. If you remove the wait() line, the PHP process spun by the script ends immediately with all it's threads and your request is never sent.
Ergo, you need Guzzle (and Curl) for multi-processing(concurrent) I/O and not for asynchronous I/O. In your case, you are processing one request and Guzzle promises are simply an overkill.
To send a request with Guzzle, simply do this:
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
$client = new Client();
$header = ['Content-Type' => 'application/x-www-form-urlencoded'];
$body = json_encode(['id' => '2', 'name' => 'dan']);
$request = new Request('POST', 'http://localhost/async-post/tester.php', $header, $body);
$response = $client->send($request);
Also, it seems you are using the form action attribute rather than the actual form data in form-params.
I'm posting this answer because I tried to achieve something really asynchronous with php - Schedule I/O processing as a background task, continue processing script and serve the page; I/O continues in background and completes without disrupting the client. Laravel Queues was the best thing I could find.

How to send data to an API in PHP Laravel?

I'm new to Laravel framework so I'm having a hard time to do something very trivial. The main idea is to contact an API and get its response. Below is my function where I'm having error,
public function verification($id=null){
try{
$res = $client->createRequest('POST','http://35.161.181.102/api/socialverify/linkedin',['headers' => $headers , 'body' => $urlclean]);
$res= $client->send($res);
}catch(\GuzzleHttp\Exception\RequestException $e) {
\Log::info($e->getMessage());
\Log::info($e->getCode());
\Log::info($e->getResponse()->getBody()->getContents());
}
}
When I run the above function I'm getting the error shown below,
Illegal string offset 'id'
Any pointers on what I'm doing wrong and how can I solve it.
Any help is appreciated. Thank in advance.
What do you see in your /storage/logs/laravel.log?
I assume Client is Guzzle Client and by default Guzzle throws RequestException whenever there is a request issue. See Documentation. So why not try to do this and see what's the error responded from Guzzle:
try {
$response = $client->post('http://link-to-my-api', array(
'headers' => array('Content-type' => 'application/json'),
'body' => $data
));
$response->send();
}catch(\GuzzleHttp\Exception\RequestException $e) {
\Log::info($e->getMessage());
\Log::info($e->getCode());
\Log::info($e->getResponse()->getBody()->getContents());
}
And check your /storage/logs/laravel.log to see the logs being printed.
you can try this way:
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders($header)
->post($url, [
$data
]);

Guzzle Http Client and authorization in LinkedIn

I try to simulate the authorization LinkedIn web browser (PHP). I use Guzzle Http Client.
Here is part of the authorization code:
use GuzzleHttp\Client as LinkedinClient;
use PHPHtmlParser\Dom as Parser;
public function authLinkedin()
{
$client = new LinkedinClient(['base_url' => 'https://www.linkedin.com']);
try {
$postData = [
'session_key' => 'My_email',
'session_password' => 'My_password',
'action' => 'login'
];
$request = $client->createRequest('POST', '/uas/login', ['body' => $postData, 'cookies' => true]);
$response = $client->send($request);
if ($response->getStatusCode() === 200) {
$parser = new Parser();
$parser->load($client->get('https://www.linkedin.com/', ['cookies' => true])->getBody());
return $parser;
} else {
Log::store("Authorization error", Log::TYPE_ERROR, $request->getStatusCode());
return null;
}
return $request;
} catch (Exception $ex) {
Log::store("Failure get followers", Log::TYPE_ERROR, $ex->getMessage());
return null;
}
}
The request is successful, returns a 200 code, but I did not authorize.
Who can faced with a similar task, or in the code have missed something. I would appreciate any advice.
I think that the issue is with CSRF protection and other hidden parameters. LinkedIn, as other sites, usually returns 200 OK for all situations, even for an error, and describes details in resulting HTML.
In your case it's better to use a web scraper, like Goutte. It emulates a user with a browser, so you don't need to worry about many things (like CSRF protection and other hidden fields). Examples can be found on the main pages, try something like this:
$crawler = $client->request('GET', 'https://www.linkedin.com');
$form = $crawler->selectButton('Sign In')->form();
$crawler = $client->submit($form, array(
'login' => 'My_email',
'password' => 'My_password'
));
You can use it with Guzzle as a driver, but some sites might require JavaScript (I'm not sure about Amazon). Then you have to go to a real browser or PhantomJS (a kind of headless Chrome).

guzzle `http_errors` changes error from 500 to 404

i have a function im testing which suppose to return error 500 but after adding 'http_errors' => 'false' to the put definition, the returned error changes from 500 to 404.
this is my function:
public function testApiAd_updateWithIllegalGroupId($adId)
{
$client = new Client(['base_uri' => self::$base_url]);
try {
$response = $client->put(self::$path.$adId, ['form_params' => [
'name' => 'bellow content - guzzle testing',
'description' => 'guzzle testing ad - demo',
'group_id' => '999999999',
]]);
} catch (Guzzle\Http\Exception\BadResponseException $e) {
//Here i want to compare received error to 500
}
}
right now this function will return server error: 500 but it also stops the class from executing rest of the tests and i can't assert it.
how can i use the guzzle getStatusCode() in my function while getting error 500 and not 404 as i mentioned above
The BadResponseException contains the original Request and the Response object. So you can, the catch block the following assertion:
} catch (Guzzle\Http\Exception\BadResponseException $e) {
//Here i want to compare received error to 500
$responseCode = $e->getResponse()->getStatusCode();
$this->assertEquals(500, $responseCode, "Server Error");
}
Further info in the doc

Categories