Laravel Http::fake response with file - file

I am trying to mock/test an Http request in a feature test to mock the whatsapp APIs, using Http::fake() in the setUp as follow:
Http::fake([
'https://www.test-whatsapp.com/upload/image' => Http::response(UploadedFile::fake()->image('TestWhatsapp.jpg')->get()),
'https://www.test-whatsapp.com/*' => Http::response(),
]);
I'd like to mock that when my app calls https://www.test-whatsapp.com/upload/image i get the file content but it seems that it never get sent. This is my actual test:
public function test_ask_attachment_image()
{
$this->receivedMessage(['type' => 'TEXT', 'text' => 'ask-attachment']);
$this->receivedMessage(['type' => 'IMAGE', 'caption' => 'some text', 'url' => '"https://www.test-whatsapp.com/upload/image']);
Http::assertSent(function (Request $request){
Log::debug($request->url(), [$request->body()]);
return true;
});
}
But the log gives an empty body.
I tried to print_r the whole response but still no sign of the file.
In the end I tried with an existing file using file_get_content but i got the same result.
I have logged the faked file and it get the content right.
How can i fake an endpoint to return me a file content? Thank you for any suggestions!
Edit
After debugging more i found out that the problem is not when i'm trying to create an image but a generic file using the method UploadedFile::fake()->create('TestWhatsapp.mp4', 1000). I get the size and the mimetype right but the file is still empty.

Related

Some requests get canceled after redirecting to a named route

