How to make POST call using FOSRestBundle - rest

I am trying to setup a RESTFUL web service using FOSRestBunble, but I have some problem making POST calls, here's my setup:
app/config/routing.yml
rest:
type: rest
resource: "routing_rest.yml"
prefix: /api
app/config/routing_rest.yml
Rest_User:
type: rest
resource: "#AppBundle/Resources/config/routing_rest.yml"
AppBundle/Resources/config/routing_rest.yml
rest_application:
type: rest
resource: "AppBundle:Rest"
name_prefix: api_
AppBundle/Controller/RestController.php
class RestController extends FOSRestController
{
public function testrestAction(Request $request)
{
$r = [
'is' => 'TEST'
];
return $r;
}
public function getArticleAction()
{
$r = [
'is' => 'GET'
];
return $r;
}
public function postArticleAction()
{
$r = [
'is' => 'POST'
];
return $r;
}
}
I also made PUT and DELETE test methods. so when I do some test call
GET /api/testrest
{
"is": "TEST"
}
GET /api/article
{
"is": "GET"
}
POST /api/article
No route found for "POST /api/article": Method Not Allowed (Allow: GET, HEAD) (405 Method Not Allowed)
PUT and DELETE are also fine. Am I missing some configuration?
second problem: if I make a API folder inside Controller folder, I change the namespace for RestController to "namespace AppBundle\Controller\API;" and I update "AppBundle/Resources/config/routing_rest.yml" to
resource: "AppBundle:API:Rest"
then I got this message:
Can't locate "AppBundle:API:Rest" controller in /var/www/ws/app/config/routing_rest.yml (which is being imported from "/var/www/ws/app/config/routing.yml").
any help appreciated

1-option, run app/console debug:router (or bin/console debug:router if v > 2.8), to list generated routes;
2-option, add RouteResource annotation to class (eg. article), rename postArticleAction to postAction and check POST /api/articles is responding or not;
3-option, add article url explicitly with #POST annotation, eg. /** #Post("article") */

Related

Drupal 9 : Ajax process to display an entity form in a popup

