In my project I use GraphQL only and need no to configure REST operations. How do I disable REST and leave GraphQL support only?
That makes me sad. :cry:
But on a more serious note, it's not currently possible, because GraphQL uses the generic application/json MIME type.
You can register only the GraphQL route, instead of all API Platform routes. Replace the content of config/routes/api_platform.yml by:
api_platform_graphql:
resource: '@ApiPlatformBundle/Resources/config/routing/graphql.xml'
It should do the trick.
Ideally, we should add a flag to disable REST, and not register the kernel listeners in this case. In the meantime the previous solution should be good enough.
@dunglas Your suggestion with the routing modifications sadly doesn't work.
The main issue is that GraphQL still uses the routes for IRI generation, not sure if that can easily be solved by still registering the routes, but not attaching the listeners?
@lukasluecke You could try manually overriding some of the built-in event listeners with the same service IDs. But we need to identify which listeners are used by GraphQL, and which are not.
Hmm... Actually I think an easier way would be to just do:
<?php
// api/src/Entity/Book.php
use ApiPlatform\Core\Annotation\ApiResource;
/**
* @ApiResource(
* graphql={
* ...
* },
* collectionOperations={
* },
* itemOperations={
* },
* )
*/
class Book
{
EDIT: Sorry, this wouldn't really work, as certain operations are still compulsory for IRI generation, as @lukasluecke has pointed out.
Related to #2954 (since this should be the only thing that's currently still required from the REST operations, if you want GraphQL to work)
@dunglas Was this not already resolved? (#3079 and api-platform/docs#886)
Maybe we should close #2954 to prevent confusion.
Good catch! To entirely fix this one we should add a config option to easily disable everything that can be disabled from the REST subsystem.
@dunglas I'll try to get something in for #2946 soonish, which should also make it possible to globally define these operation settings (and then have a doc entry with the exact settings to use) - do you think that would be enough?
Could also be related to https://github.com/api-platform/core/issues/3099 right?
@dunglas Ah yes, must've missed that one. I'll create a PR for it this / next week, if no one beats me to it 馃檪
@dunglas Was this not already resolved? (#3079 and api-platform/docs#886)
Maybe we should close #2954 to prevent confusion.
Thanks
I added to all my (graphql) entities
use ApiPlatform\Core\Action\NotFoundAction;
/**
* @ApiResource(
* graphql={...},
* collectionOperations={},
* itemOperations={ "get"={ "controller"=NotFoundAction::class, "read"=false, "output"=false } }
* )
*/
And it did the trick. Even when I have access to an object the REST GET /item/{id} throws 404.
I am migrating to graphql-only API and I completely don't need REST. I disable it to get rid of maintaining it (testing, permissions checking).
Indeed the safe way to diable item operations is to do:
/**
* @ApiResource(
* itemOperations={
* "get"={
* "method"="GET",
* "controller"=NotFoundAction::class,
* "read"=false,
* "output"=false,
* },
* },
* )
*/
As documented at the end of this section
This is my little "hack" for disabling any requests other than those towards GraphQL endpoints. Not sure if it's the 100% right way to do so but here is the snippet.
<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class KernelRequestSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 255],
];
}
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
$path = $request->getPathInfo();
$method = $request->getMethod();
$allowedPaths = 'dev' === $_ENV['APP_ENV'] ? ["/graphql", "/graphql_playground"] : ["/graphql"];
$response = new Response('Page not found.', Response::HTTP_NOT_FOUND);
if (!in_array($path, $allowedPaths)) {
$event->setResponse($response);
}
if (("/graphql" === $path and "POST" !== $method) or ("/graphql_playground" === $path and "GET" !== $method)) {
$event->setResponse($response);
}
}
}
It's all fine and dandy, guys, but the routes are still generated. Is there a way to disable route generation as well? 20K urls(in our case) are a bit excessive for us.
There's no way to disable that, you could eventually override the ApiLoader file...
There's no way to disable that, you could eventually override the ApiLoader file...
Any idea how to leave only the graphql route exposed? When editing ApiLoader I am able to either disable all routes or none.
You can register the GraphQL route "manually" (in config/route.yaml for instance).
IMHO we should provide a configuration option to disable REST entirely. Another approach could be to use the new defaults option (available in master) to disable every operations except GET ones.
A quick update - overriding the ApiLoader file does the job perfectly. I got rid of about 40K completely useless REST urls. Just don't forget to revisit ApiLoader whenever you do 'composer upgrade'.
@plamenh Have you tried this solution?
In my project bin/console debug:router shows only those few GET routes, only one for each entity.
@oleg-brizy I tried that one, but it does not work for me. I need the routes gone, I don't need the routes to point to a 404 page returned by a controller. My cache warm-up with 40K routes was painfully slow and timing out, you can imagine what this means in dev environments (waiting 30+ seconds for timeout on each and every small change in the codebase).
There's no way to disable that, you could eventually override the ApiLoader file...
Any idea how to leave only the graphql route exposed? When editing ApiLoader I am able to either disable all routes or none.
Can we have an example on HOW TO override the ApiLoader file?
There's no way to disable that, you could eventually override the ApiLoader file...
Any idea how to leave only the graphql route exposed? When editing ApiLoader I am able to either disable all routes or none.
Can we have an example on HOW TO override the ApiLoader file?
I would also be interested in a way to properly override. We are currently overriding code in place - vendor/api-platform/core/src/Bridge/Symfony/Routing/ApiLoader.php
Most helpful comment
Ideally, we should add a flag to disable REST, and not register the kernel listeners in this case. In the meantime the previous solution should be good enough.