Docs Italia beta

Documenti pubblici, digitali.

6.2.1. [NONBLOCK_PULL_REST] Not Blocking Pull REST

Quando il profilo viene implementato con tecnologia REST, DEVONO essere rispettate le seguenti regole:

  • La specifica dell’interfaccia dell’erogatore DEVE dichiarare tutti i codici di stato HTTP restituiti con relativo schema della risposta, oltre che ad eventuali header HTTP restituiti;
  • La specifica dell’interfaccia DEVE dichiarare gli schemi delle richieste insieme ad eventuali header HTTP richiesti;
  • Al passo (1), il fruitore DEVE utilizzare il verbo HTTP POST;
  • Al passo (2), l’erogatore DEVE fornire insieme all’acknowledgement della richiesta, un URL per interrogare lo stato di processamento utilizzando HTTP header Location , il codice HTTP di stato DEVE essere HTTP status 202 Accepted a meno che non si verifichino errori;
  • Al passo (3), il fruitore DEVE utilizzare il percorso di cui al passo (2) per richiedere lo stato della risorsa; il verbo HTTP utilizzato deve essere GET;
  • Al passo (4) l’erogatore indica, sulla base dello stato del processamento, che l’operazione: * 4a. non è completata (HTTP status 200 OK) * 4b. che la risorsa finale è pronta (HTTP status 303 See Other) all’URL indicato nell’ HTTP header Location ;
  • Al passo (5), il fruitore DEVE recuperare la risorsa con una richiesta HTTP method GET all’URL indicato in (4b.);
  • Al passo (6) l’erogatore risponde con la rappresentazione della risorsa, il codice HTTP restituito è HTTP status 200 OK.

6.2.1.1. Regole di processamento

Al termine del processamento delle richieste, l’erogatore deve fare uso dei codici di stato HTTP rispettando la semantica. In particolare, al ricevimento della richiesta da parte del fruitore, l’erogatore:

  • DEVE verificare la validità sintattica e semantica dei dati in ingresso
  • DEVE, in caso di dati errati, restituire HTTP status 400 Bad Request fornendo nel body di risposta dettagli circa l’errore;
  • DOVREBBE, in caso di representation semanticamente non corretta, ritornare HTTP status 422 Unprocessable Entity;
  • DEVE, se qualcuno degli ID nel path o nel body non esiste, restituire HTTP status 404 Not Found, indicando nel body di risposta quale degli ID è mancante;
  • PUÒ, se ipotizza che la richiesta sia malevola, ritornare HTTP status 400 Bad Request o HTTP status 404 Not Found;
  • DEVE, in caso di errori non dipendenti dalla richiesta, restituire HTTP status 5xx rispettando la semantica degli stessi;
  • DEVE, ricevuta la richiesta, restituire HTTP status 202 Accepted.
  • In caso di ricezione corretta della risposta, il fruitore DEVE restituire HTTP status 200 OK, riempiendo il body di risposta con il risultato dell’operazione.
  • In caso di errore al momento di ricezione della risposta da parte del fruitore, è possibile definire meccanismi specifici per la ritrasmissione della risposta o della richiesta.

NB: I messaggi di errore devono essere utili al client ma NON DEVONO rivelare dettagli tecnici e/o informazioni riservate.

6.2.1.2. Esempio

Specifica Servizio Server

https://api.ente.example/rest/nome-api/v1/openapi.yaml

openapi: 3.0.1
info:
 title: RESTbusywaiting
 version: "1.0"
 description: |-
   Questo file descrive semplicemente i metodi di un'API
   e non indica tutte le informazioni di metadatazione che
   normalmente vanno inserite.
 license:
   name: Apache 2.0 License
   url: http://www.apache.org/licenses/LICENSE-2.0.html
paths:
  /tasks/queue:
    post:
      description: Crea in maniera asincrona un task o una risorsa.
      operationId: PushMessage
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MType'
      responses:
        202:
          description: Preso carico correttamente
          headers:
            Location:
              description: URL dove verificare lo stato
              required: true
              schema:
                type: string
                format: uri
        '400':
          $ref: '#/components/responses/400BadRequest'

        default:
          $ref: '#/components/responses/default'
  /tasks/queue/{id_task}/:
    get:
      description: Verifica lo stato del task o risorsa
      operationId: CheckStatus
      parameters:
      - $ref: '#/components/parameters/id_task'
      responses:
        200:
          description: |-
            Lo stato del task o della risorsa.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaskStatus'
        '303':
          description: Task Completato
          content:
              application/json:
                schema:
                  $ref: '#/components/schemas/TaskStatus'
          headers:
              Location:
                description: URL dove prelevare il risultato
                required: true
                schema:
                  type: string
                  format: uri
        '400':
          $ref: '#/components/responses/400BadRequest'
        '404':
          $ref: '#/components/responses/404NotFound'
        default:
          $ref: '#/components/responses/default'
  /tasks/result/{id_task}/:
    get:
      description: Recupera il risultato del task o la risorsa
      operationId: RetriveResource
      parameters:
      - $ref: '#/components/parameters/id_task'
      responses:
        200:
          description:  Il risultato del task o la risorsa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MResponseType'
        '400':
          $ref: '#/components/responses/400BadRequest'
        '404':
          $ref: '#/components/responses/404NotFound'
        default:
          $ref: '#/components/responses/default'
