Commit b9762ebb authored by Michele Carignani's avatar Michele Carignani
Browse files

Examples by STF 576

parent dba54052
Loading
Loading
Loading
Loading
+310 −0
Original line number Original line Diff line number Diff line
openapi: 3.0.3
info:
  title: 'Examples for RESTful API guide'
  version: '1.0.0'
externalDocs:
  # Reference to the base document
  description: 'ETSI ES 203 647 ...'
  url: 'https://rest.etsi.org'
paths:
  # Resource path relative to server, parameters in curly braces
  /resource/{id}:
    # Method
    get:
      # Unique case-sensitive identifier
      operationId: getResource
      # Grouping
      tags:
        - Resource management
      summary: 'Read a resource'
      description: 'Read full contents of a resource with specific ID'
      parameters:
        # Parameter name used as the key in associative array of parameters
        - name: 'id'
          # The location of parameter: path, query, header or cookie
          in: path
          required: true
          description: 'Resource ID'
          schema:
            # Primitive type
            type: string
      responses:
        # Response code
        200:
          description: The requested resource
          # Custom headers
          headers:
            ETag:
              # Reference to (reusable) header definition
              $ref: '#/components/headers/ETag'
          # Response body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceData'
        401:
          # Reference to (reusable) response definition
          $ref: '#/components/responses/401'
        404:
          $ref: '#/components/responses/404'
  /resource:
    # POST JSON object
    post:
      # Info excluded
      operationId: postResource
      summary: Create new resource
      parameters:
        # Reference to (reusable) parameter definition
        - $ref: '#/components/parameters/resourceId'
        # Reference to (reusable) header definition
        - $ref: '#/components/parameters/Version'
      requestBody:
        description: 'Data for new resource'
        required: true
        content:
          # Content media type (Content-Type header value)
          application/json:
            schema:
              # Reference to data type
              $ref: '#/components/schemas/ResourceData'
      responses:
        204:
          # Reference to data type
          $ref: '#/components/responses/204'
  '/resource/{id}/file':
    # Upload a resource file
    put:
      # Info excluded
      operationId: uploadResourceFile
      summary: Upload a file for a resource
      parameters:
        - $ref: '#/components/parameters/resourceId'
      requestBody:
        description: 'An image file to be attached to the resource'
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                # Property name (also the name applied to content disposition)
                file:
                  type: string
                  # Sets content type to application/octet-stream
                  format: binary
            encoding:
              # Applies custom encoding to "file" property
              file:
                # Override default content type
                contentType: image/png
      responses:
        204:
          $ref: '#/components/responses/204'
  # Example search path /search?text=rest&max=5
  '/search':
    get:
      summary: 'Search resource'
      # Description excluded
      operationId: searchResource
      parameters:
        - name: 'text'
          in: query
          required: true
          description: 'Text to search for'
          schema:
            type: string
        - name: 'max'
          in: query
          # Optional parameter
          required: false
          description: 'Maximum number of results expected'
          schema:
            type: number
        - name: 'page'
          in: query
          required: false
          description: ''
          schema:
            type: number
      responses:
        200:
          # TBD
          description: 'The requested resource'
          # Custom headers
          headers:
            ETag:
              # Reference to (reusable) header definition
              $ref: '#/components/headers/ETag'
          # Response body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResults'
  '/subscription':
    post:
      summary: 'Subscribe to authenticated notifications'
      # Description excluded
      operationId: subscribeNotifications
      requestBody:
        content:
          application/json:
            schema:
              # Subscription containing callbackUrl property
              $ref: '#/components/schemas/Subscription'
      responses:
        # Subscription was created
        201:
          $ref: '#/components/responses/201'
      # Out-of-band notifications from server
      callbacks:
        # Named callback object (inline or reference)
        auth:
          # Local path used by server for callback(s)
          '{$request.body#/callbackUrl}/incoming':
            post:
              requestBody:
                content:
                  application/json:
                      schema:
                        $ref: '#/components/schemas/AuthenticatedNotification'
              responses:
                204:
                  $ref: '#/components/responses/204'
                401:
                  $ref: '#/components/responses/401'

  /service:
    get:
      # Info excluded
      operationId: getService
      # Support for GET request is mandatory for API provider
      x-etsi-provision: mandatory
      parameters:
        - name: 'circuitswitching'
          in: query
          required: false
          schema:
            type: string
          x-etsi-capabilities:
            # Parameter only applies to "3G" capability
            - 3G
      responses:
        200:
          description: 'The requested service'
          content:
            application/json:
              schema:
                type: object
                properties:
                  speed:
                    type: string
                    enum:
                      - fast
                      - superfast
                    x-etsi-enum:
                      # Enum value "superfast" is optional and
                      # only applies to "4G" and "5G" capabilities
                      superfast:
                        required: false
                        x-etsi-capabilities:
                          - 4G
                          - 5G