I am currently redirecting from a store route back to my index route with a flash message like this:
public function store(StoreMemberRequest $request)
{
$this->authorize('create', Member::class);
RegisterNewMember::run($request);
return redirect()->route('admin.members.index')->with('success', 'Member successfully created');
}
Normally this flash message shows me a notification on my frontend. I have this bit of code in my HandleInertiaRequests middleware which shares the flash data:
public function share(Request $request)
{
return array_merge(parent::share($request), [
'auth' => [
'user' => $request->user(),
],
'flash' => fn () => [
'success' => session('success'),
'error' => session('error'),
],
]);
}
However, when I redirect back to my admin.members.index route the flash message is not shown. The only difference between the pages where it works and where it doesn't work is that I see that two requests are being canceled in the console:
More detailed information about the request (the response couldn't be loaded because no data was found):
What could be the cause of the notification not showing? It does show on all other pages where the requests doesn't get canceled. The two canceled requests are literally the only differences that I could find. If someone needs any more detailed information than I would be happy to provide that.
Versions:
"#inertiajs/inertia": "^0.10.0"
"#inertiajs/inertia-react": "^0.7.0"
"inertiajs/inertia-laravel": "^0.4.5"
"laravel/framework": "^8.65",
Seems like I had some code which checked for parameters in the url on pageload. When some parameters were set the page would reload. This caused the first request to be canceled. Adding an extra check to this function solved my problem. If anyone else has the same problem, check if anywhere in your code is made a new request.

Laravel Excel giving CORS error only dev server

The problem:
I am making a get request to my Laravel API and getting the following error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://www.example.com/exceptions-company-reports.
(Reason: CORS header 'Access-Control-Allow-Origin' missing)
I have followed these instructions on local and then on dev server, but I cannot figure out why Im getting this problem only on the dev server. I have even confirmed that php_zip and php_xml are enabled.
I am not getting errors in my logs.
Client side Angular code
getExceptionsReport: function getExceptionsReport() {
var apiBase = apiUrl + 'exceptions-company-reports';
var config = {
responseType: 'blob'
};
return $http.get(apiBase, config);
}
Server side:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\PublishCompanyreportingRequest;
use DB;
use Auth;
use Excel;
class CompanyreportingController extends Controller {
public function __construct() {
$this->middleware( 'jwt.auth' );
$this->middleware( 'role:company-reports' );
}
public function exceptionsCompanyReports( PublishCompanyreportingRequest $requestData ) {
$list = DB::table( 'exceptions_reports' )->select('created_at','account_number','customer_name','fp','seriel_number','comment','grade','item_number','description')->get();
$rows = array();
foreach($list as $item) {
$rows[] = array(
"Received" => $item->created_at,
"Account Number"=> $item->account_number,
"Customer Name" => $item->customer_name,
"FP"=> $item->fp,
"Serial Number" => $item->seriel_number,
"Comment" => $item->comment,
"Grade" => $item->grade,
"Item Number" => $item->item_number,
"Description" => $item->description,
);
}
Excel::create('Filename2', function($excel) use($rows) {
// Set the title
$excel->setTitle('Company| Company Report');
// Chain the setters
$excel->setCreator('Company')
->setCompany('Company');
$excel->sheet('Exceptions Report', function($sheet) use($rows) {
$sheet->fromArray($rows);
$sheet->row(1, function($row) {
// call cell manipulation methods
$row->setBackground('#DDDDDD');
$row->setFontFamily('Calibri');
$row->setFontSize(14);
});
$sheet->setStyle(array(
'font' => array(
'name' => 'Calibri',
'size' => 14
)
));
});
// Call them separately
$excel->setDescription('A demonstration to change the file properties');
})->download('xlsx');
}
}
Laravel-Excel will not add the headers for you. So, in order to avoid CORS issues, add this header:
Excel::create('Contactos', function($excel) use ($results) {
...
})->export('xlsx', ['Access-Control-Allow-Origin'=>'*']);
I came up with a work around of sorts, I guess a little better than a workaround as there is nothing wrong with the code.
I decided to save the file to the server instead and then send that file as a response instead of relying on the extension to do it. Still quite frustrating because I will never really know what the error was. What makes it more frustrating is that I know it can work as it does on my local. I wont mark this answer as correct until in case someone has a better one.
Excel::create('Filename2', function($excel) use($rows) {
// other code
})->save('xlsx');
return response()->file(storage_path().'/exports/Filename2.xlsx');
I am also deleting the file immediately after with a DELETE request
public function destroy( $id ) {
\File::Delete(storage_path().'/exports/Filename2.xlsx');
return response()->json( [ 'success' => 'Report has been removed from server' ], 200 );
}
In my case it happened because it did not have a zip extension installed.
It was showing me Cross-Origin Request Blocked but that was not the error

Angular + Laravel Delete File

I'm building a REST-full web-app using Laravel 5.2 (for the back-end) and AngularJS for the font-end. I connect to the Laravel back-end by the use of an API. Now I have stumbled upon the following problem: I can properly upload an image, but deleting it again is not working.
The files are uploaded into the Larvel public/images/uploaded/ folder.
This is my Angular Service (the http request fired when clicking the 'delete' button) where the variable imageToDelete is the relative path to the image.. So Far so good, the request is firing and the imageToDelete variable is populated.
function deleteProfileImage(imageToDelete) {
return $http({
method: 'DELETE',
url: '/api/pictures/' + imageToDelete
})
.then(deleteProfileImageSuccess)
.catch(deleteProfileImageError);
function deleteProfileImageSuccess(response) {
$log.info('Deleting profile picture Success.');
console.log(response);
return response;
}
function deleteProfileImageError(error) {
$log.info('Deleting profile picture failed because: ' + error.data);
return error;
}
}
This angular HTTP request fires a DELETE request to the following function in my Laravel Controller.
public function destroy($imageToDelete)
{
if(Storage::delete($imageToDelete)) {
return response()->json(['success' => 'success', 'message' => 'File Deleted']);
} else {
return response()->json(['error' => 'Deleting Image failed.'])
->setStatusCode(Response::HTTP_BAD_REQUEST);
}
}
And here, the Storage::delete($imageToDelete) does nothing. It does not delete the file provided with the Angular DELETE request.
Some things I have already tried:
Working with File::delete() instead of Storage::delete()
Working with unlink() instead op the Laravel Facades;
Sending the imageToDelete as data with the HTTP DELETE request (so not in the URL).
But all without success.
How can I make Laravel (PHP) delete the image?
Thank you for helping!
You can try
$storage = Storage::find($imageToDelete);
if($storage->delete()) {
return response()->json(['success' => 'success', 'message' => 'File Deleted']);
}
or
if(Storage::destroy($imageToDelete)) {
return response()->json(['success' => 'success', 'message' => 'File Deleted']);
}
or
$deleteImage = Storage::where('id', $imageToDelete)->delete();
if($deleteImage){
return response()->json(['success' => 'success', 'message' => 'File Deleted']);
}
You might need to check your image path. When you use laravel storage or file facde your file path should be absolute path for example public_path($imageToDelete)

blueimp jquery upload SyntaxError: Unexpected token <

I'm using blueimp to upload images in cakephp 2.x. Images are upload but issue is after uploading images.I got error "SyntaxError: Unexpected token <" and json data in html format. I tried to figured it out myself and find a solution given on SO. I tried to resolve my issue by following answer given in solution but could not. (sorry for bad English)
my controller code
App::import('Vendor', 'UploadHandler', array('file' => 'file.upload/UploadHandler.php'));
$this->layout = 'upload';
$options = array(
// 'upload_dir' => WWW_ROOT . DS . 'img',
'accept_file_types' => '/\.(gif|jpe?g|png)$/i',
);
$upload_handler = new UploadHandler($options);
}
I changed url In main.js(blueimp js file)
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: 'index'
});
json data displayed on index page.
{"files":[{"name":"1186225_383357368459160_1371777554_n.jpg","size":58938,"url":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/files\/1186225_383357368459160_1371777554_n.jpg","thumbnailUrl":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/files\/thumbnail\/1186225_383357368459160_1371777554_n.jpg","deleteUrl":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/?file=1186225_383357368459160_1371777554_n.jpg","deleteType":"DELETE"},{"name":"e0775308650b201469fc68765dc4ff7a.jpg","size":150919,"url":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/files\/e0775308650b201469fc68765dc4ff7a.jpg","thumbnailUrl":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/files\/thumbnail\/e0775308650b201469fc68765dc4ff7a.jpg","deleteUrl":"http:\/\/localhost\/ec\/cakephp\/app\/webroot\/?file=e0775308650b201469fc68765dc4ff7a.jpg","deleteType":"DELETE"}]}
i had the same problem.
it was the validate variable
wrong
public $validate;
correct
public $validate = array();

how to implement JsonP in cakephp 2.4

I have just upgraded to cakephp 2.4.1 as it now supports JsonP. I was previously getting an a missing callback error in my ajax cross domain code. However the documentation does not mention any additional steps need to implement this so I would have thought that it should wold but i get the same error as before.
Do I need an extra piece of code to send the callbck back?
My Controller
public function api($mem_id = null) {
$options = array(
'fields' => array('Member.total_points'),
'conditions' => array('Member.member_no' => $mem_id),
'recursive' => -1
);
$members = $this->Member->find('first', $options);
$this->set(array(
'member' => $members,
'_serialize' => array('member')
));
}
}
ajax code
$('document').ready(function() {
$.ajax({
url: 'http://mydomain.com/loyalty/members/api/5749.json',
dataType: 'jsonp',
success: function(response) {
console.log(resonse);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
});
It should have worked fine with the older Cake version too, just as I've described in your other question ;)
Anyways, look at the code in /lib/Cake/View/JsonView.php or in the API documentation. You have to define a view var named _jsonp, which can be either a string specifying the name of the query variable that holds the callback function name, or true which means a default query variable with the name callback is being looked up.
So as jQuery uses a query variable name of callback by default, defining true for _jsonp should do it:
$this->set(array(
'member' => $members,
'_serialize' => array('member'),
'_jsonp' => true
));
In case no query variable named callback could be found in the request URL (ie ?callback=whatever), you'd receive a regular JSON response instead.
See also
Cookbook > Views > JSON and XML views > JSONP response
If that just don't work, try to change the value of $jsonpParam from "callback" to "jsoncallback" (in lib/Cake/View/JsonView.php). I had to do that for make it work, thats because the name of the variable in the jsonp request, is jsoncallback, this one contains the string of the callback.

Resources