From 61667e78680509764bdf56ef6730314c8c267771 Mon Sep 17 00:00:00 2001 From: Awilum Date: Tue, 21 Apr 2020 12:50:10 +0300 Subject: [PATCH] feat(core): Enable lazy CORS for all routes with config --- src/flextype/bootstrap.php | 16 +++----- src/flextype/config/settings.yaml | 38 ++++++++++++++++++ src/flextype/core/Cors/Cors.php | 66 +++++++++++++++++++++++++++++++ src/flextype/dependencies.php | 7 ++++ 4 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 src/flextype/core/Cors/Cors.php diff --git a/src/flextype/bootstrap.php b/src/flextype/bootstrap.php index c3df0ef8..d5ad98e0 100755 --- a/src/flextype/bootstrap.php +++ b/src/flextype/bootstrap.php @@ -165,18 +165,12 @@ $flextype['plugins']->init($flextype, $app); /** * Enable lazy CORS + * + * CORS (Cross-origin resource sharing) allows JavaScript web apps to make HTTP requests to other domains. + * This is important for third party web apps using Flextype, as without CORS, a JavaScript app hosted on example.com + * couldn't access our APIs because they're hosted on another.com which is a different domain. */ -$app->options('/{routes:.+}', function ($request, $response, $args) { - return $response; -}); - -$app->add(function ($req, $res, $next) { - $response = $next($req, $res); - return $response - ->withHeader('Access-Control-Allow-Origin', '*') - ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') - ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); -}); +$flextype['cors']->init(); /** * Run application diff --git a/src/flextype/config/settings.yaml b/src/flextype/config/settings.yaml index d3c08a35..8169aa14 100644 --- a/src/flextype/config/settings.yaml +++ b/src/flextype/config/settings.yaml @@ -187,6 +187,44 @@ slugify: image: driver: gd +# CORS +# +# CORS (Cross-origin resource sharing) allows JavaScript web apps to make HTTP requests to other domains. +# This is important for third party web apps using Flextype, as without CORS, a JavaScript app hosted on example.com +# couldn't access our APIs because they're hosted on another.com which is a different domain. +# +# - enabled: Set to true to enable cors +# +# - origin: The Access-Control-Allow-Origin response header indicates whether +# the response can be shared with requesting code from the given origin. +# read more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin +# +# - headers: The Access-Control-Allow-Headers response header is used in response +# to a preflight request which includes the Access-Control-Request-Headers +# to indicate which HTTP headers can be used during the actual request. +# read more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers +# +# - methods: The Access-Control-Allow-Methods response header specifies the method +# or methods allowed when accessing the resource in response to a preflight request. +# read more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods +# +# - expose: The Access-Control-Expose-Headers response header indicates which headers +# can be exposed as part of the response by listing their names. +# read more: https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Access-Control-Expose-Headers +# +# - credentials: The Access-Control-Allow-Credentials response header tells browsers whether +# to expose the response to frontend JavaScript code when the request's credentials +# mode (Request.credentials) is include. +# read more: https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials +cors: + enabled: true + origin: "*" + headers: ["X-Requested-With", "Content-Type", "Accept", "Origin", "Authorization"] + methods: [GET, POST, PUT, DELETE, PATCH, OPTIONS] + expose: [] + credentials: false + + # API's api: delivery: diff --git a/src/flextype/core/Cors/Cors.php b/src/flextype/core/Cors/Cors.php new file mode 100644 index 00000000..f7073417 --- /dev/null +++ b/src/flextype/core/Cors/Cors.php @@ -0,0 +1,66 @@ +flextype = $flextype; + $this->app = $app; + } + + /** + * Init CORS + */ + public function init() + { + $flextype = $this->flextype; + + if ($flextype['registry']->get('flextype.settings.cors.enabled')) { + + $this->app->options('/{routes:.+}', function ($request, $response, $args) { + return $response; + }); + + $this->app->add(function ($req, $res, $next) use ($flextype) { + $response = $next($req, $res); + + // Set variables + $origin = $flextype['registry']->get('flextype.settings.cors.origin'); + $headers = count($flextype['registry']->get('flextype.settings.cors.headers')) ? implode(', ', $flextype['registry']->get('flextype.settings.cors.headers')) : ''; + $methods = count($flextype['registry']->get('flextype.settings.cors.methods')) ? implode(', ', $flextype['registry']->get('flextype.settings.cors.methods')) : ''; + $expose = count($flextype['registry']->get('flextype.settings.cors.expose')) ? implode(', ', $flextype['registry']->get('flextype.settings.cors.expose')) : ''; + $credentials = ($flextype['registry']->get('flextype.settings.cors.credentials')) ? true : false; + + return $response + ->withHeader('Access-Control-Allow-Origin', $origin) + ->withHeader('Access-Control-Allow-Headers', $headers) + ->withHeader('Access-Control-Allow-Methods', $methods) + ->withHeader('Access-Control-Allow-Expose', $expose) + ->withHeader('Access-Control-Allow-Credentials', $credentials); + }); + } + } +} diff --git a/src/flextype/dependencies.php b/src/flextype/dependencies.php index ca29a36b..8300518b 100644 --- a/src/flextype/dependencies.php +++ b/src/flextype/dependencies.php @@ -187,3 +187,10 @@ $flextype['entries'] = static function ($container) { $flextype['plugins'] = static function ($container) use ($flextype, $app) { return new Plugins($flextype, $app); }; + +/** + * Add cors service to Flextype container + */ +$flextype['cors'] = static function ($container) use ($flextype, $app) { + return new Cors($flextype, $app); +};