How to write on route to receive request from external laravel project - laravel

$client = new Client();
$response =
$client->GET('http://XXX.XX.XX.XX/eDeskApi/module/SOMEFUNCTION',
[
'json' => ['foo' => 'bar']
]);
This is how i'm sending a request to external LARAVEL api.
I just want to know what do i need to write in laravel api router to get something return when i send this request.
Currently i have the following code on laravel api router
Route::GET('module/url', 'Nameof Controller#NameOfMethhod');
And in controller looks like:
public function GetApplicationModuleList()
{
echo 'something';
//i want to print the parameter value which i just sent by above mention request.
}

You need to change your request from GET to POST if you want to send some request body there.
Also your function should take an argument of:
Illuminate\Http\Request type.
After that you can access you request body by doing:
$request -> all();

Related

How can write test for laravel api route with auth.basic middleware

My laravel project has an API route by auth.basic middleware which is used id of the authenticated user in the controller. when I call it in postman it works well and I get 401 when the username or password is incorrect, but in laravel APITest which extends from DuskTestCase, authentication does not take place so I get 500 instead of 401 when the user's informations were incorrect. However, by correct information, I have the same error because auth() is null.
it is written like below, which is wrong?
api.php route:
Route::get('/xxxxxx/xxxxxx/xxxxxxx', 'xxxxx#xxxx')->middleware('auth.basic');
APITest:
$response = $this->withHeaders(['Authorization' => 'Basic '. base64_encode("{$username}:{$password}")])->get("/xxxxxx/xxxxxx/xxxxxxx");
You can use actingAs() method for authentication in tests.
An example from docs:
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
Another example that you can use for an API:
$user = User::factory()->create();
$response = $this->actingAs($user)->json('GET', $this->uri);
$response->assertOk();
For more information: https://laravel.com/docs/5.1/testing#sessions-and-authentication

How do I mock guzzle request

How do I make a mock of third party api call . That is happening from controller . I have this line of code in controller .
public function store(){
$response = $request->post('http://thirdpaty.app/rmis/api/ebp/requests', [
"headers" => [
'Content-Type' => 'application/json',
],
"json" => [
"data"=>1
]
]);
$data = json_decode($response->getBody()->getContents());
$token = $data->token;
// Saving that token to database
}
And from the test I am doing
$response = $this->post('/to-store-method');
How do I mock the api request . So that in testing I don't have to call the third api request .
Right now I am doing
if(app()->get('env') == 'testing'){
$token = 123;
}else{
//Api call here
}
Is there any better alternative of doing this test
You'll need some way of injecting a mock handler into the Guzzle Client your controller is using. Traditionally, you'd either leverage dependency injection by passing the Guzzle Client via the constructor or through some referenced service in that code that you can mock (using Mockery) behind the scenes.
After that, check out the Guzzle documentation for a peak on how to mock requests in the HTTP Client:
http://docs.guzzlephp.org/en/stable/testing.html
You'd use a MockHandler to do something resembling the following code by building a stack of fake requests and responses.
// Create a mock and queue two responses.
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], 'Hello, World'),
new Response(202, ['Content-Length' => 0]),
new RequestException('Error Communicating with Server', new Request('GET', 'test'))
]);
$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);
// The first request is intercepted with the first response.
$response = $client->request('GET', '/');
Actually, it is a bad practice to mock the network libraries. What I would recommend is to wrap the network request by the httpService and mock the httpService instead to return the required response.
public function store(){
$response = httpService.postData();
$data = json_decode($response->getBody()->getContents());
$token = $data->token;
// Saving that token to database
}
So, the you would get the response as return from the httpService.postData function and you can mock the postData instead of the network library.

How to create new POST request with Parameters in Laravel 5.5 from INSIDE Controller Method

