How to upload file using Laravel Guzzle HTTP client - laravel

I'm using the Alfresco Rest API from a Laravel application!
To do so, I use the laravel guzzlehttp/guzzle package.
Below is my code.
When I run it, I get a status 400
The documentation of my endpoint can be found here: https://api-explorer.alfresco.com/api-explorer/#!/nodes/createNode
// AlfrescoService.php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
class AlfrescoService
{
public static function apiConnexion()
{
$response = Http::withHeaders([
"Content-Type" => "application/json",
])->post('http://192.168.43.152:8080/alfresco/api/-default-/public/authentication/versions/1/tickets', [
'userId' => 'admin',
'password' => 'admin',
]);
return base64_encode( $response["entry"]["id"] );
}
public static function request2($queryType, String $query, array $data=[])
{
$response = Http::withHeaders([
"Authorization" => "Basic ".self::apiConnexion(),
])->attach(
'attachment', file_get_contents('alfresco/doc.txt'), 'doc.txt'
)->$queryType('http://192.168.43.152:8080/alfresco/api/-default-/public/alfresco/versions/1'.$query, $data);
return $response;
}
}
// AlfrescoController.php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Services\AlfrescoService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use MercurySeries\Flashy\Flashy;
class AlfrescoController extends Controller
{
public function storeFile(Request $request) {
$data=["name"=>"My new File.txt", "nodeType"=>"cm:content"];
$response=AlfrescoService::request2("post", "/nodes/-shared-/children", $data);
dd($response->status()); // 400
}
}

I dont understand why you have used $querytype but as you have asked in your heading "How to upload file using Laravel Guzzle HTTP client", so here is the answer for that,
public static function request2($queryType, String $query, array $data=[])
{
$file = fopen('alfresco/doc.txt', 'r')
$response = Http::withToken(self::apiConnexion())
->attach('attachment', $file)
->post($url);
return $response;
}
You can see withToken() method in docs

The response should mention what precipitated the bad request. You may try wireshark to capture the upload attempt and compare it with the curl examples here

Related

Why my resource do not return all meta data having "with" method?

