Skip to content

Commit 215968e

Browse files
committed
Initial commit of the module code to GitHub
0 parents  commit 215968e

File tree

14 files changed

+483
-0
lines changed

14 files changed

+483
-0
lines changed

Api/CorsCheckInterface.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright 2017 SplashLab
5+
*/
6+
7+
namespace SplashLab\CorsRequests\Api;
8+
9+
/**
10+
* Interface CorsCheckInterface
11+
* @api
12+
* @package SplashLab\CorsRequests\Api
13+
*/
14+
interface CorsCheckInterface
15+
{
16+
17+
/**
18+
* Return empty body response
19+
*
20+
* @return string
21+
*/
22+
public function check();
23+
24+
}

Model/CorsCheck.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* @copyright Copyright 2017 SplashLab
4+
*/
5+
6+
namespace SplashLab\CorsRequests\Model;
7+
8+
use SplashLab\CorsRequests\Api\CorsCheckInterface;
9+
10+
/**
11+
* Class CorsCheck
12+
* @package SplashLab\CorsRequests\Model
13+
*/
14+
class CorsCheck implements CorsCheckInterface
15+
{
16+
17+
/**
18+
* Initialize dependencies.
19+
*
20+
* @param \Magento\Framework\Webapi\Rest\Response $response
21+
* @param \Magento\Framework\App\Config\ScopeConfigInterface scopeConfig
22+
*/
23+
public function __construct(
24+
\Magento\Framework\Webapi\Rest\Response $response,
25+
\Magento\Framework\Webapi\Rest\Request $request
26+
) {
27+
$this->response = $response;
28+
$this->request = $request;
29+
}
30+
31+
/**
32+
* {@inheritDoc}
33+
*/
34+
public function check()
35+
{
36+
// respond to OPTIONS request with appropriate headers
37+
$this->response->setHeader('Access-Control-Allow-Methods', $this->request->getHeader('Access-Control-Request-Method'), true);
38+
$this->response->setHeader('Access-Control-Allow-Headers', $this->request->getHeader('Access-Control-Request-Headers'), true);
39+
return '';
40+
}
41+
42+
}

Plugin/CorsHeadersPlugin.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright 2017 SplashLab
5+
*/
6+
7+
namespace SplashLab\CorsRequests\Plugin;
8+
9+
use Magento\Framework\App\FrontControllerInterface;
10+
use Magento\Framework\App\RequestInterface;
11+
12+
/**
13+
* Class CorsHeadersPlugin
14+
*
15+
* @package SplashLab\CorsRequests
16+
*/
17+
class CorsHeadersPlugin
18+
{
19+
20+
/**
21+
* @var \Magento\Framework\Webapi\Rest\Response
22+
*/
23+
private $response;
24+
25+
/**
26+
* @var \Magento\Framework\App\Config\ScopeConfigInterface
27+
*/
28+
private $scopeConfig;
29+
30+
/**
31+
* Initialize dependencies.
32+
*
33+
* @param \Magento\Framework\Webapi\Rest\Response $response
34+
* @param \Magento\Framework\App\Config\ScopeConfigInterface scopeConfig
35+
*/
36+
public function __construct(
37+
\Magento\Framework\Webapi\Rest\Response $response,
38+
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
39+
) {
40+
$this->response = $response;
41+
$this->scopeConfig = $scopeConfig;
42+
}
43+
44+
/**
45+
* Get the origin domain the requests are going to come from
46+
* @return string
47+
*/
48+
protected function getOriginUrl()
49+
{
50+
return $this->scopeConfig->getValue('corsRequests/general/origin_url',
51+
\Magento\Store\Model\ScopeInterface::SCOPE_STORE);
52+
}
53+
54+
/**
55+
* Get the origin domain the requests are going to come from
56+
* @return string
57+
*/
58+
protected function getAllowCredentials()
59+
{
60+
return (bool) $this->scopeConfig->getValue('corsRequests/general/allow_credentials',
61+
\Magento\Store\Model\ScopeInterface::SCOPE_STORE);
62+
}
63+
64+
/**
65+
* Triggers before original dispatch
66+
* This method triggers before original \Magento\Webapi\Controller\Rest::dispatch and set version
67+
* from request params to VersionManager instance
68+
* @param FrontControllerInterface $subject
69+
* @param RequestInterface $request
70+
* @return void
71+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
72+
*/
73+
public function beforeDispatch(
74+
FrontControllerInterface $subject,
75+
RequestInterface $request
76+
) {
77+
if ($originUrl = $this->getOriginUrl()) {
78+
$this->response->setHeader('Access-Control-Allow-Origin', rtrim($originUrl,"/"), true);
79+
if ($this->getAllowCredentials()) {
80+
$this->response->setHeader('Access-Control-Allow-Credentials', 'true', true);
81+
}
82+
}
83+
}
84+
85+
}

