I'm having an issue excluding /api route from verifying token.
I'm trying to exclude all routes but not working
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
//
'*',
];
}
What I suggest is, create a middleware and use it in your routes:
Create app/Http/Middleware/Cors.php
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, \Closure $next)
{
$response = $next($request);
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization');
return $response;
}
}
Modify app/Http/Kernel.php
protected $routeMiddleware = [
...
'cors' => \App\Http\Middleware\Cors::class,
];
Finally, use it in your route file eg: routes/web.php
Route::middleware(['cors'])->group(function () {
Route::get('/', 'YourController#yourFunction');
});
Related
Laravel is not changing the language I have tried these methods in controller
if ($request->lang === 'English') {
config(['app.locale' => 'en']);
} else {
config(['app.locale' => 'ar']);
}
and this method
App::setLocale('ar')
Or this method
\App::setLocale('ar')
What should I do?
You can create a middleware that puts the locale in the session and sets it.
php artisan make:middleware SetLocale
app\Http\Middleware\SetLocale.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->input('lang') == 'English') {
$request->session()->put('locale', 'en');
} else {
$request->session()->put('locale', 'ar');
}
App::setLocale($request->session()->get('locale'));
return $next($request);
}
}
Then, add it to your global middleware (or to a middleware group).
app\Http\Kernel.php
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
// other global middlewares
\App\Http\Middleware\SetLocale::class,
];
I have a route in my web.php that returns a view:
Route::get('/', function () {
return view('welcome');
});
welcome is default Laravel view welcome.blade.php.
I have Middleware called AlwaysReturnJson and it contains:
<?php
namespace App\Http\Middleware;
use Closure;
class AlwaysReturnJson
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
I set up this middleware in Kernel.php as global middleware:
protected $middleware = [
\App\Http\Middleware\AlwaysReturnJson::class
];
What I expect is to get plain text/json of welcome file in my browser when I navigate to given route but I always get it as html and it render page properly. I checked it, it applies middleware on every request so that is not a problem. Why is this happening and shouldn't it convert that view to a plain text? Am I doing something wrong?
If you want to set a header for your response you can do this:
namespace App\Http\Middleware;
use Closure;
class AlwaysReturnJson
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
If you want to force return valid json content use this middleware instead:
namespace App\Http\Middleware;
use Closure;
class AlwaysReturnJson
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
return response()->json($response->getContent());
}
}
See Laravel docs about after middleware for more info.
You can alternatively return json response on your controller without any middleware needed:
Route::get('/', function () {
return response()->json(
view('welcome')->render()
);
});
You may want to use laravel After middleware (the middleware would perform its task after the request is handled by the application) and then set the content-type of response.
<?php
namespace App\Http\Middleware;
use Closure;
class AfterAlwaysReturnJson
{
public function handle($request, Closure $next)
{
$response = $next($request);
return $response->header('Content-Type', 'application/json');
}
}
I have to add CORS policy to my request.
So I created middleware
I already tried the following :
Route::get('/test', ['middleware' => 'cors', 'cvGenerator#show'])
or
Route::get('/test', 'cvGenerator#show');
//inside controller
$this->middleware('cors');
but none of the above work. CORS policy still aborted
my middleware code:
namespace App\Http\Middleware;
use Closure;
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin' , '*')
->header('Access-Control-Allow-Methods' , 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers' , 'X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding');
}
}
And Controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PDF;
use Illuminate\Support\Facades\Storage;
class cvGenerator extends Controller
{
public function show(Request $request)
{
$this->middleware('cors');
echo 'test';
//some code that generate output
}
}
How can I pass the request?
If you have just one route that should go through the middleware. Also middleware doesn’t belong in the controller.
Route::get('/test', 'cvGenerator#show')->middleware('cors');
If you have more than one route, you can use a route group.
Route::group(['middleware' => ['cors']], function () {
Route::get('/test', 'cvGenerator#show');
});
Also Laravel has a pretty good docs about middleware.
CORS
We're using this middleware to support pre-flight CORS requests:
<?php
namespace App\Http\Middleware;
use Closure;
class AddCorsHeaders
{
/**
* Check for CORS request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #return mixed
*/
public function handle($request, Closure $next)
{
$headers = [
'Access-Control-Allow-Origin' => $request->header('Origin'),
'Access-Control-Allow-Methods' => 'HEAD, POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers' => $request->header('Access-Control-Request-Headers'),
];
if ($request->isMethod('OPTIONS')) {
return response()->json('{"method":"OPTIONS"}', 200, $headers);
}
if ($request->header('Origin')) {
config(['access-control-origin' => $request->header('Origin')]);
}
return $next($request);
}
}
Don't forget to add this to your kernel.php in the $routeMiddleware array.
'cors' => \App\Http\Middleware\AddCorsHeaders::class,
I have the following middleware (LastSeen):
<?php
namespace App\Http\Middleware;
use Closure;
use Carbon\Carbon;
use Illuminate\Contracts\Auth\Factory as Auth;
class LastSeen
{
/**
* The authentication factory instance.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
$user = $this->auth->user();
$user->last_activity = Carbon::now();
$user->save();
}
return $next($request);
}
}
This was mostly taken from this answer ( Check if user online laravel ) as a stop-gap solution to a project I am working on.
I do have a TIMESTAMP column in my users table labeled last_activity and this is my Kernel file global middleware:
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\LastSeen::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\ModifyHeadersMiddleware::class,
];
I'm not sure where to go next, I am just beginning on middleware and am still learning but not sure what I'm doing wrong...
Thanks!
The problem is that info about authorized user is stored in session and LastSeen's auth check is running before session was started so it allways return false.
You need to move LastSeen middleware after StartSession middleware:
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\LastSeen::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
There are some issues, but the main mistake is you are calling the wrong Auth. You have to call the facade, you are calling the Auth factory. Another thing is, avoid the constructor. Keep it simple. Especially for MiddleWare. One last thing, you are updating the user status, not saving a new entry.
namespace App\Http\Middleware;
use Closure;
use Carbon\Carbon;
use Auth;
class LastSeen
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()) {
$user = Auth::user();
$user->last_activity = Carbon::now();
$user->update();
}
return $next($request);
}
}
I am using an OAuth2 client that does not send Authorization: Bearer but the standard laravel/passport setup checks this header. How to make it compatible from Laravel side?
Add the following middle ware
<?php
namespace App\Http\Middleware;
class ConvertTokenToBearer
{
/**
* #param \Illuminate\Http\Request $request
* #param $next
*
* #return \Symfony\Component\HttpFoundation\Response
*/
public function handle($request, $next)
{
if ($request->get('access_token')) {
$request->headers->set('Authorization', 'Bearer ' . $request->get('access_token'));
}
$response = $next($request);
return $response;
}
}
And add it to your app/Http/Kernel.php file.
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\App\Http\Middleware\ConvertTokenToBearer::class,
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];