# Optional definitions
security: []
components:
  schemas:
    # Name of data type
    SearchResults:
      # Array type
      type: array
      items:
        # Type of array members, reference to ResourceData
        $ref: '#/components/schemas/ResourceData'
      # No more than 10 results
      maxItems: 10
    ResourceData:
      # Structured type
      type: object
      properties:
        # Property name
        id:
          # Property type
          type: string
        size:
          type: string
          enum:
            # Set of allowed values
            - big
            - bigger
            - biggerer
          # Default value for non-required property
          default: big
        created:
          # Date-time value encoded as string
          type: string
          format: date-time
      required:
        # Set of required properties
        - id
    Subscription:
      type: object
      properties:
        credentials:
          $ref: '#/components/schemas/Credentials'
    AuthenticatedNotification:
      type: object
    Credentials:
      type: object
  responses:
    # Common responses with response code as identifier
    201:
      description: 'Created'
    204:
      description: 'No content'
    401:
      description: 'Unauthenticated'
    404:
      description: 'Not found'
  headers:
    Version:
      description: 'API version'
      required: true
      schema:
        type: string
    # Definition of ETag header
    ETag:
      description: 'Identifier for a specific version of a resource'
      schema:
        type: string
  parameters:
    Version:
      name: 'Version'
      description: 'API version'
      in: header
      required: true
      schema:
        type: string
    resourceId:
      name: 'id'
      in: path
      required: true
      description: 'Resource ID'
      schema:
        type: string
  securitySchemes: {}
  callbacks: {}
servers:
  # Recommended structure for API paths
  - url: '{apiRoot}/{apiName}/{apiMajorVersion}/'
    variables:
      apiRoot:
        default: https://example.com
      apiName:
        description: Interface name from the base document
        default: rest-api-guide
      apiMajorVersion:
        description: Major version of the API from the base document
        default: v1
tags:
  # Optional descriptions of tags
  - name: Resource management
    description: Operations for managing resources
 No newline at end of file

README.md

0 → 100644
+17 −0
Original line number Original line Diff line number Diff line
# Examples for EG 203 647 - Methodology for RESTful APIs specifications and testing

