I'm trying to write a Laravel test case where I need to make an HTTP Post Request to an external API. But my $this->postJson() keeps giving me an exception. Here's an excerpt from my code:
namespace Tests\Feature;
use Tests\TestCase;
class PurchaseTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
}
public function testPurchasePolicy()
{
$response = $this->postJson('https://apitest.cybersource.com/flex/v1/',['cardNumber'=>'4111111111111111']);
print_r($response->json());
$response->assertOk();
}
}
This gives the result:
Array
(
[message] =>
[exception] => Symfony\Component\HttpKernel\Exception\NotFoundHttpException
[file] => /var/www/projects/local/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php
[line] => 43
[trace] => Array
(
[0] => Array
(
[file] => /var/www/projects/local/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php
[line] => 162
[function] => handleMatchedRoute
[class] => Illuminate\Routing\AbstractRouteCollection
/// --> then a stack trace of laravel code that failed
)
You won't be able to fully run my code because it requires some API keys with cybersource. But i'm pretty sure my code is failing because I'm not properly telling Laravel that the API i want to access is an external resource.
What is the idiomatic way for Laravel to connect with an external URL?
You have to use an HTTP Client.
Install guzzle with composer:
composer require guzzlehttp/guzzle
Then:
For laravel 7.x and above, use the HTTP Client facade:
use Illuminate\Support\Facades\Http;
$response = Http::get('http://test.com');
Check the laravel documentation about HTTP Client usage.
For laravel 6.x or below, use guzzle like:
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/user', [
'auth' => ['user', 'pass']
]);
check the Guzzle docs.
In new Laravel
use Illuminate\Support\Facades\Http;
$response = Http::get('http://theusoffice.com/');
and if you need to use https and having issues with it try
$response = Http::withOptions(['verify' => false])->get('https://www.google.com/');
Related
I'm using Guzzle 7 to grab content from an external API with basic authentication. It works fine. Now I'd like to integrate cache management. So i've tried to use this plugin: [Guzzle-cache-middleware][1] and I can't make it working correctly. I can get API response and my desired content but the cache directory is not populated.
I've searched all around the web but I can't figure this out. Could you please tell me how to solve this? Here is my code:
$userName = "xxxxxxx";
$password = "yyyyyyyyyyy";
require_once './vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\Strategy\PublicCacheStrategy;
$stack = HandlerStack::create();
$cache = new CacheMiddleware();
$stack->push($cache, '/home/xxxx/xxxxx/guzzle2/cache');
$client = new Client([
'handler' => $stack,
'base_uri' => 'https://api.xxxxx.com/xxx/',
"timeout" => 30.0,
]);
$json = $client->get('zzzzzz.json', [
'auth' => [
$userName,
$password
]
]);
var_dump($json->getHeaderLine(CacheMiddleware::HEADER_CACHE_INFO));
Output:
string(4) "MISS"
So API result is different from cache. But headers params (ETag and Last-Modified) are still unchanged and my cache folder is still blank.
Thank you for your help!
Following a tutorial: https://www.twilio.com/blog/build-secure-api-php-laravel-passport
I manAged to get Laravel/Passport installed formy Laravel Api and Vue application.
I managed to create attoken with:
localhost:8000/oauth/token
get the login working in Postman:
localhost:8000/api/login?email=jennie05#example.com&password=password
Now when I try to register a user I get returned to the home-page.
I do get some "undefined method" errors from VS Code, but they show up in the login method,
and not in the failinf register method:
Here is the controller:
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
class AuthController extends Controller
{
public function register(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|max:55',
'email' => 'email|required|unique:users',
'password' => 'required|confirmed'
]);
$validatedData['password'] = bcrypt($request->password);
$user = User::create($validatedData);
$accessToken = $user->createToken('authToken')->accessToken;
return response([ 'user' => $user, 'access_token' => $accessToken]);
}
public function login(Request $request)
{
$loginData = $request->validate([
'email' => 'email|required',
'password' => 'required'
]);
if (!auth()->attempt($loginData)) {
return response(['message' => 'Invalid Credentials']);
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response(['user' => auth()->user(), 'access_token' => $accessToken]);
}
}
In these are the routes in api.php:
Route::post( 'register', 'App\Http\Controllers\API\AuthController#register');
Route::post( 'login', 'App\Http\Controllers\API\AuthController#login');
// Route::prefix('v2')->group(function(){ // prefix voor versie 2
Route::apiResource('/cards', 'App\Http\Controllers\CardController');
Route::apiResource('/games', 'App\Http\Controllers\GameController');
//Route::get('games', 'App\Http\Controllers\GameController#index')->middleware('auth:api');
//Route::post('games', 'App\Http\Controllers\GameController#store')->middleware('auth:api');
//Route::get('games/{id}', 'App\Http\Controllers\GameController#show')->middleware('auth:api');
//Route::put('games/{id}', 'App\Http\Controllers\GameController#update')->middleware('auth:api');
//Route::delete('games/{id}', 'App\Http\Controllers\GameController#destroy')->middleware('auth:api');
Route::get('/gameByPin/{pin}', 'App\Http\Controllers\GameController#searchPin');
Route::apiResource('/speler', 'App\Http\Controllers\SpelerController');
//});
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
is there anyone who can help troubleshooting this?
Postman does not give me errors, just the redirect to homepage..
Wow,
Thanks Patrick, your the best.
Just checked all the steps in the documentation.
reran the installation command I ran when setting up everything. ( Apperently need to do this twice ?!):
php artisan passport:install
It returned:
Encryption keys already exist. Use the --force option to overwrite them.
Personal access client created successfully.
Client ID: 5
Client secret: ikJEfthxxxxxxxxxxxxxxxxxxxxxxxxxxxBjJ36
Password grant client created successfully.
Client ID: 6
Client secret: H42lpMxxxxxxxxxxxxxxxxxxxxxxxxxxxQGZgH
Now the post request results in a token!
The error VS Code shows d for "use HasApiToken" is:
Undefined type 'Laravel\Passport\HasApiTokens'.intelephense(1009)
Using vue-tables-2 component in my #vue/cli 4.0.5 app
I see that GET request generated
http://local-ctasks-api.com/api/adminarea/activity-logs-filter?query=&limit=10&ascending=1&page=1&byColumn=0
and I try in Laravel 6 Backend REST API to set route to catch it as :
Route::group(['middleware' => 'jwt.auth', 'prefix' => 'adminarea', 'as' => 'adminarea.'], function ($router) {
Route::get('activity-logs-filter?query={query}&limit={limit}&ascending={ascending}&page={page}&byColumn={column}', 'API\Admin\ActivityLogController#filter');
But I got 404 error,
Is my route invalid ?
UPDATED # 1:
Yes, var with “/api” was unaccesible. I fixed it and running request without “/adminarea”
http://local-ctasks-api.com/api/activity-logs-filter?query=&limit=10&ascending=1&page=1&byColumn=0
I moved route definition out of any block :
Route::get('activity-logs-filter?query={query}&limit={limit}&ascending={ascending}&page={page}&byColumn={column}', 'API\Admin\ActivityLogController#filter');
I got error in browser :
"error": "INCORRECT ROUTE"
with control action defined in app/Http/Controllers/API/Admin/ActivityLogController.php :
public function filter( $query, $limit, $ascending, $page, $column )
{
\Log::info('!!++ filter $this->requestData ::');
\Log::info(print_r( $this->requestData, true ));
Why error ?
Thanks!
I think you forgot put api on prefix
Route::group(['middleware' => 'jwt.auth', 'prefix' => 'api/adminarea', 'as' => 'adminarea.'], function ($router) {
EDIT:
Don't put parameter on route like that, use Request instance
Route::get('activity-logs-filter,'API\Admin\ActivityLogController#filter');
and controller
public function filter(Request $request){
$query = $request->query;
$limit = $request->limit;
$ascending = $request->ascending;
$page = $request->page;
$column = $request->column;
dont forget use Illuminate\Http\Request; on your controller
I am trying to fetch API using unirest in my laravel application. I followed all the steps given in the docs but it's showing me an error. If there is a better alternative for unirest please let me know. Thanks in advance!
Here is my controller,
public function store(Request $request)
{
Love::create(
request()->validate([
'name_1' => ['required','max:255'],
'name_2' => ['required','max:255'],
],
[
'name_1.required' => 'You have to Enter Your name',
'name_2.required' => 'You have to Enter Your Crush name'
]));
$headers = array('Accept' => 'application/json');
$response = Unirest\Request::post("API_URL",
array(
"X-RapidAPI-Key" => "API_KEY"
)
);
dd($response);
return view("result");
}
Error
Class 'App\Http\Controllers\Unirest\Request' not found
You need to import the Unirest\Request class.
<?php
namespace Your\Namespace;
use Unirest\Request;
class YourClass{
...
If you don't import it, it will by default look for the class in the current namespace (in your case, App\Http\Controllers).
I am using Guzzle 6 to retrieve data from Ruckus public API, but keeps getting the following error
Argument 3 passed to GuzzleHttp\Client::request() must be of the type
array, boolean given
I have googled and searched for similar questions. The only working around is the second answer in this post which is to downgrade guzzle version to 5. However, other team members doing other features are using Guzzle 6, so downgrading to version 5 could also be an issue for the team.
Since I am not using any packages like in that post, I don't think the Guzzle version could be the culprit here, so can anyone give me some idea what I have done wrong? Thanks.
By the way, I am using Laravel Command. The code in the handle function is as below:
use Illuminate\Console\Command;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client;
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$client = new Client();
//to bypass local ssl certificate issuer
$client->setDefaultOption('verify', false);
$res = $client->request(
'POST',
$this->baseUrl . '/v4_0/session',
[
"headers" => [
"Content-Type" => "application/json;charset=UTF-8"
],
"json" => [
"username" => "admin",
"password" => "admin"
]
]
);
$headers = explode(';', $res->getHeader('Set-Cookie'));
return current($headers);
}
The Ruckus public API: http://docs.ruckuswireless.com/vscg-enterprise/vsz-e-public-api-reference-guide-3-5.html#header-overview. I am using version 4, but even I use version 5 I still get the same error.
At the end I logged an issue on the github account of Guzzle. It turns out that $client->setDefaultOption('verify', false); is no longer a supported function call. Instead it should be passed to the third params like below:
$res = $client->request(
'POST',
$this->baseUrl . '/v4_0/session',
[
"verify" => false,
"headers" => [
"Content-Type" => "application/json;charset=UTF-8"
],
"json" => [
"username" => "admin",
"password" => "admin"
]
]
);
Thank you for everyone who have given suggestions and tried to help.