I need help I am new in Drupal 9 Ajax development. I have developed a piece of code but it doesn't work.
To sumarise, I want to display an entity form in a popup. The popup is built dynamically with jQuery, I use Ajax to fill the popup and the form is built in an ajax command (the code is : \Drupal::service('entity.form_builder')->getForm($livraison, 'edit');)
The form is well displayed but I think I miss something in ajax developpement because when I submit the form, the entity is not saved. When I look at the javascript console log, I see 3 others command responses plus the command I have created in server side (modifLivraison).
result: Array(4) [ {…}, {…}, {…}, {…} ]
​0: Object { command: "settings", settings: {…}, merge: true }
1: Object { command: "insert", method: "prepend", selector: "head", … }
2: Object { command: "insert", method: "append", selector: "body", … }
3: Object { command: "modifLivraison", modif: "...
I think that the Entity form needs some javascript and that's why these 3 commands have been added.
I don't know if my ajax process is correct.
Here my code :
In the command class:
class ModifLivraisonCommand implements CommandInterface
{ protected livraisonId; ...
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render()
{
...
$entitytype_manager = \Drupal::service('entity_type.manager');
$storage = $entitytype_manager->getStorage('livraison');
$livraison = $storage->load($this->livraisonId);
...
$livraison_form = \Drupal::service('entity.form_builder')->getForm($livraison, 'edit');
$livraison_form['#cache']['max-age'] =0;
$output = \Drupal::service('renderer')->render($livraison_form);
return [
'command' => 'modifLivraison',
'modif' => $output
];
...
The controller :
public function modifLivraison($livraison) {
$response = new AjaxResponse();
$response->addCommand(new ModifLivraisonCommand($livraison));
return $response;
}
and the javascript in the client side :
create_popup('0,0,0,0')
...
jQuery.ajax('/livraisons/modif-livraison/' + livraison, {
success: function(result,textStatus, jqXHR) {
jQuery(".spinner").remove();
console.log(result);
var ajax;
Drupal.AjaxCommands.prototype.settings(ajax,result[0],200)
jQuery(result[1].selector)[result[1].method](result[1].data);
jQuery(result[2].selector)[result[2].method](result[2].data);
...
jQuery("#modif_livraison").append(result[3].modif);
...
}
})
I think the error is in the way of ajax calling of the url (jQuery.ajax('/livraisons/modif-livraison/' + livraison ...)
My problem is the entity is not saved when the form is submitted. What's wrong ?

Behat functional test stop Symfony HttpKernal redirects

I'm using Behat to test a REST API my team has developed. When a particular resource is created the API returns a 201 and a Location header in the response.
The API was developed using using Symfony5 and it's using the Symfony HttpKernel as the client:
$kernel->handle($request);
I would like to assert through my behat test that it returns a 201 and the headers contains the Location. However the client is automatically following the Location header and as such I can't verify that.
Is there a way to turn off following redirects using the existing kernel component? I've not been able to find a way to do this.
You can create your own context and check the Response
<?php declare(strict_types=1);
namespace App\Tests\Features\Context;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
final class HttpContext
{
private Kernel $kernel;
private Response $response;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
}
/**
* #When I request :method to :uri
*/
public function iRequest(string $method, string $uri): void
{
$this->request($method, $uri);
}
/**
* #Then the location header should be :location
*/
public function assertLocationHeader(string $location): void
{
// make your assertion
dd($this->response->headers->get('location'), $location);
}
private function request(string $method, string $uri): void
{
$request = Request::create($uri, $method, [], [], [], [], null);
$this->response = $this->kernel->handle($request);
$this->kernel->terminate($request, $this->response);
}
}

Kuzzle anonymous user to access to a plugin?

Hi i tried to give anonymous user to access to a plugin but it still does not work what you think i am doing wrong?
kuzzle-core-plugin-boilerplate/NewController:Object
actions:Object
getamount:true
should anonymous get any other privilege to access the plugin?
By default, the anonymous user is not restricted and can call every API method (core methods and also plugin methods).
For example, if you have a plugin named iot in the manifest and you declare the following controller:
this.controllers = {
sensors: {
register: request => /* ... */
}
}
Then you can call this custom API action with the following WebSocket payload:
{
"controller": "iot/sensors",
"action": "register",
"body": /* request body */
}
If you want to call this API method with the Http protocol then you have to declare a route:
this.routes = [
{ verb: 'POST', url: '/sensors', controller: 'sensors', action: 'register' }
]
Then you can call it with Curl for example: curl -X POST http://localhost:7512/_plugin/iot/sensors

Zend framework: how to pass creation options to services

When registering a service in module.config.php like
'service_manager' => [
'factories' => [
\Path\To\Your\Service\AService => \Path\To\Your\Service\Factory\AServiceFactory,
]
]
I can't pass in creation options when calling the service factory neither in ZF2 (when the factory implements MutableCreationOptionsInterface) nor in ZF3 (via $container->get(\Path\To\Your\Service\AService::class, $options).
Could anyone tell me how to pass the creation options to the services?
MutableOptions is currently only available on plugin manager instances; the service manager does not implement it. This is why you see the discrepancy.
Références : https://github.com/zendframework/zend-servicemanager/issues/7
Sample : https://samsonasik.wordpress.com/2014/08/14/zend-framework-2-using-creationoptions-in-pluginmanager/
COMPLEMENT
My solution is to add a method with a fluent pattern to the AService class :
class AService
{
public function __construct(...)
{
//your code, you can inject variables from $container by AServiceFactory
}
public function setOptions($options)
{
// your setting from $options
...
// fluent pattern
return $this;
}
}
To use your service :
$container->get(\Path\To\Your\Service\Aservice::class)->setOptions($options);

In Extjs5, erase() can't relate to destory api when the proxy type is rest

This is my viewController:
onRestDeleteClick: function(){
var ouType = Ext.create('MyApp.model.OuType',
{
id: 49,
ouTypeName: 'Lenlee',
entityName: 'Lenlee'
});
ouType.erase();
}
The model whose id is 49 exists in database.
This is the OuType model:
Ext.define('MyApp.model.OuType', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.field.Field'
],
fields: [
{
name:'id'
},
{
name: 'ouTypeName'
},
{
name: 'entityName'
}
],
proxy:{
type: 'rest',
api: {
read: 'role/read',
update: 'role/update',
create: 'role/create',
destory: 'role/destory'
}
}
});
This is my server class:
#RequestMapping("/role")
#Controller("sysRoleContro")
public class SysRoleController {
…………
…………
#RequestMapping(value="/destory/{id}")
public void destoryOuType(HttpServletRequest request,
HttpServletResponse response, #PathVariable("id") Long id){
log.info("destory");
ouTypeRepository.delete(id);
log.info("end");
}
………
……
}
Now when i click the delete button, the request url is: http://localhost:7080/MyApp.model.OuType/49 404 Not Found.
The expected url is http://localhost:7080/CSQMS/role/destory/49
How can i delete the model?
Rest proxy is special in that that it does not CRUD operations to urls, as you set in api, but to HTTP verbs: GET, POST, PUT, DELETE, etc. So api config is most likely ignored. Configure the proxy this way:
proxy:{
type:'rest',
url:'/CSQMS/role'
}
If your server expects that CRUD operation verb is part of the URL you probably need a different proxy or you need to implement buildUrl method.
I want to say i'm so careless, i should write 'destroy' instead of 'destory'. MY GOD.