I'm trying to call my own laravel api with POST method but I am not getting the post values in get_cities_list method.
LocationController.php
public function get_cities(){
$params = array('country_id' => 1);
$req = Request::create('api/get_cities_list', 'POST', $params);
$response = json_decode(Route::dispatch($req)->getCOntent());
print_r($response);
}
Api/CommonController.php
public function get_cities_list(Request $request){
print_r($request->all()) //empty array
print_r($_POST) //empty array
}
Use guzzle for sending request with php.
You could also use vue to set it up. Or ajax calls.
Could you provide your web.php?

How to validate params in REST Lumen/Laravel request?

Route:
$app->get('/ip/{ip}', GeoIpController::class . '#show');
How to validate ip's properly? I've tried to inject Request object in show method, but wasn't able to solve this. I want to stick with REST, so using URL parameters is not solution for me. I use it for API purposes, so status code as response would be appropriate.
Also tried that way:
$app->bind('ip', function ($ip) {
$this->validate($ip, [
'ip' => 'required|ip',
]);
});
EDIT:
The answer below is correct, I've found more info about requests in documentation:
Form requests are not supported by Lumen. If you would like to use form requests, you should use the full Laravel framework.
In other words, you cannot use custom requests via injection in constructors in Lumen.
The validate method takes the request object as the first parameter. Since you're passing the ip in the route, you need to create a custom validator.
public function show($ip)
{
$data = ['ip' => $ip];
$validator = \Validator::make($data, [
'ip' => 'required|ip'
]);
if ($validator->fails()) {
return $validator->errors();
}
return response()->json(['All good!']);
}
Edit : This is all laravel does under the hood. You could basically you this function directly to validate the ip and save a lot of effort.
protected function validateIp($ip)
{
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}

Laravel 5 - Remove Parameter From All Request Objects at Controller Level

I have URLs that look like:
http://example.com/api/user?id=45&name=mike&api_token=2348283
http://example.com/api/project?id=5&description=first&api_token=2348283
etc...
In my controllers, I have functions that look like:
public function user_get_endpoint(Request $request){
$request = $request->toArray();
return UserModel::where($request)->get()->toArray();
}
The above will currently break since the $request object contains a property called api_token which does not exist in the user table. I am using the api_token in a middleware to check for authentication.
I can manually unset the api_token property in each of my API functions by using unset($request['api_token'], but I'd like to avoid that if possible.
Is there anyway to do this application wide or at a class or controller level?
Laravel provides add and remove functions to add and remove new properties to the request object respectively.
$request->request->add(['api_token' => 'api_token']); // to add new property to $request
$request->request->remove('api_token'); // to remove property from $request
Perhaps you want global middleware?
First arrange for the middleware to run on all routes:
// routes.php
$app->middleware([
App\Http\Middleware\Apitoken::class
]);
Then define what the middleware should do:
// src/App/Http/Middleware/Apitoken.php
<?php
namespace App\Http\Middleware;
use Closure;
class Apitoken
{
public function handle($request, Closure $next)
{
unset($request['api_token']);
return $next($request);
}
}
Method 1
$request->except(['key1','key2',....])
provides an easy way to skip unwanted keys, similarly
Method 2
$request->only(['key3','key4',....])
provides an easy way to skip all others unwanted keys, I find both reasonably good for almost all scenarios
A solution that works for all HTTP Methods (not only for GET and HEAD) :
$except = ['api_token'];
$request = request();
$cleanup = $request->except($except);
$request->query = new \Symfony\Component\HttpFoundation\ParameterBag($cleanup);
Ideally, you should send your api_token in request headers instead of Uri params.
If you are using Laravel's auth:api Middleware for authentication then you can send api_token in headers as:
$response = $client->request('GET', '/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
Then api_token will never come in your Uri params.
As #JanWillem said in the comments you can use except() which will remove the params you pass to it:
public function user_get_endpoint(Request $request){
return UserModel::where($request->except('api_token'))->get();
}
https://laravel.com/docs/5.2/requests#retrieving-input and then scroll down to Retrieving A Portion Of The Input Data
Furthermore, you don't have to use toArray() with the response as Laravel will automatically do this for you.
Hope this helps!

Resources