Plugin/CorsRequestMatchPlugin.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright 2017 SplashLab
5+
*/
6+
7+
namespace SplashLab\CorsRequests\Plugin;
8+
9+
use Magento\Framework\Webapi\Rest\Request;
10+
use Magento\Webapi\Controller\Rest\Router;
11+
12+
/**
13+
* Class CorsRequestMatchPlugin
14+
*
15+
* @package SplashLab\CorsRequests
16+
*/
17+
class CorsRequestMatchPlugin
18+
{
19+
20+
/**
21+
* @var \Magento\Framework\Webapi\Rest\Request
22+
*/
23+
private $request;
24+
25+
/**
26+
* @var \Magento\Framework\Controller\Router\Route\Factory
27+
*/
28+
protected $routeFactory;
29+
30+
/**
31+
* Initialize dependencies.
32+
*
33+
* @param \Magento\Framework\Webapi\Rest\Request $request
34+
* @param \Magento\Framework\Controller\Router\Route\Factory $routeFactory
35+
*/
36+
public function __construct(
37+
\Magento\Framework\Webapi\Rest\Request $request,
38+
\Magento\Framework\Controller\Router\Route\Factory $routeFactory
39+
) {
40+
$this->request = $request;
41+
$this->routeFactory = $routeFactory;
42+
}
43+
44+
/**
45+
* Generate the list of available REST routes. Current HTTP method is taken into account.
46+
*
47+
* @param \Magento\Webapi\Model\Rest\Config $subject
48+
* @param $proceed
49+
* @param Request $request
50+
* @return \Magento\Webapi\Controller\Rest\Router\Route
51+
* @throws \Magento\Framework\Webapi\Exception
52+
*/
53+
public function aroundMatch(
54+
Router $subject,
55+
callable $proceed,
56+
Request $request
57+
)
58+
{
59+
try {
60+
$returnValue = $proceed($request);
61+
} catch (\Magento\Framework\Webapi\Exception $e) {
62+
$requestHttpMethod = $this->request->getHttpMethod();
63+
if ($requestHttpMethod == 'OPTIONS') {
64+
return $this->createRoute();
65+
} else {
66+
throw $e;
67+
}
68+
}
69+
return $returnValue;
70+
}
71+
72+
/**
73+
* Create route object to the placeholder CORS route.
74+
*
75+
* @return \Magento\Webapi\Controller\Rest\Router\Route
76+
*/
77+
protected function createRoute()
78+
{
79+
/** @var $route \Magento\Webapi\Controller\Rest\Router\Route */
80+
$route = $this->routeFactory->createRoute(
81+
'Magento\Webapi\Controller\Rest\Router\Route',
82+
'/V1/cors/check'
83+
);
84+
85+
$route->setServiceClass('SplashLab\CorsRequests\Api\CorsCheckInterface')
86+
->setServiceMethod('check')
87+
->setSecure(false)
88+
->setAclResources(['anonymous'])
89+
->setParameters([]);
90+
91+
return $route;
92+
}
93+
94+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright 2017 SplashLab
5+
*/
6+
7+
namespace SplashLab\CorsRequests\Plugin;
8+
9+
use Magento\Framework\Webapi\Request;
10+
11+
/**
12+
* Class CorsRequestOptionsPlugin
13+
*
14+
* @package SplashLab\CorsRequests
15+
*/
16+
class CorsRequestOptionsPlugin
17+
{
18+
19+
/**
20+
* Triggers before original dispatch
21+
* Allow Options requests from jQuery AJAX
22+
*
23+
* @param Request $subject
24+
* @return void
25+
* @throws \Magento\Framework\Exception\InputException
26+
*/
27+
public function aroundGetHttpMethod(
28+
Request $subject
29+
) {
30+
if (!$subject->isGet() && !$subject->isPost() && !$subject->isPut() && !$subject->isDelete() && !$subject->isOptions()) {
31+
throw new \Magento\Framework\Exception\InputException(new Phrase('Request method is invalid.'));
32+
}
33+
return $subject->getMethod();
34+
}
35+
36+
}

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Magento 2 CORS Cross-Domain Requests by SplashLab
2+
3+
This module allows you to enable Cross-Origin Resource Sharing (CORS) REST API requests in Magento 2 by adding the appropriate HTTP headers and handling the pre-flight OPTIONS requests.
4+
5+
This can be used to allow AJAX and other requests to the Magento 2 REST API from another domain (or subdomain).
6+
7+
## How to install
8+
9+
### 1. via composer
10+
11+
```
12+
composer require splashlab/magento-2-cors-requests
13+
php bin/magento setup:upgrade
14+
php bin/magento setup:static-content:deploy
15+
```
16+
17+
### 2. Copy and paste
18+
19+
Download latest version from GitHub
20+
21+
Paste into `app/code/SplashLab/CorsRequests` directory
22+
23+
```
24+
php bin/magento setup:upgrade
25+
php bin/magento setup:static-content:deploy
26+
```
27+
28+
## How does it work?
29+
30+
The full implementation of CORS cross-domain HTTP requests is outside the scope of this README, but this is what this module does:
31+
32+
1. Allows onfigureing an Origin Url in the Admin Configuration area - this is the domain which cross-domain requests are permitted from
33+
2. This domain is added to a `Access-Control-Allow-Origin` response HTTP header
34+
3. Optionally you can enable the `Access-Control-Allow-Credentials` header as well, to enable passing cookies
35+
36+
For non-GET and non-standard-POST requests (i.e. PUT and DELETE), the "pre-flight check" OPTIONS request is handled by:
37+
38+
1. An empty `/V1/cors/check` API response with the appropriate headers:
39+
2. `Access-Control-Allow-Methods` response header, which mirrors the `Access-Control-Request-Method` request header
40+
3. `Access-Control-Allow-Headers` response header, which mirrors the `Access-Control-Request-Headers` request header
41+
42+
### Alternative Solutions
43+
44+
You can also manage these CORS headers with Apache and Nginx rules, instead of using this extension:
45+
46+
- https://community.magento.com/t5/Magento-2-Feature-Requests-and/API-CORS-requests-will-fail-without-OPTIONS-reponse/idi-p/60551
47+
- https://stackoverflow.com/questions/35174585/how-to-add-cors-cross-origin-policy-to-all-domains-in-nginx
48+
49+
But I created this extension to allow you to configure the Origin domain the Admin Configuration, and to avoid having to create and manage special server configuration.
50+
51+
## CORS Cross-Domain Request References
52+
53+
Not only can you create unlimited sliders but Product Slider module also allows placing the sliders like content or sidebar additional at the top or bottom of any page on your website flexibly. The options you can put the sliders are:
54+
55+
- https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
56+
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
57+
- https://www.html5rocks.com/en/tutorials/cors/
58+
- https://stackoverflow.com/questions/29954037/how-to-disable-options-request
59+
- https://stackoverflow.com/questions/12320467/jquery-cors-content-type-options
60+
61+
62+
63+

composer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "splashlab/cors-requests",
3+
"description": "N/A",
4+
"require": {
5+
"php": "~5.6.5|7.0.2|7.0.4|~7.0.6"
6+
},
7+
"type": "magento2-module",
8+
"version": "100.0.1",
9+
"license": [
10+
"OSL-3.0",
11+
"AFL-3.0"
12+
],
13+
"autoload": {
14+
"files": [
15+
"registration.php"
16+
],
17+
"psr-4": {
18+
"SplashLab\\CorsRequests\\": ""
19+
}
20+
}
21+
}

etc/acl.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0"?>
2+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
4+
<acl>
5+
<resources>
6+
<resource id="Magento_Backend::admin">
7+
<resource id="Magento_Backend::stores">
8+
<resource id="Magento_Backend::stores_settings">
9+
<resource id="Magento_Config::config">
10+
<resource id="SplashLab_CorsRequests::config" title="CORS Request Configuration" sortOrder="50"/>
11+
</resource>
12+
</resource>
13+
</resource>
14+
</resource>
15+
</resources>
16+
</acl>
17+
</config>

0 commit comments

Comments
 (0)