slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.94k stars 1.95k forks source link

Feature Request: Ability to disable sending session cookie #1084

Closed funkatron closed 9 years ago

funkatron commented 9 years ago

We ran into this scenario on our last major Slim 2 project:

The site used authentication for user accounts and such, but much of the content was viewable whether or not you were logged-in. Authenticated requests obviously required a session cookie, but we wanted to cache non-authenticated requests with Varnish, and sending a constantly changing session cookie would constantly break the cache.

We had to hack around this to set a flag that said "undo sending a cookie!" when we determined that the user was not logged in (some pages allowed both authenticated and non-authenticated access, so you couldn't just do it on a per-route basis). The flag would then modify the Cookie header (which had already been set, because we had sessions enabled) in the final response stages.

(I don't yet have access to the code, but I'm asking my previous employer to check out that bit, so I could share. It's super duper hackey.)

tl;dr: It would be really handy to, one way or another, say "oh, I don't want a session cookie sent -- kill it!" at some arbitrary point in route handler processing.

<?php
/**
* extends Slim App class to add functionality
*/
class App extends Slim
{
    /**
     * use this to block the cookie header from being sent entirely
     * @param  boolean $state
     */
    public function blockCookie($state)
    {
        if ($state) {
            $_ENV['FKAPP_BLOCK_COOKIE'] = true;
        } else {
            unset($_ENV['FKAPP_BLOCK_COOKIE']);
        }
    }

    /**
     * This is a duplicate of the method in \Slim\Slim, except it will not set
     * the cookie if $_ENV['FKAPP_BLOCK_COOKIE'] is truthy
     * @see \FKApp\Lib\App::blockCookie()
     */
    public function run()
    {
        set_error_handler(array('\Slim\Slim', 'handleErrors'));

        //Apply final outer middleware layers
        if ($this->config('debug')) {
            //Apply pretty exceptions only in debug to avoid accidental information leakage in production
            $this->add(new \Slim\Middleware\PrettyExceptions());
        }

        //Invoke middleware and application stack
        $this->middleware[0]->call();

        //Fetch status, header, and body
        list($status, $headers, $body) = $this->response->finalize();

        // Serialize cookies (with optional encryption)
        if (!empty($_ENV['FKAPP_BLOCK_COOKIE'])) {
            // we want to block the cookie, but we should only do that if the
            // client did not send us a cookie in its request, So we should
            // check if a cookie with our config name was sent
            if (!isset($_COOKIE[$this->config('cookies.name')])) {
                $this->log->addDebug('Not building set-cookie headers ($_COOKIE[$cookies_name] was falsy)');
            } else {
                $this->log->addDebug('Building set-cookie header because cookie was sent by client');
                \Slim\Http\Util::serializeCookies($headers, $this->response->cookies, $this->settings);
            }
        } else {
            $this->log->addDebug('Building set-cookie header');
            \Slim\Http\Util::serializeCookies($headers, $this->response->cookies, $this->settings);
        }

        //Send headers
        if (headers_sent() === false) {
            //Send status
            if (strpos(PHP_SAPI, 'cgi') === 0) {
                header(sprintf('Status: %s', \Slim\Http\Response::getMessageForCode($status)));
            } else {
                header(sprintf('HTTP/%s %s', $this->config('http.version'), \Slim\Http\Response::getMessageForCode($status)));
            }

            //Send headers
            foreach ($headers as $name => $value) {
                $hValues = explode("\n", $value);
                foreach ($hValues as $hVal) {
                    header("$name: $hVal", false);
                }
            }
        }

        //Send body, but only if it isn't a HEAD request
        if (!$this->request->isHead()) {
            echo $body;
        }

        restore_error_handler();
    }
}
codeguy commented 9 years ago

Agreed. This would be nice. I think this is a good candidate for the forthcoming session middleware layer since Slim core will no longer touch anything related to sessions. This is related to https://github.com/slimphp/Slim/issues/1049

codeguy commented 9 years ago

Looping @silentworks in on this.

funkatron commented 9 years ago

I added code to show how we hacked around it. It's pretty… hackey.

harikt commented 9 years ago

Interesting @funkatron . That brings me to another place, I like how conduit does this. You can attach a middleware to a route. I hope Slim can also do the same ?

codeguy commented 9 years ago

@harikt Slim has had route middleware since 2.0.

harikt commented 9 years ago

nice :) .

Hari K T

You can ring me : +91 9388 75 8821

http://harikt.com , https://github.com/harikt , http://www.linkedin.com/in/harikt , http://www.xing.com/profile/Hari_KT

Skype : kthari85 Twitter : harikt

On Wed, Mar 11, 2015 at 7:27 PM, Josh Lockhart notifications@github.com wrote:

@harikt https://github.com/harikt Slim has had route middleware since 2.0.

— Reply to this email directly or view it on GitHub https://github.com/slimphp/Slim/issues/1084#issuecomment-78267198.

codeguy commented 9 years ago

@funkatron Isn't this already solved with 3.x since we are no longer saving session data into cookies?