components:
  parameters:
    id_task:
      name: id_task
      in: path
      required: true
      schema:
        type: string
  responses:
    400BadRequest:
      description: Richiesta non accoglibile
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorMessage'
    404NotFound:
      description: Identificativo non trovato
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorMessage'
    default:
      description: |-
        Errore inatteso. Questo viene ritornato nel caso ci sia
        un errore inatteso. Non vanno mai esposti i dati interni
        del server.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorMessage'
  schemas:
    TaskStatus:
      type: object
      properties:
        status:
          type: string
          enum: [pending, completed]
          example: pending
        message:
          type: string
    MType:
      type: object
      properties:
        a:
          $ref: '#/components/schemas/AComplexType'
        b:
          type: string
    MResponseType:
      type: object
      properties:
        c:
          type: string

    AComplexType:
      type: object
      properties:
        a1s:
          type: array
          items:
            type: string
        a2:
          type: string
    ErrorMessage:
      type: object
      properties:
        detail:
          description: |
            A human readable explanation specific to this occurrence of the
            problem.
          type: string
        instance:
          description: |
            An absolute URI that identifies the specific occurrence of the problem.
            It may or may not yield further information if dereferenced.
          format: uri
          type: string
        status:
          description: |
            The HTTP status code generated by the origin server for this occurrence
            of the problem.
          exclusiveMaximum: true
          format: int32
          maximum: 600
          minimum: 100
          type: integer
        title:
          description: |
            A short, summary of the problem type. Written in english and readable
            for engineers (usually not suited for non technical stakeholders and
            not localized); example: Service Unavailable
          type: string
        type:
          default: about:blank
          description: |
            An absolute URI that identifies the problem type.  When dereferenced,
            it SHOULD provide human-readable documentation for the problem type
            (e.g., using HTML).
          format: uri
          type: string

Il fruitore richiede la risorsa M, e l’erogatore risponde dichiarando di aver preso in carico la richiesta.

Endpoint https://api.ente.example/rest/nome-api/v1/resources/1234/M

  1. Request:
POST /rest/nome-api/v1/resources/1234/M HTTP/1.1
Host: api.ente.example
Content-Type: application/json

{
  "a": {
     "a1": [1, "…", 2],
     "a2": "Stringa di esempio"
  },
  "b": "Stringa di esempio"
}
  1. Response
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: /rest/nome-api/v1/resources/1234/M/8131edc0

{
  "status": "accepted",
  "message": "Preso carico della richiesta",
  "id": "8131edc0"
}

Quindi il fruitore verifica lo stato dell’esecuzione di M (3). L’erogatore ritorna un payload diverso a seconda dei casi: - processamento ancora in atto (4a) - e di processamento avvenuto (4b).

Endpoint

https://api.ente.example/rest/nome-api/v1/resources/1234/M/8131edc0

  1. Request
GET /rest/nome-api/v1/resources/1234/M/8131edc0 HTTP/1.1
Host: api.ente.example

4a. Response (HTTP status 200 OK)

HTTP/1.1 200 OK
Host: api.ente.example
Content-Type: application/json

{
  "status": "processing",
  "message": "Richiesta in fase di processamento"
}

4b. Response (HTTP status 303 See Other)

Poiché al termine del processamento il client viene rediretto verso la risorsa finale, il payload deve contenere solamente le informazioni utili al redirect. Questo anche perché alcuni client potrebbero seguire direttamente l”HTTP header Location ignorando il payload HTTP status 303 See Other e ritornando invece quello indicato nel punto 5.

HTTP/1.1 303 See Other
Content-Type: application/json
Content-Location: /rest/nome-api/v1/resources/1234/M/8131edc0
Location: /rest/nome-api/v1/resources/1234/M/8131edc0/result

{
  "status": "done",
  "message": "Processamento completo",
  "href": "https://api.ente.example/rest/nome-api/v1/resources/1234/M/8131edc0/result"
}

Di seguito un esempio di chiamata con cui il fruitore richiede l’esito della sua richiesta.

Endpoint

https://api.ente.example/rest/nome-api/v1/resources/1234/M/8131edc0/result

  1. Request:
GET /rest/nome-api/v1/resources/1234/M/8131edc0/result HTTP/1.1
Host: api.ente.example
  1. Response:
HTTP/1.1 200 OK
Host: api.ente.example
Content-Type: application/json

{"c": "OK"}