craftcms/element-api

http OPTIONS request returns full result with data in body

judos opened this issue · 3 comments

judos commented

In our application we have a jwt header which gets sent to the cms. Naturally thus the browser does a preflight request before sending the actual request and it just realized that element-api returns already a full response with data in the preflight request "OPTIONS /endpoint" as well as then in the "GET /endpoint".
Shouldn't element api only serve GET requests?
Is there a way to configure this?

The element-api.php looks like this:

return [
	'defaults' => [
		'elementType' => Entry::class,
		'resourceKey' => 'elements',
		'pretty' => Craft::$app->getConfig()->general->devMode,
		'paginate' => false,
		'cache' => ApiHelper::enableCache(300),
	],
	'endpoints' => [
		'pages/<slug:{slug}>' => function($slug) {
			return [
				'one' => true,
				'criteria' => [
					'section' => 'pages',
					'slug' => $slug,
				],
				'transformer' => new PageTransformer()
			];
		},
	}
]

The header that is added in angular is just this:

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.jwt) {
      req = req.clone({
        headers: req.headers.set('Authorization', 'Bearer ' + this.jwt)
      });
    }
    return next.handle(req);
  }

I didn't find anything in the documentation.

Thanks for your help!

judos commented

Found a small workaround: In element-api instead of returning criterias to form a query you can return a NullResource which is then directly serialized as empty brackets. So I solved as follows:

'pages'` => function() {
	if ($response = ApiHelper::assumeGet()) {
		return $response;
	}
	return [
		'criteria' => [
			'section' => 'pages',
		],
		'transformer' => new PageTransformer()
	];
},

And my ApiHelper:

class ApiHelper {

	/**
	 * @throws BadRequestHttpException
	 */
	public static function assumeGet() {
		$request = Craft::$app->getRequest();
		if ($request->getIsOptions()) {
			return new NullResource();
		}
		if (!Craft::$app->getRequest()->getIsGet()) {
			throw new BadRequestHttpException('Get request required');
		}
	}
}

👍

Just released Element API 2.8.0, which now checks if the endpoint request is an OPTIONS request, and returns an empty response in that case.