URLManager passing wrong verb over SSL

I’ve been using Yii for a couple of years now for both a website and a set of web services that I use to power an iOS app. Recently the need has come up to add the ability to access the web services via SSL. For the most part it works as expected but I’m seeing some strange behaviour where the wrong verb is being interpreted in some of the rules.

Here are my rules:

                            array('service/create', 'pattern'=>'service/<model:\w+>', 'verb'=>'POST'),


                            array('service/list', 'pattern'=>'service/<model:\w+>', 'verb'=>'GET'),


                            array('service/view', 'pattern'=>'service/<model:\w+>/<id:.+>', 'verb'=>'GET'),


                            array('service/update', 'pattern'=>'service/<model:\w+>/<id:\d+>', 'verb'=>'PUT'),


                            array('service/delete', 'pattern'=>'service/<model:\w+>/<id:\d+>/<sub_id:\d+>', 'verb'=>'DELETE'),


                            array('service/delete', 'pattern'=>'service/<model:\w+>/<id:\d+>', 'verb'=>'DELETE'),

These all work great to direct to the correct actions for the RESTful api over http but over SSL POST requests are being sent to the list service. PUT requests also troublesome. Has anybody else had any experience with this?

This wiki helped me to manage ssl.

Yes I used the same one to get it set up and it works as far as redirecting the appropriate URLs. The issue is that once I’ve been redirected the ‘verb’ that comes through that the URL manager uses to identify which action to use for a request seems to be getting mixed up. POST requests are being sent to the list action

I’m not sure if this is helpful or not but in the parseUrl method of the URLManager class if I log the requestType

error_log($request->requestType);

It shows "GET" for all PUT requests.

I am not competent enough to comment, but in Yii2 also, after an internal redirect, I got the POST in the request as GET and the verbfilter was not not accepting.

In this case, there is a redirect in the UrlManager.php as written in the wiki.




    public function parseUrl($request)

    {

        $route = parent::parseUrl($request);


        // Perform a 301 redirection if the current protocol 

        // does not match the expected protocol

        $secureRoute = $this->isSecureRoute($route);

        $sslRequest = $request->isSecureConnection;

        if ($secureRoute !== $sslRequest) {

            $hostInfo = $secureRoute ? $this->secureHostInfo : $this->hostInfo;

            if ((strpos($hostInfo, 'https') === 0) xor $sslRequest) {

                $request->redirect($hostInfo . $request->url, true, 301);

            }

        }

        return $route;

    }



As the first line says $route = parent::parseUrl($request);, the verb is taken care in the CUrlManager::parseUrl(). I think you may have to do something on the UrlManager class or do some other hack. I am not able to find a clear solution.

If what I wrote about the internal redirection is really the problem, then there is a solution, if you are able to change the http:// to https:// at the webserver level, and avoid the use of UrlManager, then it may solve the problem

Only wild thinking, not sure.

Thanks for the suggestion I really appreciate it. When poking through my apache logs I noticed that PUT requests via SSL are getting 301 redirected to the non SSL version. I’ve reached out to my hosting provider to see if they can provide me any info about why this would be happening. That might explain what is going on.

Just wanted to wrap this up. Turns out it appears to have been a problem with mod_security that was causing all the fuss. Once the PUT security rules were changed it all seems to work fine. Thanks for the help along the way!