CakePHP 4 $this->request->referer() not working in production

Written by James McDonald

June 24, 2020

Just had a situation where I couldn’t get a redirect to work. My CakePHP app is in an Apache enabled docker container behind an nginx reverse proxy


The above simply refused to work in my development environment it worked fine

http://localhost:8090/blah/ worked fine


and it would return nothing

It turned out that if your hostnames don’t match i.e. your front end is accessed via and your backend is accessed via http://localhost:8090/blah then a call to $request->referer() return bupkis

This works although I imagine some sanitizing needs to be done to stop it just accepting any forged referer URL

$this->redirect($this->request->referer($local = false));


$referer = $this->request->referer(false);
if( preg_match('', $referer ) === 1 ) {
     return $this->redirect($referer);
} else {
     return $this->redirect([ 'action' => 'index' ]);

Taking into account a trusted proxy (i.e. it can tell you what the external http_host name is)

        $this->request->trustProxy = true;
        $referer = $this->request->referer($local = false);
        $host = $this->request->host(); 
        $scheme = $this->request->scheme();

        if (preg_match('/^' . $scheme . ':\/\/' . $host . '/', $referer) === 1) {
            return $this->redirect($referer);
        return $this->redirect(['action' => 'index']);

Nginx Configuration

Note I’m only trusting this because nginx is setting the headers:

upstream my-test {
location /test {
    proxy_pass http://my-test;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Forwarded-Proto https;

Notes about this nginx config

Front end running https Backend running http

This nginx frontend server block is running ssl enabled

The backend is running only http so specify http:// to upstream

proxy_pass http://my-test;

Proxy Pass Trailing Slash or Lack of it Changes the Behavior

Without a trailing slash

If you specify no trailing forward slash then the location and all subsequent pieces are passed. For example a request made to the front end nginx to:
# is passed to the backend as

With a trailing slash

if you specify proxy_pass http://my-test/; a request to will be passed on without the location /test parameter
# is passed to the backend as

X-Forwarded-Proto Header Required

I found if I didn’t set this header

proxy_set_header X-Forwarded-Proto https;

Then after I posted a delete e.g. POST /test/controller/delete/23 the 302 redirect issued to the client would have the wrong scheme in the location header:


And then nginx would issue an internal redirect and mess-up the redirect

with the X-Forwarded-Proto header set it performed as required



Submit a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.

You May Also Like…

Clear HSTS Settings in CHrome

Open chrome://net-internals/#hsts enter the domain in the query field and click Query to confirm it has HSTS settings...

Ubuntu on Hyper-v

It boils town to installing linux-azure # as root or sudo apt-get update apt-get install linux-azure...