In lumen 8 app I use resources and reading here
https://laravel.com/docs/8.x/eloquent-resources
I try to use “with” method, as I want to add some meta data to any request and I have no
this meta data in returned data :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Models\Page As PageModel;
use App\Http\Resources\User as UserResource;
class Page extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
...
'created_at' => $this->created_at,
];
}
public function with($request)
{
\Log::info( '-1 unction with ::' . print_r( 1, true ) ); // I DO NOT SEE THIS LOGGINHG line
return [
'meta' => [
'version'=>getAppVersion()
]
];
}
}
In the referenced docs resource is declared a bit different from ResourceCollection:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return parent::toArray($request);
}
public function with($request)
{
return [
'meta' => [
'key' => 'value',
],
];
}
}
Could it be the issue and how can fix my resource to get all meta data ?
Updated block:
UserCollection - that is collection https://laravel.com/docs/8.x/eloquent-resources
my collection is Page and I use it in controller as :
namespace App\Http\Controllers;
use Carbon\Carbon;
use App\Models\Page;
use Illuminate\Http\Request;
use App\Http\Resources\Page as PageResource;
use Config;
use App\Http\Requests\PageRequest;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Validator;
class PageController extends Controller
{
public function index()
{
$pages = Page
...
->get();
return $this->sendOkResponse(PageResource::collection($pages), '');
}
sendOkResponse defined in Http/Controllers/Controller.php :
class Controller extends BaseController
{
protected $requestData;
public function __construct()
{
$request = request();
$this->requestData = $request->all();
}
public function sendOkResponse($responseResult, $message)
{
$response = [
'success' => true,
'data' => $responseResult,
'message' => $message,
];
return response()->json($response, HTTP_RESPONSE_OK);
}
I suppose PageResource is destroyed at PageController controller index method exit...
Updated block # 2:
After some tests I found that Resource method “with” does not work if collection is returned
and I need to use ->additional in controller like:
return (PageResource::collection($pages))
->additional([
'meta' => [
'version' => getAppVersion()
]
]);
But in cases when I return sinopgle element(ex store method) like
return (new PageResource($page));
method “with” works ok.
That exludes using of wrapper like sendOkResponse.
Is is the only proper way?
Thanks in advance!
Laravel resources are intended to be returned directly from your controller's action method, not as part of an associative array representing JSON.
When wrapping your responses with the sendOkResponse method, the resource is not being returned directly from the method and thus toArray is being called on your resource. The with method on your resources is being ignored.
Try returning the resources directly from your controller's method. Use the additional method when constructing your resources to pass the extra attributes in the response. See: https://laravel.com/docs/8.x/eloquent-resources#adding-meta-data-when-constructing-resources.
If you can control the API contracts, I'd recommend changing them to omit success entirely, this can be derived from the HTTP status code.

use trait variable undefined

I am trying to use trait because I will put the code in several files as it is an api connection.
But when calling the variable that displays the values returned by the api, it is showing undefined in the controller.
App/Http/Traits/UserConnect.php
namespace App\Http\Traits;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
trait UserConnect
{
public function connectInfo(Request $request)
{
try {
$client = new \GuzzleHttp\Client();
$url = "api_url";
$response = $client->request('GET', $url, [
'headers' => [
'Authorization' => 'Bearer '.$token,
],
]);
$result = json_decode($response->getBody());
return $result;
}catch (\Exception $e){
dd($e);
}
}
}
Controller
<?php
namespace App\Http\Controllers;
use App\Http\Traits\UserConnect;
class HomeController extends Controller
{
use UserConnect;
public function page(Request $request)
{
$api = $this->connectInfo($result);
dd($api);
}
$result is returning undefined but $ api is forcing 1 variable.
Your call should be $api = $this->connectInfo($result$request); because your function declaration accepts Request public function connectInfo(Request $request)

How to receive JSON from POST?

I receive JSON from Vue.JS client via REST Api, and I'd like to get data using Eloquent, but it doesn't work. It's not blade and not standard form-submit data, I receive JSON Api from client, single-page application.
This is the JSON, addressed to route '/order' from client, method POST:
{
"name": "John",
"phone": "+7 794 910 5708",
"email": "example#gmail.com"
}
The route is:
Route::post('/order','OrderController#order');
In a Controller I try to do that:
<?php
namespace App\Http\Controllers;
use Request;
use App\Data;
class OrderController extends Controller
{
public function order()
{
$input = Request::all();
$data = new Data;
$data->name = $input['name'];
$data->phone = $input['phone'];
$data->save();
return response()->json(['result' => '200 OK'], 200);
}
}
But nothing happens. What is the right syntax to receive data from REST Api?
Make some changes as per below:
In controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Data;
class OrderController extends Controller
{
public function order(Request $request)
{
$post = $request->all();
$data = Data::create($post);
if($data){
return response()->json(['success' => true, 'message' => 'Data has been inserted!']);
} else {
return response()->json(['success' => false, 'message' => 'Data not inserted, Something went wrong!']);
}
}
}

Laravel get input data from POST request in a rest api

i'm trying to get input data which i post them from rest api as an json format, but in laravel i can't get them on controller and that return empty array of request
my api route:
Route::group(['prefix' => 'v1', 'namespace' => 'Api\v1'], function () {
$this->post('login', 'ApiController#login');
});
and ApiController:
<?php
namespace App\Http\Controllers\Api\v1;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class ApiController extends Controller
{
public function login(Request $request)
{
dd($request->all());
}
}
output:
[]
ScreenShot
Problem resolved by adding this line:
Content-type: text/json
to RestClient header
use Input Facade class In my case it was work
use \Illuminate\Support\Facades\Input;
$request = Input::All();

Manipulating Laravel html response just before sending it to browser

What is the proper way to manipulate final output before sending it to browser? (laravel 5.*)
I have created facade
namespace App\Facades;
use Illuminate\Support\Facades\Response as ResponseFacade;
use Illuminate\Http\Response as ResponseHttp;
class Response extends ResponseFacade
{
public static function viewMod($view, $data = [], $status = 200, array $headers = [])
{
$output = \Response::view($view, $data, $status, $headers);
return some_manipulating_function($output);
}
}
and in the controller action i use
return viewMod("my_view_file", array $view_data);
but i receive corrupted output (http response headers are added to/ prepended to html)
most probably \Response related __toString method behaves strangely
any ideas? (thanks!)
You can use AfterMiddleware like below example from docs,
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}

Resources