Main API entrypoints (Symfony)

You want to add a new entrypoint to the main-api? Here’s some ropes!

In what controller?

Controllers are groupes in bundles in Symfony. Bundles were primarily used to split the database (as one Bundle controls one database). Now the bundles responsibilities are as follows:

  • APIBundle: contains the endpoints for external client users or external systems.
  • ConsoleBundle: contains code for the Symfony Console command (doctrine updates of the schemes, Ceneau updates of basic data, etc.)
  • DailyBundle: contains the endpoints for the legacy Perl backoffice scripts
  • MeasureBundle: only contains definition of the Measure DB schema
  • RESTBundle: contains the endpoints for the newer NestJS backoffice webservices
  • SVBundle: contains the endpoints for the front application (V1 and Angular apps); within it, the APIController (and all controllers in SVBundle/Controller/API) serves dedicated data for the Angular apps.
  • WIPBundle: used to replace the routes in WIP screens during V1 deployments

Securing the access

Symfony secures its access via the app/config/security.yml. Within that file, the routes are secured by role or by IP (the routes themselves are defined via the app/config/routing.yml).

Two main routes can be used when adding an entrypoint:

  • /app/data is used to serve data to Angular apps: it requires a Symfony authentication and leads to the SVBundle.
  • /intern/rest requires no authentication: it’s reserved to communication between automatic processes (legacy Perl, NestJS webservices) and will be filtered by IP for security. These routes lead to the RESTBundle.

Within your code file, you can them add a security layer with PHP annotation just above your method definition via:

@Secure(roles=”ROLE_ADMIN”)

use JMS\SecurityExtraBundle\Annotation\Secure;
/**
 * @Secure(roles="ROLE_ADMIN")
 */
public function mySecuredMethod() { ...

This will require the user to be authenticated via Symfony with the ROLE_ADMIN role.

Returning data to a Nestjs service

NestJS services require static data in the simplest format, therefore a REST API is indicated. Use the FOSRestBundle to define the HTTP Verb and the route:

use FOS\RestBundle\Controller\Annotations as Rest;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

  /**
   * @Rest\Put("/save")
   * @ParamConverter("dtoIn", converter="fos_rest.request_body")
   */
  public function saveMeasurements(MeasurementSaveBulkInputDto $dtoIn)

Sensio ParamConverter allows use to automatically decypher the input DTO in a class you defined. It will generate a 400 if the DTO is invalid. Validation within the target class uses JMS serialization (check examples in code).

You can now return data with 2 ways:

  • create a output DTO class with JMS serialization annotations within it; then create an instance of this class in your controller and simply return it to return its JSON version to the consumer service (check MeasurementController::getBulkMeasurements)
  • form your own simple data structure (with array() and keys in it) in your Controller and simply return it: it will be turned into a JSON object (check ExchangeController:: getEntitiesInformation)

Returning data to an Angular application

Angular apps typically use the Store as a reactive sole source of truth. The reactive structure of the entities in the Store allows for great reactivity within Angular templates. If you intend to store your data in the Store, then your entrypoint can return a dedicated structure, proper to feed the Store.

Define your route with Symfony @Route annotation:

  /**
   * @Route("/my/route/{entityId}", defaults={"_format"="json"}, name="_process_entity")
   */
  public function processEntity($entityId)

Then, check the following helping class/methods:

  • EntitiesMap: create a new EntitiesMap and add the entities you want to return via the addEntity/addEntities methods.
  • ApiUtilityService::getJson: from an EntitiesMap, generate a JSON object using the customed serialization, coded by each entity’s svSerialize/svSerializeDates/ createAssociations methods.
  • ApiUtilityService::renderResponse: offers a json template to embed different things, including json entitys for the Store.