how to get http request detail in laravel? - php

I have an http client request like this?
try {
$request = json_encode($data);
$result = $this->pendingRequest->{$method}('http://test.local/general/wallets/1000000', $data);
// this is my request detail
$request = $result->transferStats ? Message::toString($result->transferStats->getRequest()) : $request;
$result->throw();
$this->setLog($provider, $step, $request, $result->body(), $url, $result->status());
return $result;
} catch (RequestException $exception) {
// I need to http request detail
} catch (ConnectionException $exception) {
// I need to http request detail
}
I need to get my request param and headers and token and every thing that send to third party in cache exceptions. I can get detail in try via: Message::toString($result->transferStats->getRequest())

you can #dd($request);
on blade OR
dd($request); on controllers etc..

Illuminate\Http\Client\Request
headers() : array
Get the request headers.
parameters() : array
Get the request's form parameters.
body() : string
Get the body of the request.
data() : array
Get the request's data (form parameters or JSON).

You can take it as
$request->all();
if you want to see more regular. you can try
dd($request->all());

Related

Laravel HTTP Client Post Response Save File

Sends post request to another api inside Laravel controller.
It returns .pdf file as a response. I wanna save this file to storage. I get FileNotFound exception.
Here is the code
public function cvToPDF(Request $request)
{
$response = Http::withHeaders(['Content-Type' => 'application/pdf'])
->withToken(Request()->bearerToken())
->post('http://some-endpoint', $request->all());
Storage::disk('s3')->putFile('drive/files', $response);
return $response;
}
return $response works in client side. I can download the pdf with this endpoint. But Storage::disk raises exception.
Because you try to save response, not file.
Workaround at sink() method - this MAY work.
public function cvToPDF(Request $request)
{
$tempName = tempnam(sys_get_temp_dir(), 'response').'.pdf';
$response = Http::sink($tempName)
->withHeaders(['Content-Type' => 'application/pdf'])
->withToken(Request()->bearerToken())
->post('http://some-endpoint', $request->all());
Storage::disk('s3')->putFile('drive/files', new File($tempName));
return $response;
}

does Slim framework have URL encoded annotation for POST method?

I'm developing a web RESTful API using slim framework of php.I want to know how do I add some annotation type thing on POST method so that it can behave as URL encoded method.Please help me in this regard.Advance thanks.
There is no pre-programmed way for this - there is no Slim or php method that will definitively check if your string is urlencoded. What you can do is implement Slim Middleware to your route.
<?php
$app = new \Slim\App();
$mw = function ($request, $response, $next) {
if ( urlencode(urldecode($data)) === $data){
$response = $next($request, $response);
} else {
$response = ... // throw error
}
return $response;
};
$app->get('/', function ($request, $response, $args) { // Your route
$response->getBody()->write(' Hello ');
return $response;
})->add($mw); // chained middleware
$app->run();
Discussion: Test if string is URL encoded in PHP
Middleware: https://www.slimframework.com/docs/v3/concepts/middleware.html
Since you're using Slim as the foundation to your API, the easiest way is to just build a GET route with the desired URL parameters defined:
$app->get('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
// Route actions here
});
In your documentation, make sure you inform the consumers of this API that it is a GET endpoint, so that a POST body should not be made; rather, the parameters that you outline in the URL should be used to pass the client's data over to the API.
If you are intent on using a POST route with just URL parameters, then you could also force a response back if the route detects an incoming POST body:
$app->post('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
$postBody = $request->getParsedBody();
if (is_array($postBody)) {
$denyMsg = "This endpoint does not accept POST body as a means to transmit data; please refer to the API documentation for proper usage.";
$denyResponse = $response->withJson($denyMsg, $status = null, $encodingOptions = 0);
return $profileData;
}
});

laravel callback url with file_get_contents('php://input')

