Laravel set cookie not working - laravel

I have the following code in a custom middleware:
public function handle($request, Closure $next)
{
if($request->hasCookie('uuid')) {
return $next($request);
}
$uuid = 99;
$response = $next($request);
return $response->withCookie(cookie()->forever('uuid', $uuid));
}
I have registered the middleware in the app.php file, but cookies is still not being written. Please can anyone help. Additionally can this above be run as a singleton, so that it is executed once on app start?
Thanks

If you are on a local environment, make sure to set 'secure' => env('SESSION_SECURE_COOKIE', false), around lines #165-170 in your config/session.php file.
On a non-SSL domain (like http://localhost/), this directive must be false. Otherwise cookies will not be set in browser.

Here, I'm mention set and get a cookie in laravel simple example following.
First of the create a controller.
1.php artisan make:controller CookieController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class CookieController extends Controller {
**/* below code a set a cookie in browser */**
public function setCookie(Request $request){
$response = new Response('Hello World');
$response->withCookie(cookie('name', 'Anything else'));
return $response;
}
**/* below code a get a cookie in browser */**
public function getCookie(Request $request){
$value = $request->cookie('name');
echo $value;
}
}
Add a following line code in routes/web.php file (Laravel 5.4)
Route::get('/cookie/set','CookieController#setCookie');
Route::get('/cookie/get','CookieController#getCookie');
And all files add-in project than a run program easily sets and get a cookie.

You can obtain the response object in middleware like so:
public function handle($request, Closure $next)
{
$response = $next($request);
// Do something after the request is handled by the application
return $response;
}
So you could do something like this
if($request->hasCookie('uuid')) {
return $next($request);
}
$uuid = Uuid::generate();
$response = $next($request);
return $response->withCookie(cookie()->forever('uuid', $uuid));

You can use the laravel helper function cookie(). This worked for me.
<?php
//Create:
cookie()->queue(cookie($name, $value, $minutes));
// forever
cookie()->queue(cookie()->forever($name, $value));
//get
request()->cookie($name);
//forget
cookie()->queue(cookie()->forget($name));

Related

Laravel - Delete Cookie in Middleware

I have a middleware in my project that call in every request. It will check if Request has a specific cookie, then delete another cookie. But it seems Cookies are not forgotten or set in Laravel until return in the response. something like
return response('view')->withCookie($cookie); that is not possible in middlewares.
Also I tried Cookie::queue(Cookie::forget('myCookie')); nothing happened and cookie is shown in my browser.
This is my middleware handle method:
public function handle(Request $request, Closure $next)
{
if (! $request->cookie('clear_token')) {
cookie()->forget('access_token'); # not worked
Cookie::queue(Cookie::forget('access_token')); # not worked
}
return $next($request);
}
You can change the response in middleware too:
https://laravel.com/docs/5.0/middleware
<?php namespace App\Http\Middleware;
class AfterMiddleware implements Middleware {
public function handle(\Illuminate\Http\Request $request, \Closure $next)
{
$response = $next($request);
// Forget cookie
return $response;
}
}

Laravel load middleware in routes under condition

I have a route files for my api and im using this package to cache the whole response.
routes/api.php
<?php
Route::get('/types', 'TypeController#indexType')->middleware('cacheResponse:600');
This works fine but i need to skip this middleware loading when i have a specific header in the request so i make this extra middleware
conditionalCacheResponse.php
<?php
namespace App\Http\Middleware;
use Closure;
class ConditionalCacheResponse
{
public function handle($request, Closure $next)
{
if (request()->header('Draft') != true) {
$this->middleware('cacheResponse:3600');
}
return $next($request);
}
}
and setup like this
routes/api.php
<?php
Route::get('/types', 'TypeController#indexType')->middleware('conditionalCacheResponse');
But is not working, im not sure if i can append a middleware in this way.
There's a few ways to do this, one way would be to use the handle() method of the HttpKernel to unset the CacheResponse middleware based on a check of the request header.
So in app/Http/Kernel.php, add this method:
public function handle($request)
{
if ($request->header('Draft')) {
if (($key = array_search('Spatie\ResponseCache\Middlewares\CacheResponse', $this->middleware)) !== false) {
unset($this->middleware[$key]);
}
}
return parent::handle($request);
}
I haven't checked this is working, but it should do the job.

How to execute code on every page load, but only after route controller executed?

I'm working on a Laravel based project and I need to execute some "basic" php code on every page load. Until now, I placed my code in boot() from AppServiceProvider. It works well, but I need to execute my "basic" code only after the code from route's controller has been already executed.
I've already searched in laravel's official docs, but I still did not figured out how to do it.
This is how my route looks:
Route::match(['get', 'post'], '/profile/email/{profile_id?}', 'profileController#profileHandleEmail')->name('profile/email');
The result I want to achive is to execute the code from profileController#profileHandleEmail before the "basic" code from AppServiceProvider.
Which would be the best way to do this? I guess it can't be achived using AppServiceProvider.
The suggested way to achieve what you want is to use middleware:
Run php artisan make:middleware PostProcess
It should generate the a middleware class under App\Http\Middleware
class PostProcess {
public function handle($request, $next) {
$response = $next($request);
// Run you code here.
return $response
}
}
Then modify your App\Http\Kernel.php middleware:
protected $middleware = [
//Existing entries
\App\Http\Middleware\PostProcess::class
];
That middleware will run after the response has been generated but before the response is sent to the client. If you want to run the code after the response was sent to the client you can use terminable middleware
class PostProcess {
public function handle($request, $next) {
return $next($request);
}
public function terminate($request, $response) {
//Your code here
}
}
Step1 : Create Middleware
php artisan make:middleware PostProcess
Step2 : Make a code which you need
class PostProcess {
public function handle($request, $next) {
if(condition){
you code here
}
return $next($request);
}
}
Step3 : Call middleware in kernel.php
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\PostProcess::class,
];
Step 4: Call middleware in route file
Route::group(['middleware' => 'admin'], function() {
});

