I'm trying to upload a file in my Laravel 9 application. On the localhost, it works just fine, however, the same action fails when I try it from my application running on an Amazon Linux EC2.
What I know:
The action does not throw any exceptions, it just receives an HTTP 403 error. (I've enabled debug in my .env)
I'm only receiving this error in places where I'm trying to upload an image. Other controllers work fine.
What I suspect the issue is:
I believe the issue is with Apache/server configuration. I've added a dd() call in the first line of the update() function and it doesn't even get there. The 403 error is thrown before that. see below.
What I've done to troubleshoot:
Made sure the S3 bucket policy is ok (the same controller works fine on localhost)
Made sure the file permissions are ok (see screenshot below)
Made sure the authorize() function inside the request class returns true
looked at the error logs and don't see anything relevant in there either.
Made sure file_uploads = On, upload_max_filesize = 4M and max_file_uploads = 20 inside php.ini
Here is what my controller looks like (the authorize() function inside UpdateContactRequest returns true):
//https://myapp.com/contacts/1
//App\Http\Controllers\ContactController
public function update(UpdateContactRequest $request, Contact $contact)
{
dd($request); //This does not get executed. The 403 error happens before reaching this.
$contact->update($request->all());
$this->uploadAvatar($request, $contact);
Flash::success('Contact updated successfully.');
return redirect(route('dealers.contacts.index', $contact->dealer->id));
}
Here is the uploadAvatar function I use to do the upload:
private function uploadAvatar(Request $request, Contact $contact)
{
if ($request->hasFile('avatar')) {
try {
$contact
->addMediaFromRequest('avatar')
->sanitizingFileName(function ($fileName) {
return strtolower(str_replace(['#', '/', '\\', ' '], '-', $fileName));
})
->toMediaCollection('avatars');
} catch (\Spatie\MediaLibrary\MediaCollections\Exceptions\FileUnacceptableForCollection $e) {
Flash::error($e->getMessage());
}
}
}
How the routes are defined:
Route::get('/', function () {
return view('welcome');
});
Route::get('/test', App\Http\Controllers\TestController::class);
Route::get('/embed-iframe/{uuid}', [App\Http\Controllers\EmbedController::class, 'iframe']);
Route::get('/embed-js/{uuid}', [App\Http\Controllers\EmbedController::class, 'js']);
Auth::routes();
Route::middleware('admin')->group(function () {
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::resource('dealers', App\Http\Controllers\DealerController::class);
Route::post('refreshDealerCRMData', [App\Http\Controllers\DealerController::class, 'refreshCRMData']);
Route::post('loadCRMView', [App\Http\Controllers\DealerController::class, 'loadCRMView']);
Route::resource('cms', App\Http\Controllers\CmsController::class);
Route::resource('crms', App\Http\Controllers\CrmController::class);
Route::resource('leads', App\Http\Controllers\LeadController::class);
Route::resource('contacts', App\Http\Controllers\ContactController::class);
Route::resource('attachment-categories', App\Http\Controllers\AttachmentCategoryController::class);
Route::resource('CRMAttachments', App\Http\Controllers\CRMAttachmentController::class);
Route::resource('dealers.leads', App\Http\Controllers\DealerLeadController::class)->scoped([
'dealers' => 'dealer.id',
'leads' => 'lead.id',
]);
Route::resource('dealers.contacts', App\Http\Controllers\DealerContactController::class)->scoped([
'dealers' => 'dealer.id',
'contacts' => 'contact.id',
]);
});
Here is a screenshot of my root directory (/var/www/html):
Here are my virtual hosts defined in /etc/httpd/conf/httpd.conf
<VirtualHost *:443>
ServerAdmin user#domain.com
ServerName myapp.com
ServerAlias www.myapp.com
DocumentRoot /var/www/html/public
<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerAdmin user#domain.com
ServerName myapp.com
ServerAlias www.myapp.com
DocumentRoot /var/www/html/public
<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Here is my IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucket",
"arn:aws:s3:::mybucket/*"
]
}
]
}
Here is a screenshot of the exact error being thrown:
How can I further troubleshoot this when no actual exception is thrown?
For other users who run into mysterious 403 Errors using AWS, here is an approach to debugging this and problems like it.
First, verify if your request is even hitting your application. An excellent way to do this is to try to dd() in the AppServiceProvider. In this case, it would not have returned anything, which is your clue that it is outside your application. If it would have been inside, continue debugging using dd() through your application or logging into the Laravel log.
The next step is ensuring you are hitting the server—two approaches for this when using AWS.
Using Sampled Requests View
Aws has a thorough walk-through for viewing a sample of web requests - this will allow you to view any incoming requests that AWS WAF has inspected and either allowed or blocked.
AWS Waf Logs
Additionally, when setting up new projects, I recommend always enabling AWS Waf Logs, allowing you to see which rule is the terminating rule blocking the request.
Both of these methods should be sufficient in debugging this type of error.
The issue was with an AWS WAF rule preventing HTTP post size from exceeding a certain number. Removed the rule, and it's now working again.
I'm guessing this 403 issue you were experiencing was having place in a shared hosting. When you create the symlink with php artisan storage:link it contains the full absolute path to the storage/app/public folder. This is what probably causes the 403 response by the server.
The solution is create a symlink with a relative path from the project root like
ln -s ../storage/app/public public/storage
Related
I try to install my Laravel application in a new environment acceptance,
After composer install (no errors)
when I check the url it's redirected to /login which is normal
The problem: it returns 404 error and this error is coming from the server not from Laravel because I customized 404 error in my application
it seems like the server does accept only / path :
also when I change the router :
from
Route::get('/', function () {
if (Auth::check()) return redirect('/myprofile');
return redirect('/login');
});
To this:
Route::get('/', function () {
return 'hello world'
});
it works and I can see hello world
the route /login exists when I route:list
First check if Apache's mod_rewrite module is enabled, If it's not enabled aleady please run below commands to enable it or else jump to second part of the answer
sudo a2enmod rewrite
sudo service apache2 restart
Also add below config block in your virtual host configuration to enable laravels .htaccess rules
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Change /var/www/ path accordingly
I have a Debian server 9 with Apache 2 and Laravel 5.6
I have the folder: /LcmTI/projects/www to publish my projects, port 81 answers for all projects, eg:
http://localhost: 81/project1 [html project only]
In the folder /LcmTI/projects/laravel, I have two laravel projects 5.6:
extranet at /LcmTI/projects/laravel/extranet
intranet at /LcmTI/projects/laravel/intranet
I have created a link to the two projects in the www folder (which is the folder that is published):
ln -s /LcmTI/projects/laravel/extranet/public /LcmTI/projects/www/extranet
ln -s /LcmTI/projects/laravel/intranet/public /LcmTI/projects/www/intranet
In this way, I expected without any problem to access the two laravel environments without any problem, but it is not working.
When I type:
http://localhost:81/extranet/api/test or http://localhost:81/intranet/api/test
does not work and should return:
/* file routes/api.php in both applications */
`Route::get('test', function () {
return response()-> json(['foo' => 'bar']);
});`
If I enter http://localhost:81/extranet or http://localhost:81/intranet
Enter the homepage of Laravel
My configuration for Apache 2:
<VirtualHost *:81>
DocumentRoot /LcmTI/projects/www
<Directory /LcmTI/projects/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
Require all granted
</Directory>
</VirtualHost>
I'm having a hard time setting up larval API applications on a single host.
I use laravel 5.6.34. I installed Laravel with the clone github laravel / laravel and composer install. I make a route something like this
Route::get('/', function () {
return view('welcome');
});
Route::prefix('admin')->group(function () {
Route::get('/', function () {
echo 'Hello Admin';
});
});
I run php artisan serve it work fine in first url localhost:8000, but when I try to open second url localhost:8000/admin it keep loading. Because I can't wait I stop php artisan serve with ctrl + c, but the strange thing happens when I run exit cmd not closed. Can anyone tell what's wrong? And sorry for bad english.
<Directory /var/www/html/sites/test/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
add this rule in virtualhost basically AllowOverride All*
check is a2enmod rewrite enabled or not and
check .htaccess file
more info check this thread
after I did research, I knew the main problem. There no problem in code. The problem come from avast antivirus that try block artisan console. so to fix this problem just disable your avast anti virus when development stage.
I'm beginning Laravel 5.2 and I'm stuck with this simple route:
Route::group(['prefix' => 'admin'], function(){
Route::get('/', function(){
return view('admin/login');
});
});
When I type http://<my_site>/admin I am redirected to http://<my_site>/public/admin/? instead of returning the view (I also tried with a simple return 'ok' and it keeps get redirected.
I can't understand where I am wrong, please a help?
EDIT: I found out that it's because I have an admin folder in my public one, that maybe causes conflict! But I'd like to keep the name admin to my assets folder, what can I do?
You should set up public directory as root direcotry in your web server configuration. For example, for Apache do this:
<VirtualHost *:80>
ServerName myapp.localhost.com
DocumentRoot "/home/vagrant/projects/myapp/public"
<Directory "/home/vagrant/projects/myapp/public">
AllowOverride all
</Directory>
</VirtualHost>
The thing is if your web server is pointed to another directory (for example, the Laravel's root directory), your app will never work properly.
I'm not only new to Laravel 4, but new to using frameworks. I thought I'd start with Laravel since it's gotten such good reviews.
I've got a good install of Laravel. I go to /l4/public and see the welcome page.
I'm trying to add a route to routes.php so that when I navigate to /l4/public/articles I get a response.
I get "The requested URL /l4/public/articles was not found on this server." Do I need to run an artisan command to compile the routes? It's probably something easy. Why this message?
routes.php
Route::get('/', function()
{
return View::make('hello');
});
Route::get('articles', function ()
{
//return View::make('articles');
return "Articles hello there";
});
Problem is solved by two editing changes in apache's httpd.conf file.
AllowOverride None is default. AllowOverride controls whether .htaccess files are processed.
mod_rewrite is commented out by default.
Changes to make:
Change 1: Activate mod_rewrite by uncommenting it.
Change 2:
Change
AllowOverride None
to
AllowOverride All
Now restart Apache...
The default .htaccess file that Laravel provides in the public folder specified some mod_rewrite rules. These rules were not getting applied because AllowOverride was set to none. Be sure and restart apache after changing these settings.
My configuration: Apache 2.4.6 on Windows XP.
It appears that there may be some security implications to the AllowOverride change. If anyone has additional information on this, I would like to hear it.
That Error basically say that the router cannot found your request. Make sure you already save your changes.
if you using the artisan command to running the page,just re-run again command "artisan Serve".
You need mod_rewrite on. Try: l4/public/index.php/articles
in httpd.conf change
<Directory />
AllowOverride none
Require all granted
</Directory>
to
<Directory />
AllowOverride all
Require all granted
</Directory>
then uncomment
#LoadModule rewrite_module modules/mod_rewrite.so
to
LoadModule rewrite_module modules/mod_rewrite.so