Hiding the controller path in the URL

124 Views Asked by At

I have these URLs:

  • https://my.example.com/api/foo
  • https://my.example.com/api/bar
  • https://my.example.com/api/baz

In order to simplify it for the user and also to emphasise the different meaning I have set up these subdomains which have the same DocumentRoot as https://my.example.com/:

  • https://foo.example.com/
  • https://bar.example.com/
  • https://baz.example.com/

Due to the fact I am not capable to do the final step which means the URLs are still like this:

  • https://foo.example.com/api/foo
  • https://bar.example.com/api/bar
  • https://baz.example.com/api/baz

which isn't really simplifying it as the user has still to append api/<name> to the URL.

My question:

Is there a way to omit /api/<name> and redirect it somehow in the CakePHP controller so it's enough to enter https://foo.example.com/ and this would run the code in https://foo.example.com/api/foo?

I can check the current subdomain using $_SERVER ["SERVERNAME"] so this isn't the problem.

What makes it a bit more difficult:

The login page is as usually accessed through https://foo.example.com/users/login which means when /users/login is a part of the URL then the invisible redirect must NOT be triggered. However, I think I can prevent this checking the content of the $_SERVER variable.

I really hope you guys understand what I mean.

PS: I don't want to use Apache's redirect as this would display the final URL https://foo.example.com/api/foo in the browser.

Running CakePHP 4.1.4

1

There are 1 best solutions below

1
On BEST ANSWER

I don't really see how this is more simple, if anything I'd find it to be less verbose, which is never good for a URL. Anyways, it sounds like you're looking for host bound routes, ie the _host option.

This would connect / to foo.example.com, bar.example.com, and baz.example.com, each to a different controller depending on the host:

$routes->scope(
    '/',
    function (\Cake\Routing\RouteBuilder $builder) {
        $builder
            ->connect('/', ['controller' => 'Foo'])
            ->setHost('foo.example.com');

        $builder
            ->connect('/', ['controller' => 'Bar'])
            ->setHost('bar.example.com');

        $builder
            ->connect('/', ['controller' => 'Baz'])
            ->setHost('baz.example.com');

        $builder
            ->connect('/users/login', ['controller' => 'Users', 'action' => 'login']);
    }
);

The /users/login URL would connect to any host, as it's not being restricted, ie all of these URLs would work and point to the same controller and action:

  • foo.example.com/users/login
  • bar.example.com/users/login
  • baz.example.com/users/login

That could possibly introduce further problems, like for example cookies not working if they're not scoped for all subdomains, or duplicate content as far as SEO goes. So make sure that you keep your routes as specific as possible!

Also note that resource routing won't work properly with this, as it requires a path element, ie you cannot connect resources on just /, eg foo.example.com, it would have to be foo.example.com/resource-name, if you'd wanted to connect to the former, each resource route would need to be connected manually.

Finally, if you're not using named routes, then you'll have to use '_host' => 'foo.example.com' in your URL arrays if you want to generate URLs!

See also