return a json error in middleware?

I'm building an app and I'm using laravel5 as webAPI.
When the webAPI is in Maintenance Mode, I want to return a json error to app and I will get the status code in app to show a suitable message.
I rewrite the laravel CheckForMaintenanceMode for somereason and registed it in Kernel.
I write
if ($this->app->isDownForMaintenance()) {
$ip = $request->getClientIp();
$allowIp = "111.222.333.444";
if ($allowIp != $ip) {
return response()->json(['error' => "Maintenance!!"], 503);
}
}
return $next($request);
But I can get NOTHING in app side.I cannot get the message, the satus....
I writh the same code like return response()->json(['error' => "errormessage"], 422); in controller and I can get the message.status.. in app but I cannot do the same thing in a middleware.
why? how to do it?
This worked:
if ($this->app->isDownForMaintenance()) {
$ip = $request->getClientIp();
$allowIp = "111.222.333.444";
if ($allowIp != $ip) {
return response(['Maintenance'], 503);
}
}
return $next($request);
And not register the middleware in Kernel global HTTP middleware but put it in the route(api.php),like:
Route::group(['middleware' => 'maintenance'], function(){******}
I really donot know why but this worked for me.
Full example
public function handle($request, Closure $next)
{
if($request->token == "mytoken")
return $next($request);
else return response(['Token mismatch'],403);
}
Explanation
The response of a middleware
must be an instance of Symfony\Component\HttpFoundation\Response
so, for return a json, you have to do this
return response(['Token mismatch'],403);
The middleware must be registered in Kernel.php
The cleaner way to do it is to extend the
Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode class
and change it as per our needs and update the App\Http\Kernel.php like so..
App\Http\CustomMaintanceMiddleware.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
class CustomMaintanceMiddleware extends CheckForMaintenanceMode
{
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance()) {
return response(['Maintenance'], 503);
}
return $next($request);
}
}
Kernel.php
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class
];
TO
protected $middleware = [
\App\Http\CustomMaintanceMiddleware::class
];

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