yii2

Why is DELETE method not allowed in simple API controller


The basics work perfectly fine:

But when I attempt to use DELETE delete (/api/v1/pools/1), I get the following message:

Method Not Allowed

The requested method DELETE is not allowed for the URL /api/v1/pools/1.

I even defined checkAccess() as an empty method, but nothing seems to help.

Setup

Controller:

class PoolController extends \yii\rest\ActiveController
{
    public $modelClass = 'api\models\Pool';

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        // authenticate by using an access token passed in the username authentication header
        $behaviors['authenticator'] = [
            'class' => HttpBasicAuth::className(),
        ];
        return $behaviors;
    }
}

Config:

....
'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    //'enableStrictParsing' => true,
    'rules' => [
    [
        'class' => 'yii\rest\UrlRule', 
        'controller' => ['v1/pool'],
    ],
]
....

Requests & Responses

cURL DELETE request

curl -X DELETE \
  https://###/api/v1/pools/1 \
  -H 'Authorization: Basic dHBDMEUxNWVscl8tNlF6OFVYSGV5V0NydVBwdEp5elM6' \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache'

cURL repsponse

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method DELETE is not allowed for the URL         
/api/v1/pools/1.</p>
</body></html>

wget DELETE request

wget --method DELETE 
  --header 'Content-Type: application/json'   
  --header 'Authorization: Basic dHBDMEUxNWVscl8tNlF6OFVYSGV5V0NydVBwdEp5elM6'   
  --header 'cache-control: no-cache'
  --output-document   - https://###/api/v1/pools/1

wget DELETE reponse

HTTP request sent, awaiting response... 405 Method Not Allowed
2019-02-04 10:25:54 ERROR 405: Method Not Allowed.

For clarity, below the working request/response of another action (view) in the same controller is shown:

cURL GET request

curl -X GET \
  https://###/api/v1/pools/1 \
  -H 'Authorization: Basic dHBDMEUxNWVscl8tNlF6OFVYSGV5V0NydVBwdEp5elM6' \
  -H 'cache-control: no-cache'

cURL GET response

{"success":true,"data":{
    "id":1,
    "user_id":1,
    "name":"pool",
    ....
    "created_at":"2019-01-31 20:00:00"
}}

After further fiddling, I found out it will always return this message, even if I intentionally cause an internal error in the controller or the api main config. The working actions do indicate an internal error occurred. The request does not even show up in the debugger, only GET, POST and HEAD get that far.


Solution

  • After a lot of wasted time I discovered the requests did not even show up in the api debugger (/api/debug/default/view) and a grep in the repo for the message returned nothing. Only then did I begin to expect the server.

    The server is running Apache/2.4.35 (Unix) and in /etc/httpd/conf/httpd/extra/httpd-directories.conf there is a rule which blocks all but GET, HEAD and POST requests. I added PUT, PATCH, DELETE and OPTIONS.

    <Directory /home>
        AllowOverride All
        Options -MultiViews -Indexes +FollowSymLinks +IncludesNoExec +Includes
        AllowMethods GET HEAD POST PUT PATCH DELETE OPTIONS
    </Directory>
    

    Finally got it to work.