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 ??

Was it helpful?

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

Check contact module post action how it's use

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...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top