The ETSI Guide EG 203 647 provides guidance and methodology for RESTful API specfication and testing based on analysis of methods, languages and best practices used in the industry and in ETSI groups. More information and download of the document available [here](https://portal.etsi.org/webapp/WorkProgram/Report_WorkItem.asp?WKI_ID=56708).

The set of examples or specification and testing artefacts related to EG 203 647 are maintained in this repository and comprise the following:

* **Example OpenAPI** specification located in the *OpenAPI* folder.
* **Example requirements**, **implementation conformance statements** and **test suite structure** generated from the OpenAPI specification located in the *RQ-ICS-TSS.md* file (also available as Word document).
* **Example test purposes** and related resources in [TDL-TO](https://tdl.etsi.org) located in the *TP* folder, with automatically generated TP skeletons in the *Generated* sub-folder and manually derived TPs in the *Manual* sub-folder.
* **Example test descriptions** and related resources in [TDL](https://tdl.etsi.org) located in the *TD* folder, including *Standard* and *HTTP* libraries for TDL, as well as separate data and behaviour packages for the example. Graphical representations with TDL-GR are also included.
* **Example test cases** and related resources in [TTCN-3](http://www.ttcn-3.org) located in the *TC* folder, with automatically generated TTCN-3 skeletons in the *Generated* sub-folder and manually derived complete TTCN-3 test cases in the *Manual* sub-folder

To make the best out of the test purposes in TDL-TO and the test descriptions in TDL, it is recommended to use the TOP toolset available at [top.etsi.org](). Further information on TDL and TDL-TO is available at [tdl.etsi.org]().

## Contact

For more information on ETSI TC MTS and this project, contact `espsupport` at `etsi` dot `org`.

RQ-ICS-TSS.md

0 → 100644
+105 −0
Original line number Original line Diff line number Diff line
# Generated Documentation

## Requirements

### API: Examples for RESTful API guide

| Identifier | Reference  | Type | Applicability | Requirement  | Context |
| ---------- | ---------- | ---- | ------------- | ------------ | ------- |
| RQ_RESOURCE_ID_GET_001 | Path: /resource/{id} | M | RESOURCE_ID | Read a resource; Read full contents of a resource with specific ID | getResource |
| RQ_RESOURCE_POST_001 | Path: /resource | M | RESOURCE | Create new resource;  | postResource |
| RQ_RESOURCE_ID_FILE_PUT_001 | Path: /resource/{id}/file | M | RESOURCE_ID_FILE | Upload a file for a resource;  | uploadResourceFile |
| RQ_SEARCH_GET_001 | Path: /search | M | SEARCH | Search resource;  | searchResource |
| RQ_SUBSCRIPTION_POST_001 | Path: /subscription | M | SUBSCRIPTION | Subscribe to authenticated notifications;  | subscribeNotifications |
| RQ_SERVICE_GET_001 | Path: /service | M | SERVICE |  | getService |
[Table X.Y: Extracted requirements]{custom-style="FL"}

## Implementation Conformance Statements

#### Detail

| ID | Resource  | Reference | Method | Type  | Request | Response |
| -- | --------- | --------- | ------ | ----- | ------- | -------- |
| D_RESOURCE_ID_GET_200_001 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200 |
| D_RESOURCE_ID_GET_401_002 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 401 |
| D_RESOURCE_ID_GET_404_003 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 404 |
| D_RESOURCE_POST_204_001 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| D_RESOURCE_ID_FILE_PUT_204_001 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| D_SEARCH_GET_200_001 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| D_SUBSCRIPTION_POST_201_001 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| D_SERVICE_GET_200_001 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
[Table X.Y: Extracted ICS (Detail)]{custom-style="FL"}

#### Method

| ID | Resource  | Reference | Method | Type  | Request | Response |
| -- | --------- | --------- | ------ | ----- | ------- | -------- |
| M1 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200,401,404 |
| M2 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| M3 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| M4 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| M5 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| M6 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
[Table X.Y: Extracted ICS (Method)]{custom-style="FL"}

#### Path

| ID | Resource  | Reference | Method | Type  | Request | Response |
| -- | --------- | --------- | ------ | ----- | ------- | -------- |
| P1 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200,401,404 |
| P2 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| P3 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| P4 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| P5 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| P6 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
[Table X.Y: Extracted ICS (Path)]{custom-style="FL"}

#### Hierarchical

| ID | Resource  | Reference | Method | Type  | Request | Response |
| -- | --------- | --------- | ------ | ----- | ------- | -------- |
| P1 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200,401,404 |
| P1_M1 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200,401,404 |
| P1_M1_R1 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 200 |
| P1_M1_R2 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 401 |
| P1_M1_R3 | /resource/{id} | Path: /resource/{id} : getResource | GET | M | (fill in request) | 404 |
| P2 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| P2_M1 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| P2_M1_R1 | /resource | Path: /resource : postResource | POST | M | (fill in request) | 204 |
| P3 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| P3_M1 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| P3_M1_R1 | /resource/{id}/file | Path: /resource/{id}/file : uploadResourceFile | PUT | M | (fill in request) | 204 |
| P4 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| P4_M1 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| P4_M1_R1 | /search | Path: /search : searchResource | GET | M | (fill in request) | 200 |
| P5 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| P5_M1 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| P5_M1_R1 | /subscription | Path: /subscription : subscribeNotifications | POST | M | (fill in request) | 201 |
| P6 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
| P6_M1 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
| P6_M1_R1 | /service | Path: /service : getService | GET | M | (fill in request) | 200 |
[Table X.Y: Extracted ICS (Hierarchical)]{custom-style="FL"}

## Test Suite Structure

* API: Examples for RESTful API guide
  * RESOURCE_ID
    * GET
      * GET_200
      * GET_401
      * GET_404
  * RESOURCE
    * POST
      * POST_204
  * RESOURCE_ID_FILE
    * PUT
      * PUT_204
  * SEARCH
    * GET
      * GET_200
  * SUBSCRIPTION
    * POST
      * POST_201
  * SERVICE
    * GET
      * GET_200
+229 −0
Original line number Original line Diff line number Diff line
module ExampleAPI {
    modulepar float mp_componentElapsedTimerMaxDuration
    type record ResourceData {
        charstring id ,
        integer size optional ,
        charstring created optional
    }

    template Request postResource := {
        uri := "/resource" , method := mPOST , headers := ? , parameters :=
        postParameters , body := "TODO_NOT_SUPPORTED_YETX"
    }

    template Parameters postParameters := {
        "TODO_NOT_SUPPORTED_YET"
    }

    template Request postResourceInline := {
        uri := "/resource" , method := mPOST , headers := ? , parameters :=
        "TODO_NOT_SUPPORTED_YETX" , body := "TODO_NOT_SUPPORTED_YETX"
    }

    template Parameter ID1 := {
        name := "TODO: Not Implemented Yet" , value_ :=
        "TODO: Not Implemented Yet" , location := path
    }

    template Response getResource200 := {
        status := "200" , statusMessage := "OK" , headers := ? , body :=
        "TODO_NOT_SUPPORTED_YETX"
    }

    template Response getResourceCollection200 := {
        status := "200" , statusMessage := "OK" , headers := ? , body :=
        validResources
    }

    template CollectionBody validResources := {
        "TODO_NOT_SUPPORTED_YET" , "TODO_NOT_SUPPORTED_YET"
    }

    template Response getResourceCollectionInline200 := {
        status := "200" , statusMessage := "OK" , headers := ? , body :=
        "TODO_NOT_SUPPORTED_YETX"
    }

    template Request getSearchInline := {
        uri := "/search" , method := mGET , headers := ? , parameters :=
        "TODO_NOT_SUPPORTED_YETX" , body := ?
    }

    template Parameters GetRequestParameters := {
        ID1
    }

}

module Standard {
    modulepar float mp_componentElapsedTimerMaxDuration
}

module HTTP {
}

module MessageBasedConfiguration {
    modulepar float mp_componentElapsedTimerMaxDuration

    function setupTestConfiguration_BasicClientServer ( ) runs on
    MTC_BasicClientServer {
        client := API.create ;
        map ( client : http_to_server_http , system : server_http ) ;
    }

    type component MTC_BasicClientServer {
        var API client ;
    }

    type component SYSTEM_BasicClientServer {
        port HTTPGate server_http ;
    }

    type component API {
        timer T_elapsedTimeOfComponent := mp_componentElapsedTimerMaxDuration ;
        port HTTPGate http ;
        port HTTPGate http_to_server_http ;
    }

    type port HTTPGate message {
        inout Request , Response
    }

}

module MessageBased {
    modulepar float mp_componentElapsedTimerMaxDuration
    type charstring MessageBased_SimpleDataType
    type MessageBased_SimpleDataType Method
    type MessageBased_SimpleDataType Location
    type record Request {
        charstring uri ,
        Method method optional ,
        Headers headers optional ,
        Parameters parameters optional ,
        Body body optional
    }

    type record Response {
        integer status optional ,
        charstring statusMessage optional ,
        Headers headers optional ,
        Body body optional
    }

    type record Parameter {
        Location location ,
        charstring name ,
        charstring value_
    }

    type record Header {
        charstring name ,
        charstring value_
    }

    type record Body {
    }

    type record StringBody {
        charstring text
    }

    type record CollectionBody {
        Bodies items
    }

    type record FormBody {
        charstring field ,
        charstring content
    }

    type record of Parameter Parameters
    type record of Header Headers
    type record of Body Bodies
    template Method mGET := "mGET"
    template Method mPOST := "mPOST"
    template Method mPUT := "mPUT"
    template Method mPATCH := "mPATCH"
    template Method mDELETE := "mDELETE"
    template Location path := "path"
    template Location query := "query"
    template Location cookie := "cookie"
    template Request GET := {
        uri := ? , method := ? , headers := ? , parameters := ? , body := ?
    }

    template Request POST := {
        uri := ? , method := ? , headers := ? , parameters := ? , body := ?
    }

    template Request PUT := {
        uri := ? , method := ? , headers := ? , parameters := ? , body := ?
    }

    template Request PATCH := {
        uri := ? , method := ? , headers := ? , parameters := ? , body := ?
    }

    template Request DELETE := {
        uri := ? , method := ? , headers := ? , parameters := ? , body := ?
    }

    template Response d200 := {
        status := ? , statusMessage := "OK" , headers := ? , body := ?
    }

    template Response d201 := {
        status := ? , statusMessage := "Created" , headers := ? , body := ?
    }

    template Response d204 := {
        status := ? , statusMessage := "No Content" , headers := ? , body := ?
    }

    template Response d400 := {
        status := ? , statusMessage := "Bad Request" , headers := ? , body := ?
    }

    template Response d401 := {
        status := ? , statusMessage := "Not Found" , headers := ? , body := ?
    }

    template Response d403 := {
        status := ? , statusMessage := "Not Authorized" , headers := ? , body
        := ?
    }

    template Response d404 := {
        status := ? , statusMessage := "Forbidden" , headers := ? , body := ?
    }

    template Response OK := {
        status := "200" , statusMessage := ? , headers := ? , body := ?
    }

    template Response Created := {
        status := "201" , statusMessage := ? , headers := ? , body := ?
    }

    template Response NoContent := {
        status := "204" , statusMessage := ? , headers := ? , body := ?
    }

    template Response BadRequest := {
        status := "400" , statusMessage := ? , headers := ? , body := ?
    }

    template Response NotFound := {
        status := "404" , statusMessage := ? , headers := ? , body := ?
    }

    template Response NotAuthorized := {
        status := "401" , statusMessage := ? , headers := ? , body := ?
    }

    template Response Forbidden := {
        status := "403" , statusMessage := ? , headers := ? , body := ?
    }

}
 No newline at end of file
+385 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading