Laravel 5 - redirect to HTTPS - php

Working on my first Laravel 5 project and not sure where or how to place logic to force HTTPS on my app. The clincher here is that there are many domains pointing to the app and only two out of three use SSL (the third is a fallback domain, long story). So I'd like to handle this in my app's logic rather than .htaccess.
In Laravel 4.2 I accomplished the redirect with this code, located in filters.php:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
I'm thinking Middleware is where something like this should be implemented but I cannot quite figure this out using it.
Thanks!
UPDATE
If you are using Cloudflare like I am, this is accomplished by adding a new Page Rule in your control panel.

You can make it works with a Middleware class. Let me give you an idea.
namespace MyApp\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
class HttpsProtocol {
public function handle($request, Closure $next)
{
if (!$request->secure() && App::environment() === 'production') {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
Then, apply this middleware to every request adding setting the rule at Kernel.php file, like so:
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
// appending custom middleware
'MyApp\Http\Middleware\HttpsProtocol'
];
At sample above, the middleware will redirect every request to https if:
The current request comes with no secure protocol (http)
If your environment is equals to production. So, just adjust the settings according to your preferences.
Cloudflare
I am using this code in production environment with a WildCard SSL and the code works correctly. If I remove && App::environment() === 'production' and test it in localhost, the redirection also works. So, having or not a installed SSL is not the problem. Looks like you need to keep a very hard attention to your Cloudflare layer in order to get redirected to Https protocol.
Edit 23/03/2015
Thanks to #Adam Link's suggestion: it is likely caused by the headers that Cloudflare is passing. CloudFlare likely hits your server via HTTP and passes a X-Forwarded-Proto header that declares it is forwarding a HTTPS request. You need add another line in your Middleware that say...
$request->setTrustedProxies( [ $request->getClientIp() ] );
...to trust the headers CloudFlare is sending. This will stop the redirect loop
Edit 27/09/2016 - Laravel v5.3
Just need to add the middleware class into web group in kernel.php file:
protected $middlewareGroups = [
'web' => [
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// here
\MyApp\Http\Middleware\HttpsProtocol::class
],
];
Remember that web group is applied to every route by default, so you do not need to set web explicitly in routes nor controllers.
Edit 23/08/2018 - Laravel v5.7
To redirect a request depending the environment you can use App::environment() === 'production'. For previous version was
env('APP_ENV') === 'production'.
Using \URL::forceScheme('https'); actually does not redirect. It just builds links with https:// once the website is rendered.

An other option that worked for me, in AppServiceProvider place this code in the boot method:
\URL::forceScheme('https');
The function written before forceSchema('https') was wrong, its forceScheme

Alternatively, If you are using Apache then you can use .htaccess file to enforce your URLs to use https prefix. On Laravel 5.4, I added the following lines to my .htaccess file and it worked for me.
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

for laravel 5.4 use this format to get https redirect instead of .htaccess
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}

What about just using .htaccess file to achieve https redirect? This should be placed in project root (not in public folder). Your server needs to be configured to point at project root directory.
<IfModule mod_rewrite.c>
RewriteEngine On
# Force SSL
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove public folder form URL
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
I use this for laravel 5.4 (latest version as of writing this answer) but it should continue to work for feature versions even if laravel change or removes some functionality.

Similar to manix's answer but in one place. Middleware to force HTTPS
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceHttps
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (!app()->environment('local')) {
// for Proxies
Request::setTrustedProxies([$request->getClientIp()],
Request::HEADER_X_FORWARDED_ALL);
if (!$request->isSecure()) {
return redirect()->secure($request->getRequestUri());
}
}
return $next($request);
}
}

This is for Larave 5.2.x and greater. If you want to have an option to serve some content over HTTPS and others over HTTP here is a solution that worked for me. You may wonder, why would someone want to serve only some content over HTTPS? Why not serve everything over HTTPS?
Although, it's totally fine to serve the whole site over HTTPS, severing everything over HTTPS has an additional overhead on your server. Remember encryption doesn't come cheap. The slight overhead also has an impact on your app response time. You could argue that commodity hardware is cheap and the impact is negligible but I digress :) I don't like the idea of serving marketing content big pages with images etc over https. So here it goes. It's similar to what others have suggest above using middleware but it's a full solution that allows you to toggle back and forth between HTTP/HTTPS.
First create a middleware.
php artisan make:middleware ForceSSL
This is what your middleware should look like.
<?php
namespace App\Http\Middleware;
use Closure;
class ForceSSL
{
public function handle($request, Closure $next)
{
if (!$request->secure()) {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
Note that I'm not filtering based on environment because I have HTTPS setup for both local dev and production so there is not need to.
Add the following to your routeMiddleware \App\Http\Kernel.php so that you can pick and choose which route group should force SSL.
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'forceSSL' => \App\Http\Middleware\ForceSSL::class,
];
Next, I'd like to secure two basic groups login/signup etc and everything else behind Auth middleware.
Route::group(array('middleware' => 'forceSSL'), function() {
/*user auth*/
Route::get('login', 'AuthController#showLogin');
Route::post('login', 'AuthController#doLogin');
// Password reset routes...
Route::get('password/reset/{token}', 'Auth\PasswordController#getReset');
Route::post('password/reset', 'Auth\PasswordController#postReset');
//other routes like signup etc
});
Route::group(['middleware' => ['auth','forceSSL']], function()
{
Route::get('dashboard', function(){
return view('app.dashboard');
});
Route::get('logout', 'AuthController#doLogout');
//other routes for your application
});
Confirm that your middlewares are applied to your routes properly from console.
php artisan route:list
Now you have secured all the forms or sensitive areas of your application, the key now is to use your view template to define your secure and public (non https) links.
Based on the example above you would render your secure links as follows -
Login
SignUp
Non secure links can be rendered as
About US</li>
Get the deal now!</li>
What this does is renders a fully qualified URL such as https://yourhost/login and http://yourhost/aboutus
If you were not render fully qualified URL with http and use a relative link url('/aboutus') then https would persists after a user visits a secure site.
Hope this helps!

You can use RewriteRule to force ssl in .htaccess same folder with your index.php
Please add as picture attach, add it before all rule others

In Laravel 5.1, I used:
File: app\Providers\AppServiceProvider.php
public function boot()
{
if ($this->isSecure()) {
\URL::forceSchema('https');
}
}
public function isSecure()
{
$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
$isSecure = true;
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
$isSecure = true;
}
return $isSecure;
}
NOTE: use forceSchema, NOT forceScheme

I'm adding this alternative as I suffered a lot with this issue. I tried all different ways and nothing worked. So, I came up with a workaround for it. It might not be the best solution but it does work -
FYI, I am using Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- It should be replaced with the APP_ENV value in your .env file

The easiest way would be at the application level. In the file
app/Providers/AppServiceProvider.php
add the following:
use Illuminate\Support\Facades\URL;
and in the boot() method add the following:
$this->app['request']->server->set('HTTPS', true);
URL::forceScheme('https');
This should redirect all request to https at the application level.
( Note: this has been tested with laravel 5.5 LTS )

The answers above didn't work for me, but it appears that Deniz Turan rewrote the .htaccess in a way that works with Heroku's load balancer here:
https://www.jcore.com/2017/01/29/force-https-on-heroku-using-htaccess/
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Here's how to do it on Heroku
To force SSL on your dynos but not locally, add to end of your .htaccess in public/:
# Force https on heroku...
# Important fact: X-forwarded-Proto will exist at your heroku dyno but wont locally.
# Hence we want: "if x-forwarded exists && if its not https, then rewrite it":
RewriteCond %{HTTP:X-Forwarded-Proto} .
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
You can test this out on your local machine with:
curl -H"X-Forwarded-Proto: http" http://your-local-sitename-here
That sets the header X-forwarded to the form it will take on heroku.
i.e. it simulates how a heroku dyno will see a request.
You'll get this response on your local machine:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved here.</p>
</body></html>
That is a redirect. That is what heroku is going to give back to a client if you set the .htaccess as above. But it doesn't happen on your local machine because X-forwarded won't be set (we faked it with curl above to see what was happening).

in IndexController.php put
public function getIndex(Request $request)
{
if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {
return redirect('/');
}
return view('index');
}
in AppServiceProvider.php put
public function boot()
{
\URL::forceScheme('https');
}
In AppServiceProvider.php every redirect will be going to URL https and for HTTP request we need once redirect so in IndexController.php Just we need do once redirect.
You particularly don't need to do the work as mentioned in IndexController.php, it is an extra control on the redirection.

If you're using CloudFlare, you can just create a Page Rule to always use HTTPS:
This will redirect every http:// request to https://
In addition to that, you would also have to add something like this to your \app\Providers\AppServiceProvider.php boot() function:
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
This would ensure that every link / path in your app is using https:// instead of http://.

I am using in Laravel 5.6.28 next middleware:
namespace App\Http\Middleware;
use App\Models\Unit;
use Closure;
use Illuminate\Http\Request;
class HttpsProtocol
{
public function handle($request, Closure $next)
{
$request->setTrustedProxies([$request->getClientIp()], Request::HEADER_X_FORWARDED_ALL);
if (!$request->secure() && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}

A little different approach, tested in Laravel 5.7
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
class ForceHttps
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ( !$request->secure() && Str::startsWith(config('app.url'), 'https://') ) {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
PS. Code updated based on #matthias-lill's comments.

You can simple go to app -> Providers -> AppServiceProvider.php
add two lines
use Illuminate\Support\Facades\URL;
URL::forceScheme('https');
as shows in the following codes:
use Illuminate\Support\Facades\URL;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
// any other codes here, does not matter.
}

For Laravel 5.6, I had to change condition a little to make it work.
from:
if (!$request->secure() && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
To:
if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}

This worked out for me.
I made a custom php code to force redirect it to https.
Just include this code on the header.php
<?php
if (isset($_SERVER['HTTPS']) &&
($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$protocol = 'https://';
}
else {
$protocol = 'http://';
}
$notssl = 'http://';
if($protocol==$notssl){
$url = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";?>
<script>
window.location.href ='<?php echo $url?>';
</script>
<?php } ?>

I found out that this worked for me. First copy this code in the .htaccess file.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

This work for me in Laravel 7.x in 3 simple steps using a middleware:
1) Generate the middleware with command php artisan make:middleware ForceSSL
Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
class ForceSSL
{
public function handle($request, Closure $next)
{
if (!$request->secure() && App::environment() === 'production') {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
2) Register the middleware in routeMiddleware inside Kernel file
Kernel
protected $routeMiddleware = [
//...
'ssl' => \App\Http\Middleware\ForceSSL::class,
];
3) Use it in your routes
Routes
Route::middleware('ssl')->group(function() {
// All your routes here
});
here the full documentation about middlewares
========================
.HTACCESS Method
If you prefer to use an .htaccess file, you can use the following code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://yourdomain.com/$1 [R,L]
</IfModule>
Regards!

The easiest way to redirect to HTTPS with Laravel is by using .htaccess
so all you have to do is add the following lines to your .htaccess file and you are good to go.
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Make sure you add it before the existing(*default) code found in the .htaccess file, else HTTPS will not work.
This is because the existing(default) code already handles a redirect which redirects all traffic to the home page where the route then takes over depending on your URL
so putting the code first means that .htaccess will first redirect all traffic to https before the route takes over

Related

PHP router only triggers on index, but not other URI's

I'm using the Bramus PHP router for my application, but it only seems to work on the index route which is /. Here's the piece of code that won't work:
public function handle(): Response
{
$response = null;
$request = new Request($_REQUEST);
$uri = $request->getRequestUri();
$container = $this->configureContainer();
$renderer = new RendererFactory();
$router = $this->configureRouter();
$controllerFactory = new ControllerFactory();
$controller = $controllerFactory->create($request, $container, $renderer, $uri);
$router->get($uri, function () use ($uri, $controller, &$response) {
$response = $controller->get();
});
$router->run();
return $response;
}
So when I go to the homepage, it works fine and returns the response with the correct value. However, when I go to say /about-us, the $router->get() never fires at all. It doesn't execute the anonymous function inside. Even replacing the $uri parameter with a hardcoded string like $router->get('/about-us'...) doesn't make the anonymous function execute.
I confirmed that the ControllerFactory does in fact return the right controller, so if the $router->get() fires, the get() method is in there and the $response should not be null. But now I get an error saying $response is null because the $router->get() won't fire.
What's the mistake I'm missing here? How can the index route work perfectly fine, but the router won't accept another route?
Edit Did some digging and added a var_dump to the Bramus Router
I added a var_dump() in the handle function inside the package itself, and it always says that the result of $this->getCurrentUri() is /, and not the URI in the browser.
My .htaccess is in the root directory and I redirect all requests to /public/index.php. Maybe that's the culprit? But I don't know how to fix it. My .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /public/index.php?path=$1 [NC,L,QSA]
Forgot to add $router->setBasePath('/');, and my folder structure and .htaccess config made the router go crazy.

Laravel Multi Tenant considers www part as subdomain

I am building a multi tenant system in laravel and each subdomain is saved in database. When a subdomain in visited, it is checked from the database either it exists or not, if it doesn't exists then abort(403) is called. Following is the way:
Routes/web.php
Route::group(array('domain' => '{subdomain}.example.com', 'middleware' => ['Subdomain']), function () {
Route::get('/', 'IndexController#index');
}
Middleware/Subdomain.php
public function handle($request, Closure $next)
{
if(Subdomains::where('subdomain', $request->subdomain)->count()==0){
return abort(403);
}else{
return $next($request);
}
}
But when I visit www.example.com, then www is also considered as subdomain and checked from database, since it doesn't exist in database and abort(403) is also called for it. In short my website is not visited with www.example.com URL.
Is there any way to differentiate www form other subdomains in this Laravel multi tenancy system or any way to handle this thing?
Just use an if statement to check if the subdomain queried is www
public function handle($request, Closure $next)
{
if($request->subdomain != 'www') {
if(Subdomains::where('subdomain', $request->subdomain)->count()==0){
return abort(403);
}else{
return $next($request);
}
}
}
Also in your .htaccess, remove www from the domain name
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Slim Framework routes returns not found except "get" named ones

I use: slim-skeleton (Mr. Rob Allen's scaffold provided on github)
Under /projects grouped routes, only "get" method routes work without any problem but with rest of all return page not found error. Also these routes have auth middleware + cors middleware (Cors Middleware taken from Slim Framework's v3 Documentation).
Here is my ../src/routes.php file:
use Slim\Http\Request;
use Slim\Http\Response;
// Routes
// Administration
$app->group('/admin', function() use ($app) {
// Dashboard
$app->get('/dashboard', 'App\Controllers\Admin\Dashboard:index');
// Projects and images management
$app->group('/projects', function() use ($app){
// Projects Actions
$app->get('/list', 'App\Controllers\Admin\ProjectManagement:index');
$app->post('/add', 'App\Controllers\Admin\ProjectManagement:add'); # NOT WORKING
$app->get('/id/{id}', 'App\Controllers\Admin\ProjectManagement:find');
$app->put('/edit/{id}', 'App\Controllers\Admin\ProjectManagement:edit'); # NOT WORKING
$app->delete('/remove/{id}', 'App\Controllers\Admin\ProjectManagement:remove'); # NOT WORKING
// Project Images Actions
$app->get('/{pid}/images', 'App\Controllers\Admin\ProjectImageManagement:attachments');
$app->post('/{pid}/images/attach', 'App\Controllers\Admin\ProjectImageManagement:attach');
// Project's Image management
$app->get('/{pid}/images/id/{id}', 'App\Controllers\Admin\ProjectImageManagement:find');
$app->put('/{pid}/images/edit/{id}', 'App\Controllers\Admin\ProjectImageManagement:edit');
$app->delete('/{pid}/images/remove/{id}', 'App\Controllers\Admin\ProjectImageManagement:removeImage');
/**
* Project's Image Sort Order
*
* Additional Info:
*
* GET /{pid}/images Retrieves current sort order beforehand
*
*/
$app->put('/{pid}/images/order/{id}/resort', 'App\Controllers\Admin\ProjectImageManagement:sortOrder');
});
// Page management
$app->group('/pages', function() use ($app) {
// About Page
$app->get('/about/content', 'App\Controllers\Admin\PageManagement:aboutPage');
$app->put('/about/content/update', 'App\Controllers\Admin\PageManagement:updateAbout');
// Contact Page
$app->get('/contact/content', 'App\Controllers\Admin\PageManagement:contactPage');
$app->put('/contact/content/update', 'App\Controllers\Admin\PageManagement:updateContact');
});
// Settings
$app->group('/settings', function() use ($app) {
// Account
$app->get('/account/details', 'App\Controllers\Admin\Settings:accountDetails');
$app->post('/account/details/apply', 'App\Controllers\Admin\Settings::applyAccountSettingChanges');
});
})->add($auth);
// Auth
$app->get('/auth/point', 'App\Controllers\AuthController:checkPoint');
$app->post('/auth/login','App\Controllers\AuthController:login');
$app->get('/auth/logout', 'App\Controllers\AuthController:logout');
// Guest
$app->get('/about', 'App\Controllers\Guest\PageContents:about');
$app->get('/contact', 'App\Controllers\Guest\PageContents:contact');
$app->get('/works', 'App\Controllers\Guest\ProjectExplorer:projects');
And here is my .htaccess under /public directory:
<IfModule mod_rewrite.c>
RewriteEngine On
# Some hosts may require you to use the `RewriteBase` directive.
# Determine the RewriteBase automatically and set it as environment v
ariable.
# If you are using Apache aliases to do mass virtual hosting or
installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# If the above doesn't work you might need to set the `RewriteBase` directive manually, it should be the
# absolute physical path to the directory that contains this htaccess file.
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
I also added Allow from all, but it results in same way. But if i have doing something wrong why all other routes created outside of "/projects" work well. For instance, Auth related routes work well.
I know that, I have to see "Method Not Allowed" warning instead of seeing not found. Where am i doing something wrong? Any help would be very appreciated.
EDIT:
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function($req, $res) {
$handler = $this->notFoundHandler; // handle using the default Slim page not found handler
return $handler($req, $res);
});
I forgot this one. This mapping hides/exchanges method not allowed page => not found handler. It seems to me as an application based error. Sorry for my carelessness...
My suggestion is to add a root for the group you added
$app->group('/admin', function(){};
Under this you should add
$this->get('', function(){/*-----activities----*/});
And try to use $this while using the groups
Explanation:
when you are using $app you are referring to slim object.
when you are using $this inside your $app->group(){} then you are referring to grouped object which will be responsible for grouping the statements.
So, basically when you use $app inside the group then you make it useless because your slim-app is looking for it on above layer of the code(ie. outside the group). and you are not using group object($this in this case) to declare routes so eventually they are getting declared but not addressed properly.
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function($req, $res) {
$handler = $this->notFoundHandler; // handle using the default Slim page not found handler
return $handler($req, $res);
});
I forgot this one. This mapping hides/exchanges method not allowed page => not found handler. It seems to me as an application based error. Sorry for my carelessness...
But in my opinion notFoundHandler is not the right choice for this. A custom error message has to be raised for this situation like 405 Method Not Allowed - (notFoundHandler returns 404)
Not sure if this is the case, but if you need to change $app->get or $app->post to $this->get or $this->post if you group the routes.

How to get redirected to correct page with silex?

When I go to http://www.example.com/new/index.php/login/
(please note /index.php/ as part of the url.)
After successful login, I get redirects to http://www.example.com/new/welcome/
and that's correct.
but the login screen url should not have /index.php/ as this is Silex restapi.
But when I try login without /index.php/ that would be
http://www.example.com/new/login/
after login this time, I get redirected to new/index.php instead of /welcome/ like last time.
Please help.
my code is below:
Index.php:
$app = Silex\Application;
$app->mount('/login', new Routers\Login());
$app->run();
Routers\Login.php:
namespace Routers;
use Silex\Application;
use Silex\Api\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request ;
class Login implements ControllerProviderInterface
{
public function connect(Application $app)
{
// creates a new controller based on the default route
$controllers = $app['controllers_factory'];
$controllers->get('/', 'Controllers\\Login::index');
$controllers->post('/', 'Controllers\\Login::validate');
return $controllers;
}
}
Controllers\Login.php:
namespace Controllers;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
class Login {
public function index(Request $request, Application $app)
{
return $app['twig']->render('login.html');
}
public function validate(Request $request, Application $app)
{
// validation goes here
if ( // invalid ) {
return $app['twig']->render('login.html');
} else {
// valid
header("Location: /welcome");
exit;
}
}
}
htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>
EDIT:
I guess I discovered the issue, the login form is:
<form method="post" action="index.php">
instead of posting data to http://www.example.com/new/login
So how the action url must be? I tried action="/new/login" and it doesn't work. I get no route for POST /login. but this is defined in Routers/Login.php, so why should I get this?
Please advise.
EDIT2:
How can I have named routes in my Routers\Login.php as I am using organized controllers with mount like
$controllers->get('/', 'Controllers\\Login::index');
it seems it doesn't accept bind()? Does organized controllers support named routers?
If you want to let silex find the right route for you,
bind a name to your route declaration:
$controllers->get('/', 'Controllers\\Login::index')->bind('login');
and use it in your twig template
<form method="post" action="{{ path('login') }}">
It should find the url you need.

Laravel 5 pretty URL not working on wamp

I am new to Laravel, I am working over a small project, using wamp. I was facing problem with pretty URL part, which I figured it out just now.
But now I am getting a weird issue. I have created my application under directory laravel-first-app.
When I am trying to request a page (articles) for example, http://localhost/laravel-first-app/public/index.php/cv, it is showing up the page.
But now if, I request a page for example, http://localhost/laravel-first-app/public/cv, it is saying URL Not Found error.
Below is a brief description what I did.
In my routes.php
Route::get('/', 'WelcomeController#index');
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Route::resource('articles','ArticlesController');
Route::get('articles/delete/{article_id}','ArticlesController#destroy');
Route::get('cv','CvController#index');
Route::get('cv/upload','CvController#upload');
Route::post('cv','CvController#store');
In my CvController
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
class CvController extends Controller {
private $pathToCV;
private $fileName;
public function __construct()
{
$this->pathToCV="cv/";
$this->fileName='piyush_cv.doc';
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
return response()->download($this->pathToCV.$this->fileName);
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function upload()
{
return view('cv.upload');
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store(Request $request)
{
dd($request);
if($request->hasFile('cv'))
{
$file = $request->file('cv');
$file->move($this->pathToCV,$this->fileName);
flash()->overlay('File Uploaded','Thanks for uploading the file');
return redirect('cv/upload');
}
flash()->overlay('File was not selected','');
return redirect('cv/upload');
}
}
In .htaccess I have:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Also, for my wamp, I have enabled mod_rewrite module.
Can you please help me out with this? I want to use url http://localhost/laravel-first-app/public/cv instead of http://localhost/laravel-first-app/public/index.php/cv
Please help.
go to the project folder, open terminal and then run php artisan serve it will start localhost:8000 or similar like that then simply go to https://localhost:8000/articles for your required page
I looked carefully to the application structure, I figured out what was the problem.
Now, I resolved the issue and every thing is working fine.
In the Controller, CvController, I had sent a directory CV, and path name was also CV, so it was behaving weirdly.
If you want detailed solution for this, let me know.
Thanks anyways.

Categories