Closed Lokilein closed 10 months ago
I have the same problem:
XHRPOSThttp://localhost/api-tools/api/module/myapp/rpc [HTTP/1.1 422 Unprocessable Entity 10175ms]
validation_messages Object { controller_class: […], accept_whitelist: […], content_type_whitelist: […], … } controller_class [ "The Controller Class must be a valid, fully qualified, PHP class name" ] 0 "The Controller Class must be a valid, fully qualified, PHP class name" accept_whitelist [ "The Accept Whitelist must be an array of valid media type expressions" ] 0 "The Accept Whitelist must be an array of valid media type expressions" content_type_whitelist [ "The Content-Type Whitelist must be an array of valid media type expressions" ] 0 "The Content-Type Whitelist must be an array of valid media type expressions" http_methods [ "The HTTP Methods must be an array of valid HTTP method names" ] 0 "The HTTP Methods must be an array of valid HTTP method names" type "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" title "Unprocessable Entity" status 422 detail "Failed Validation"
vendor\laminas-api-tools\api-tools-admin\config\module.config.php
Following @Lokilein guidelines, we should edit the lines
'ZF\Apigility\Admin\InputFilter\RpcService\PATCH' => RpcPatchInputFilter::class, 'ZF\Apigility\Admin\InputFilter\RpcService\POST' =>
RpcPatchInputFilter::class,RpcPostInputFilter::class, 'ZF\Apigility\Admin\InputFilter\Version' => VersionInputFilter::class,// Legacy Zend Framework aliases v2 'ZF\Apigility\Admin\InputFilter\RpcService\PatchInputFilter' => RpcPatchInputFilter::class, 'ZF\Apigility\Admin\InputFilter\RpcService\PostInputFilter' =>
RpcPatchInputFilter::class,RpcPostInputFilter::class,
~~### I edited the file: PatchInputFilter.php vendor\laminas-api-tools\api-tools-admin\src\InputFilter\RpcService\PatchInputFilter.php~~
~~And commented out the lines. It's not ideal, but it created the service. We need to investigate here.~~
class PatchInputFilter extends PostInputFilter
{
public function init()
{
parent::init();
// $this->add([
// 'name' => 'controller_class',
// 'required' => true,
// 'error_message' => 'The Controller Class must be a valid, fully qualified, PHP class name',
// ]);
// $this->add([
// 'name' => 'accept_whitelist',
// 'validators' => [
// ['name' => MediaTypeArrayValidator::class],
// ],
// 'error_message' => 'The Accept Whitelist must be an array of valid media type expressions',
// ]);
// $this->add([
// 'name' => 'content_type_whitelist',
// 'validators' => [
// ['name' => MediaTypeArrayValidator::class],
// ],
// 'error_message' => 'The Content-Type Whitelist must be an array of valid media type expressions',
// ]);
// $this->add([
// 'name' => 'selector',
// 'required' => false,
// 'allow_empty' => true,
// 'error_message' => 'The Content Negotiation Selector must be a valid,'
// . ' defined api-tools-content-negotiation selector name',
// ]);
// $this->add([
// 'name' => 'http_methods',
// 'validators' => [
// ['name' => HttpMethodArrayValidator::class],
// ],
// 'error_message' => 'The HTTP Methods must be an array of valid HTTP method names',
// ]);
}
}
Instead of deactivating the filter, I would really recommand to adapt the wrong filter config. As you can see from my post, the PostFilter is used when asked for the PatchFilter. This is most likely a typo by CopyPaste. Replace RPCPostInputFilter with RPCPatchInputFilter at the two places and everything work as it should.
Perfect! I didn't read your post carefully.
I edited the file: module.config.php vendor\laminas-api-tools\api-tools-admin\config\module.config.php
Here is the file already corrected module.config.zip
Hi there,
I'm new to laminas and trying to learn the basics trough the documentation with the skeleton. Stumbled upon this issue when creating my first RPC-Service in Laminas API tools.
After editing vendor\laminas-api-tools\api-tools-admin\config\module.config.php
as said by @Zimhoo I can create my first RPC-Service trough the web client and continue the getting-started guide.
I have too little knowledg about Laminas yet, but why would we not just submit the edited module.config.php
submitted above as an PR on this package? As this edit will fix this issue and seems non-breaking.
Hoping that someone with some more knowledge about Laminas can answer this 😄 .
For me as Laminas-API-tools first time learner this issue was relative annoying...
When diving into an new framework and going trough an "getting started" guide, you want to see things work as expected and not searching trough vendor/
code to fix framework-related bugs.
Update: Seems like there is an PR ready; https://github.com/laminas-api-tools/api-tools-admin/pull/88 Hoping this will get merged/released.
@robertvanlienden We are using the API tools since a year now and I cannot recommand it. We are planning to remove them again as they do more harm than good. Just to let you know some of our expierences if you want to consider it.
However, we find out that the REST is not the best option for us for most cases, so we will go to RPC instead, but in my opinion we might just use regular Controller for this and keep the API tools out of this.
@Lokilein I think it would be better to write down a general laminas review in the appropriate channels, and not in a particular issue that has nothing to do with points you are raising. Nevertheless, as the discussion is started, I'd like to reply to some of those points:
Generally speaking, the Laminas API Tools need some getting-used-to, but on the up-side you get a very powerful, customizable & stable framework, guiding you in a variety of best-practices. Sure, the admin package could need some work. At lot of features are not even editable in the Admin UI. But I've setup recently multiple new installations with our team in no time and the Admin package (& UI) worked as it should. What can make reading the documentation difficult, is, that Laminas API Tools are composed of a lot of smaller packages, and the documentation equally is split up in those packages.
We were not able to configure the returns like we wished
I think it's a misconception to link the input (to create a resource) 1-to-1 with the output. And this is not defined by the HAL component but rather by your Hydrators. The HAL component is just a renderer. If you want a fine-grained control on your resource's output, simply use a the ArraySerializableHydrator
. Removing then the password from your resource becomes the easiest thing in the world. If, however, you use a ClassMethodsHydrator
in combination with a getPassword()
in your entity, then, sure, you end up having the password in your output.
We had a extremely hard time to stop it sending Exceptions to the frontend directly
...
One time, we didn't typed the getter/setter in the model correctly to nullable, but all you get is a generic error that the answer cannot be generated
I see multiple problems here:
1) Invalid requests should NEVER touch your database. If that happens, you input has probably not been filtered and validated correctly (which is perfectly doable with laminas validators (or even your ownn custom validators).
2) Verify you encapsulation : Create your own specific exception classes for the different components of your application. Each component should catch the exceptions of the invoked sub-components and handle them appropriately. You shouldn't expect the framework to handle low-level exceptions from the database out-of-the-box. As for not letting through exceptions to the API customer, you have always a catch(\Throwable $e)
as a last resort if you didn't catch the exception before.
3) Have you written automated tests for your application? Are you doing TDD or even better BDD? What about Static code analysis? Using tools like Behat, PHPUnit, etc. lets you develop a lot faster with much more reliable code. Especially Static Analysis with PHPStan is a real no-brainer and does a lot of the debugging work for you.
Best regards, Pascal
@ppaulis I didn't want to critize the Laminas Framework at whole, but my experience with the API tools, when I was new to it a year ago, wasn't that good and I just wanted to feedback that to Robert, as he said he is new to it. Also, the thing, that this bug is still not fixed, as it is also essential to new developers to get in touch with these tools is a message, that can't be unseen.
Maybe there are good solution, your experience is a completly other, which might also be good to know. I also have to say that our API Tools were setup by a colleague in the "ivory tower", which are gone now and which made it hard for uns to understand, also, some concepts were implemented though they did not suit our solution. We tried to get it right, but then there was the documentation which was missing for us to find a workaround for our problems. I've read the documentation of the main API Tools several times up and down and haven't found a solution there - maybe, yes, I should have look for further documentation in sub-elements.
However, I agree that my experience might be a "how not to do it" expierence and based on missing documentation and/or knowledge, but, again, we haven't had so much problems with any other part of Laminas yet, and I am usually not that bad to work through stuff.
To your recommandations:
I can/will delete the comment from above, as it might not belong here, agree. Just wanted to explain my post to bring it in the right context.
Hello, this issue is still present. PHP 8.2.10.
As others suggested, in ./vendor/laminas-api-tools/api-tools-admin/config/module.config.php
I can see wrong aliases for POST.
'ZF\Apigility\Admin\InputFilter\RpcService\POST' => RpcPatchInputFilter::class,
...
'ZF\Apigility\Admin\InputFilter\RpcService\PostInputFilter' => RpcPatchInputFilter::class,
RpcPatchInputFilter is used instead of RestPostInputFilter.
When I make change to RestPostInputFilter::class it works.
'ZF\Apigility\Admin\InputFilter\RpcService\POST' => RestPostInputFilter::class,
...
'ZF\Apigility\Admin\InputFilter\RpcService\PostInputFilter' => RestPostInputFilter::class,
Cleaner solution is to add new file in config/autoload/local.php
and add correct aliases there:
<?php
use Laminas\ApiTools\Admin\InputFilter\RestService\PostInputFilter as RestPostInputFilter;
return [
'input_filters' => [
'aliases' => [
'ZF\Apigility\Admin\InputFilter\RpcService\POST' => RestPostInputFilter::class,
'ZF\Apigility\Admin\InputFilter\RpcService\PostInputFilter' => RestPostInputFilter::class,
],
],
];
@tasmaniski Thanks, that worked with latest version 22-Nov-2023
Bug Report
With v1.10.3, it is not possible to create a new service, as the wrong filter is taken for the POST action;
Summary
Current behavior
You cannot add a RPC-Service with the "New Service" Button. You receive an 422 error instead:
How to reproduce
Expected behavior