belgif / rest-guide

REST Guidelines of Belgian government institutions
https://www.belgif.be/specification/rest/api-guide/
Apache License 2.0
26 stars 4 forks source link

Warnings in successful response #190

Open jpraet opened 3 months ago

jpraet commented 3 months ago

This topic has already been briefly touched upon in https://github.com/belgif/rest-guide/issues/74.

How can we model non-blocking warnings that are returned in a successful API response?

A Warning HTTP header exists, but it is deprecated.

There's also a proposed RFC draft Communicating Warning Information in HTTP APIs. It prescribes a top-level "warnings" array property, containing RFC7807 (now superseded by RFC9457) problem details. Additionally, it suggests adding an Content-Warning HTTP header indicating that there are warnings present in the response.

Example:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Warning: "embedded-warning"; 1590190500

{
 "request_id": "2326b087-d64e-43bd-a557-42171155084f",
 "warnings": [
   {
     "detail": "Street name was too long. It has been shortened...",
     "instance": "https://example.com/shipments/3a186c51/msgs/c94d",
     "status": "200",
     "title": "Street name too long. It has been shortened.",
     "type": "https://example.com/errors/shortened_entry" 
   },
   {
     "detail": "City for this zipcode unknown. Code for shipment..",
     "instance": "https://example.com/shipments/3a186c51/msgs/5927",
     "status": "200",
     "title": "City for zipcode unknown.",
     "type": "https://example.com/errors/city_unknown" 
   }
 ],
 "id": "3a186c51d4281acb",
 "carrier_tracking_no": "84168117830018",
 "tracking_url": "http://example.com/3a186c51d",
 "label_url": "http://example.com/shipping_label_3a186c51d.pdf",
 "price": 3.4
}

Could we design a standard for this in the Belgif REST Guide (possibly inspired by above RFC draft)?

Some questions come to mind:

Here are a couple of real-life scenarios for warning messages at CBSS:

jpraet commented 1 month ago

As we already had a need for this in one of our APIs, here's how we modeled this at CBSS in the mean time:

    ProcessingWarning:
      # This definition is similar to InputValidationIssue, but without the inheritance of Problem, and with a
      # name that should avoid confusion about its usage
      description: >
        Report of a non-blocking issue that occurred during processing. Examples of issues could be:
        non-blocking input validations, non-critical omissions of data in the response because of the non-availability
        of a data source, processing that wasn't done by the server, etc.
      type: object
      required: [type]
      properties:
        type:
          type: string
          format: uri
          description: An absolute URI that identifies the warning type
        href:
          type: string
          format: uri
          description: >
            An absolute URI that, when dereferenced, provides human-readable documentation for the problem type
            (e.g. using HTML).
        title:
          type: string
          description: >
            A short summary of the warning type. Written in English and readable for engineers
            (usually not suited for non technical stakeholders and not localized).
          example: Update didn't change any data
        detail:
          type: string
          description: A human-readable explanation specific to this occurrence of the warning
          example: No difference found between the address in the request and the address in the database
        inputs:
          type: array
          items:
            $ref: "#/components/schemas/InputOutputReference"
        outputs:
          type: array
          items:
            $ref: "#/components/schemas/InputOutputReference"
      example:
        type: urn:warning-type:cbss:ssinInsufficientlyIntegratedForProvider
        title: Insufficiently Integrated SSIN for provider
        detail: The SSIN is not sufficiently integrated for the provider
        inputs:
          - in: query
            name: ssin
            value: "11111111111"
    InputOutputReference:
      description: The reference to a field in request or response
      type: object
      properties:
        in:
          type: string
          description: The location of the field
          enum:
            - body
            - header
            - path
            - query
        name:
          type: string
          description: The name of the field
        value:
          description: The value of the field

documentation:

image

pvdbosch commented 1 month ago

Do you have any examples of warnings on output fields?

Anomalies in the current state of a resource could also be represented in a specific data structure (e.g. "duplicateRegistration": true) rather than warnings; I wonder if there are some best practices.

jpraet commented 1 month ago

Do you have any examples of warnings on output fields?

{
    "items": [
        {
            "href": "https://api.ksz-bcss.fgov.be/isi/v1/cards/9950001534",
            "id": "9950001534",
            "cardSsin": "53480200724",
            "valid": true
        }
    ],
    "total": 1,
    "embedded": {
        "https://api.ksz-bcss.fgov.be/isi/v1/cards/9950001534": {
            "id": "9950001534",
            "cardSsin": "53480200724",
            "validityPeriod": {
                "startDate": "2014-01-03",
                "endDate": "2026-12-31"
            },
            "cycle": "produced",
            "valid": true
        }
    },
    "warnings": [
        {
            "type": "urn:warning-type:cbss:isi:missingPersonData",
            "title": "Missing person data",
            "detail": "Unable to provide recto and verso, missing person data",
            "outputs": [
                {
                    "in": "body",
                    "name": "embedded.*.id",
                    "value": 9950001534
                }
            ]
        }
    ]
}
pvdbosch commented 1 month ago

"status" wouldn't be used for warnings

Could WG members add their own use cases to have warnings to this issue?

jpraet commented 1 month ago

"status" wouldn't be used for warnings

Yes, in the warning type from CBSS we chose not to extend from Problem, so we can omit the "status" and "instance" properties which don't really make sense in this context.

The same could also be said for InputValidationIssue though: it is kind of unfortunate that that type extends from Problem, but with a description indicating the status is usually not present.

What about extracting a base type with properties type, href, title and detail? Problem, InputValidationIssue and Warning can then all extend this base type.