Magento 2 frontend route only allow POST method
-
07-03-2021 - |
Question
I'm using magento 2.2.5 and created a frontend route like this:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="spin" frontName="spin">
<module name="Neverending_Story" />
</route>
</router>
</config>
How can i allow only POST method request that can access this route ??
Solution
Magento request object has a function
$this->getRequest()->getMethod()
which provide the request method name on request object. So using this getMethod()
,you can prevent your route from all other request accept POST..
Create an observer on event
controller_action_predispatch_spin
And on that observer if you will found that the request method $observer->getEvent()->getRequest()->getMethod()
,then dis-allow the all pages of this routes <route id="spin" frontName="spin">
Call observer from events.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="controller_action_predispatch_spin">
<observer instance="StackExchange\Magento\Observer\Frontend\CheckAndPrevent"
name="prevent_all_method"/>
</event>
</config>
Observer code:
<?php
namespace StackExchange\Magento\Observer\Frontend;
class CheckAndPrevent implements \Magento\Framework\Event\ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
//$eventParameters = ['controller_action' => $this, 'request' => $request];
$request = $observer->getEvent()->getRequest();
$requestMethod = strtolower($request->getMethod());
if($requestMethod !== 'put'){
// echo $requestMethod;
// Throw an exception for prevent the accesss
throw new \Exception("Cannot access.");
}
}
}
OTHER TIPS
If you use M 2.3 then easily use that. You controller should implements the following interface:
Magento\Framework\App\Action\HttpPostActionInterface
If you are to use this route for an API like endpoint, I would suggest using webapi.xml configuration options instead. Register the route as a REST API endpoint.
You can do it like below:
webapi.xml
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route method="POST" url="/V1/spin">
<service class="YourVendor\YourModule\Controller\Index\Index" method="execute"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
Then your POST Endpoint: yourdomain.com/rest/V1/spin
This might not be the appropriate solution but I think this will do the work.
In Magento < 2.3 versions, I don't think there is a way to set this up in the route definition level. As Sohel explained in his answer, it is possible to ensure this in Magento >= 2.3 in the controller level.
However, you can make sure whether the method is POST or not by the request object. You can check this in the execute()
method as shown below:
public function execute()
{
$isPostRequest = !empty($this->getRequest()->getPostValue());
if (!$isPostRequest) {
// Not a POST request; logic to show some error
}
// Do relevant stuff here...
}