4

I have try to create a Custom REST POST plugin in my Drupal 8.3.2 for get an external JSON and then create an article from that.

I have follow that guide: How to create Custom Rest Resources for POST methods in Drupal 8 And this is my code:

<?php

namespace Drupal\import_json_test\Plugin\rest\resource;

use Drupal\Core\Session\AccountProxyInterface;
use Drupal\node\Entity\Node;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Psr\Log\LoggerInterface;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "tio_rest_json_source",
 *   label = @Translation("Tio rest json source"),
 *   serialization_class = "Drupal\node\Entity\Node",
 *   uri_paths = {
 *     "canonical" = "/api/custom/",
 *     "https://www.drupal.org/link-relations/create" = "/api/custom"
 *   }
 * )
 */
class TioRestJsonSource extends ResourceBase {

  /**
  * A current user instance.
  *
  * @var \Drupal\Core\Session\AccountProxyInterface
  */
  protected $currentUser;

  /**
  * Constructs a new TioRestJsonSource object.
  *
  * @param array $configuration
  *   A configuration array containing information about the plugin 
  instance.
  * @param string $plugin_id
  *   The plugin_id for the plugin instance.
  * @param mixed $plugin_definition
  *   The plugin implementation definition.
  * @param array $serializer_formats
  *   The available serialization formats.
  * @param \Psr\Log\LoggerInterface $logger
  *   A logger instance.
  * @param \Drupal\Core\Session\AccountProxyInterface $current_user
  *   A current user instance.
  */
  public function __construct(
  array $configuration,
  $plugin_id,
  $plugin_definition,
  array $serializer_formats,
  LoggerInterface $logger,
   AccountProxyInterface $current_user) {
   parent::__construct($configuration, $plugin_id, 
   $plugin_definition, $serializer_formats, $logger);

   $this->currentUser = $current_user;
 }

 /**
  * {@inheritdoc}
  */
 public static function create(ContainerInterface $container, array 
 $configuration, $plugin_id, $plugin_definition) {
   return new static(
     $configuration,
     $plugin_id,
     $plugin_definition,
     $container->getParameter('serializer.formats'),
     $container->get('logger.factory')->get('import_json_test'),
     $container->get('current_user')
   );
 }

 /**
  * Responds to POST requests.
  *
  * Returns a list of bundles for specified entity.
  *
  * @param $data
  * 
  * @param $node_type
  *
  * @return \Drupal\rest\ResourceResponse
  *
  * @throws \Symfony\Component\HttpKernel\Exception\HttpException
  *   Throws exception expected.
  */
  public function post($node_type, $data) {

   // You must to implement the logic of your REST Resource here.
   // Use current user after pass authentication to validate access.
   if (!$this->currentUser->hasPermission('access content')) {
     throw new AccessDeniedHttpException();
   }

   $node = Node::create(
       array(
           'type' => $node_type,
           'title' => $data->title->value,
           'body' => [
               'summary' => '',
               'value' => $data->body->value,
               'format' => 'full_html',
               ],
           )
   );

   $node->save();
   return new ResourceResponse($node);

 }

}

Now if i try to test this without passing a payload and modifing the return value in this way:

return new ResourceResponse(array('test'=>'OK'));

It's working!

But if i send a custom payload like this using my custom code above:

 {
 "title": [{
   "value": "Test Article custom rest"
 }],
 "type": [{
   "target_id": "article"
 }],
 "body": [{"value": "article test custom"}]
}

I recieve a 400 Error with: Symfony\Component\HttpKernel\Exception\BadRequestHttpException: The type link relation must be specified. in Drupal\rest\RequestHandler->handle() (line 103 of core/modules/rest/src/RequestHandler.php).

What's going Wrong?

Thx.

Mettek
  • 409
  • 6
  • 13

1 Answers1

3

I have find a solution:

I have removed the annotation:

*   serialization_class = "Drupal\node\Entity\Node",

Then i take care just for data in my post function:

  /**
  * Responds to POST requests.
  *
  * Returns a list of bundles for specified entity.
  *
  * @param $data
  *
  *
  * @return \Drupal\rest\ResourceResponse
  *
  * @throws \Symfony\Component\HttpKernel\Exception\HttpException
  *   Throws exception expected.
  */
 public function post($data) {

   // You must to implement the logic of your REST Resource here.
   // Use current user after pass authentication to validate access.
   if (!$this->currentUser->hasPermission('access content')) {
     throw new AccessDeniedHttpException();
   }


   return new ResourceResponse(var_dump($data));

The important thing is, when you use postman for example, is to add an header with Content-Type -> application/json: THe header configuration in postman

Instead of Content-Type -> application/hal+json

With this configuration i can post any type of JSON and then manage it as i prefer.

Bye!

Mettek
  • 409
  • 6
  • 13