in vanilla php i would create a callbak url with just
try
{
//response content type application/json
header("Content-Type:application/json");
//read incoming request
$postData = file_get_contents('php://input');
.......
......
but in laravel i'm yet to get a clear explanation on how to achieve the same
ive tried using
$postData = Request::getContent();
but it returns blank
If you need data in request use (new \Illuminate\Http\Request())->all() or use DI
public function someAction(\Illuminate\Http\Request $request)
{
dd($request->all());
}

Created Request using die() also dies the Request caller

I don't know if it's the right terms to employ...
I made an API, in which the answer is sent by the die() function, to avoid some more useless calculations and/or functions calls.
example :
if (isset($authorize->refusalReason)) {
die ($this->api_return(true, [
'resultCode' => $authorize->resultCode,
'reason' => $authorize->refusalReason
]
));
}
// api_return method:
protected function api_return($error, $params = []) {
$time = (new DateTime())->format('Y-m-d H:i:s');
$params = (array) $params;
$params = ['error' => $error, 'date_time' => $time] + $params;
return (Response::json($params)->sendHeaders()->getContent());
}
But my website is based on this API, so I made a function to create a Request and return the contents of it, based on its URI, method, params, and headers:
protected function get_route_contents($uri, $type, $params = [], $headers = []) {
$request = Request::create($uri, $type, $params);
if (Auth::user()->check()) {
$request->headers->set('S-token', Auth::user()->get()->Key);
}
foreach ($headers as $key => $header) {
$request->headers->set($key, $header);
}
// things to merge the Inputs into the new request.
$originalInput = Request::input();
Request::replace($request->input());
$response = Route::dispatch($request);
Request::replace($originalInput);
$response = json_decode($response->getContent());
// This header cancels the one there is in api_return. sendHeaders() makes Content-Type: application/json
header('Content-Type: text/html');
return $response;
}
But now when I'm trying to call an API function, The request in the API dies but dies also my current Request.
public function postCard($token) {
$auth = $this->get_route_contents("/api/v2/booking/payment/card/authorize/$token", 'POST', Input::all());
// the code below is not executed since the API request uses die()
if ($auth->error === false) {
return Redirect::route('appts')->with(['success' => trans('messages.booked_ok')]);
}
return Redirect::back()->with(['error' => $auth->reason]);
}
Do you know if I can handle it better than this ? Any suggestion of how I should turn my code into ?
I know I could just use returns, but I was always wondering if there were any other solutions. I mean, I want to be better, so I wouldn't ask this question if I knew for sure that the only way of doing what I want is using returns.
So it seems that you are calling an API endpoint through your code as if it is coming from the browser(client) and I am assuming that your Route:dispatch is not making any external request(like curl etc)
Now There can be various approaches to handle this:
If you function get_route_contents is going to handle all the requests, then you need to remove the die from your endpoints and simply make them return the data(instead of echoing). Your this "handler" will take care of response.
Make your Endpoint function to have an optional parameter(or some property set in the $request variable), which will tell the function that this is an internal request and data should be returned, when the request comes directly from a browser(client) you can do echo
Make an external call your code using curl etc(only do this if there is no other option)

How do I inspect response headers in laravel 4 for unit testing?

I have seen many examples on how to set headers on a response but I cannot find a way to inspect the headers of a response.
For example in a test case I have:
public function testGetJson()
{
$response = $this->action('GET', 'LocationTypeController#index', null, array('Accept' => 'application/json'));
$this->assertResponseStatus(200);
//some code here to test that the response content-type is 'application/json'
}
public function testGetXml()
{
$response = $this->action('GET', 'LocationTypeController#index', null, array('Accept' => 'text/xml'));
$this->assertResponseStatus(200);
//some code here to test that the response content-type is 'text/xml'
}
How would I go about testing that the content-type header is 'application/json' or any other content-type? Maybe I'm misunderstanding something?
The controllers I have can do content negation with the Accept header and I want to make sure the content type in the response is correct.
Thanks!
After some digging around in the Symfony and Laravel docs I was able to figure it out...
public function testGetJson()
{
// Symfony interally prefixes headers with "HTTP", so
// just Accept would not work. I also had the method signature wrong...
$response = $this->action('GET', 'LocationTypeController#index',
array(), array(), array(), array('HTTP_Accept' => 'application/json'));
$this->assertResponseStatus(200);
// I just needed to access the public
// headers var (which is a Symfony ResponseHeaderBag object)
$this->assertEquals('application/json',
$response->headers->get('Content-Type'));
}
While not specifically about testing, a nice way of getting at Laravel's response object is to register a 'Finish' callback. These are executed just after the response is delivered, right before the app closes. The callback receives the request and the response objects as arguments.
App::finish(function($request, $response) {
if (Str::contains($response->headers->get('content-type'), 'text/xml') {
// Response is XML
}
}
Take a look at the laravel documentation
Request::header('accept'); // or
Response::header('accept');
Retrieving A Request Header
$value = Request::header('Content-Type');
Another way would be to use getallheaders() :
var_dump(getallheaders());
// array(8) {
// ["Accept"]=>
// string(63) "text/html[...]"
// ["Accept-Charset"]=> ...
For debugging purposes You could simply use this:
var_dump($response->headers);

Categories