jdesrosiers / silex-cors-provider

A silex service provider that adds CORS services to silex
MIT License
78 stars 25 forks source link

Accept all subdomains and different protocols instead of a precise host #21

Closed MacDada closed 7 years ago

MacDada commented 8 years ago

Hi,

in my app I cannot specify all exact hosts that should be accepted. I need to whitelist all subdomains for some domain. Whitelisting any protocol would be nice as well (although I need two, http and https, so it's not much duplication).

I don't want to do: http://example.com https://example.com http://mobile.example.com https://mobile.example.com… I don't even know which subdomains are ok, I need them all.

I want to do something like *.example.com and this should match all the above.

I've implemented it myself, but it required copy–pasting and modifying Cors class, as it's not extensible in any way (no composition and its methods are private).

jdesrosiers commented 8 years ago

That would be a really great feature for the CORS protocol to define natively. But since it doesn't it would be great for a library like this to handle it. Could you submit a pull request with your modifications? That would be the quickest way to get it released to everyone.

MacDada commented 8 years ago

Yeah, but I need to rethink how would it be implemented "the proper way". In my project, for now, it is just a little hacking:

Cors:

private function allowOrigin(Request $request)
{
    if ($this->app["cors.allowOrigin"] === '*') {
        $this->app["cors.allowOrigin"] = null;
    }

    $origin = $request->headers->get("Origin");
    if (is_null($this->app["cors.allowOrigin"])) {
        $this->app["cors.allowOrigin"] = $origin;
    }

    $originDomain = $this->parseUrlDomain($origin);
    if (false === $originDomain) {
        return false;
    }

    return in_array($originDomain, preg_split('/\s+/', $this->app["cors.allowOrigin"])) ? $origin : "null";
}

private function parseUrlDomain($url)
{
    $host = parse_url($url, PHP_URL_HOST);

    if (false === $host) {
        return false;
    }

    $hostNames = explode('.', $host);

    // last 2 components ("example.com" from "m.example.com")
    return $hostNames[count($hostNames) - 2].'.'.$hostNames[count($hostNames) - 1];
}

Usage in App:

protected function enableCorsRequests(array $allowedDomains)
{
    $this->register(new \JDesrosiers\Silex\Provider\CorsServiceProvider(), [
        'cors.allowMethods' => 'GET,POST',
        'cors.allowOrigin' => join(' ', $allowedDomains),
    ]);

    $app = $this;
    $this['cors'] = $this->share(function () use ($app) {
        return new My\Overriden\Cors($app);
    });

    $this->after($this['cors']);
}
MacDada commented 8 years ago

BTW, this would break for example on http://example.co.uk:

$hostNames[count($hostNames) - 2].'.'.$hostNames[count($hostNames) - 1];

jdesrosiers commented 7 years ago

I have a basic implementation of this on master now if you want to check it out.