Craft 3.1.18
I have a simple controller VeteransController
made using the updated Business Logic module. The purpose of this controller is to create a very simple endpoint for an external Vue application to send requests to and receive an array of veterans
entries.
When I test this controller using a "local" version of the same Vue component it functions perfectly. The response includes an array of entries just as expected.
Error from console
But when I send the request from my external Vue app I get a 404 error:
Access to XMLHttpRequest at 'https://myproject.test/actions/business-logic/veterans/index' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
This seems to suggest that the action isn't sending the correct status code with the response or doesn't know how to correctly respond to the preflight OPTIONS. But the logs from storage/logs
seem to tell a different story.
Error from storage/logs/web-404s.log:
[yii\web\Application::handleRequest] Route requested: 'templates/render'
[yii\base\Controller::runAction] Route to run: templates/render
[yii\base\InlineAction::runWithParams] Running action: craft\controllers\TemplatesController::actionRender()
[yii\web\HttpException:404] yii\web\NotFoundHttpException: Template not found: actions/business-logic/veterans/index in /Users/steven/Code/destination-small-town/vendor/craftcms/cms/src/controllers/TemplatesController.php:70
This is my first time getting this deep into extending Craft like this, so I could be missing small steps or reading things incorrectly. But those errors make it sound like Craft is trying to read the URL from my Vue's axios post call (https://mycraftproject.test/actions/business-logic/veterans/index
) and render a template that doesn't exist rather than navigate to the correct controller action.
But when I place a breakpoint in PhpStorm on my VeteransController
class definition and go through the steps I can tell that the request is indeed making its way to the controller. But when it goes along down the steps to the runAction()
method in yii\base\Module
it returns a null
value.
So I can establish that my request is reaching the controller. But it is not reaching my index action. I'm at a loss as to how I should proceed or troubleshoot further.
Here is my controller in case I am missing something simple here:
class VeteransController extends Controller
{
public $allowAnonymous = true;
public $enableCsrfValidation = false;
/**
* Add CORS Filter from Yii2
*/
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['POST', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
]
]
];
}
/**
* @throws BadRequestHttpException
*/
public function actionIndex ()
{
$this->requirePostRequest();
$this->requireAcceptsJson();
$request = Craft::$app->getRequest();
$countyId = $request->getBodyParam('countyId');
$veterans = Entry::find()
->section('veterans')
->relatedTo($countyId)
->limit(10)
->all();
return $this->asJson([
'success' => true,
'veterans' => $veterans
]);
}
}
Request Headers:
The request headers are set by my Axios instance in my external Vue app.
Axios.defaults.headers.common['Accept'] = 'application/json';
Axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
While not set as an Axios default the request does include Access-Control-Request-Method
with a value of POST
.
In Chrome's dev tools, under the Network -> Headers tabs and below the first section which is called "General" it shows the following:
Request URL: https://destinationsmalltown.test/actions/business-logic/veterans/index
Request Method: OPTIONS
Status Code: 404 Not Found
Remote Address: [::1]:443
Referrer Policy: no-referrer-when-downgrade
Thank you!
Access-Control-Request-Method