A delightfully tasty plugin for generating OpenAPI, Swagger and Redoc

Swagger Bake

A delightfully tasty plugin for generating OpenAPI, Swagger and Redoc

Automatically generate OpenApi, Swagger, and Redoc documentation from your existing CakePHP code

  • Creates OpenApi paths and operations from your RESTful routes and controllers.
  • Creates OpenAPI Schema from your Entities and Tables.
  • Integrates with: Paginator, friendsofcake/search, Validator, and Bake.
  • Provides additional functionality through Attributes and Doc Blocks.

Check out the demo applications for examples.

DemosSource
Swagger Bake Demo (v2)https://github.com/cnizzardini/cakephp-swagger-bake-demo
Swagger Bake Demo (v1)https://github.com/cnizzardini/cakephp-swagger-bake-demo/tree/1.next
Swagger/MixerAPI Demo (v1)https://github.com/mixerapi/demo

This is built for CakePHP 4.x only. Supported versions:

VersionBranchCake VersionPHP Version
2.*master^4.28.0+
1.*1.next^4.07.2+

Installation

SwaggerBake requires CakePHP4 and a few dependencies that will be automatically installed via composer.

composer require cnizzardini/cakephp-swagger-bake

Run bin/cake plugin load SwaggerBake or manually load the plugin:

# src/Application.php
public function bootstrap(): void
{
    // other logic...
    $this->addPlugin('SwaggerBake');
}

For standard applications that have not split their API into plugins, the automated setup should work. Otherwise use the manual setup.

Automated Setup

Run the installer:

bin/cake swagger install

Then load the config and add a route.

Manual Setup

Create a base swagger.yml file at config\swagger.yml. An example file is provided here.

Create a swagger_bake.php config file at config/swagger_bake.php file. See the example file here for further explanation. Then just add a route.

For more read sections on Multiple Instances of SwaggerBake and Extending Views and Controllers

Load the config

In your config/bootstrap.php file:

Configure::load('swagger_bake', 'default', false);

Add Route

Create a route for the SwaggerUI page in config/routes.php, example:

$builder->connect(
    '/api',
    ['plugin' => 'SwaggerBake', 'controller' => 'Swagger', 'action' => 'index']
);

You can now browse to either /api for swagger or /api?doctype=redoc for redoc. Your OpenAPI JSON will exist at /api/swagger.json.

Getting Started

  • You can generate OpenAPI json from the command line at anytime by running:
bin/cake swagger bake

If Hot Reload is enabled (see config) OpenAPI will be generated each time you browse to SwaggerUI (or Redoc) in your web browser.

You can also generate OpenAPI programmatically:

$swagger = (new \SwaggerBake\Lib\SwaggerFactory())->create();
$swagger->getArray(); # returns swagger array
$swagger->toString(); # returns swagger json
$swagger->writeFile('/full/path/to/your/swagger.json'); # writes swagger.json

Routes

Your RESTful routes are used to build OpenAPI paths and operations.

Controllers

SwaggerBake will parse the DocBlocks on your controller actions for additional OpenAPI data.

/**
 * OpenAPI Operation Summary
 * 
 * This displays as the operations long description
 * 
 * @link https://book.cakephp.org/4/en/index.html External documentation
 * @deprecated Indicates the operation is deprecated
 * @throws \Cake\Http\Exception\BadRequestException Appears as 400 response with this description
 * @throws \Exception Appears as 500 response with this description
 */
public function index() {}

If you prefer, you may use the OpenApiOperation, OpenApiResponse attributes instead. These attributes take precedence over doc block parsing. Read below for a full list of attributes.

Models

OpenAPI schema is built from your Table and Entity classes and any validators you've defined in them. You may adjust the default schema using the OpenApiSchema and OpenApiSchemaProperty attributes.

Attributes

For additional functionality the following PHP8 Attributes may be used. These can be imported individually from the SwaggerBake\Lib\Attribute namespace. Read the Attributes docs for detailed examples. If you are using version 1 you will need to use annotations.

AttributeUsageDescription
OpenApiDtoController ActionBuilds OpenAPI query params and request bodies from Data Transfer Objects
OpenApiFormController ActionBuilds OpenAPI for application/x-www-form-urlencoded request bodies
OpenApiHeaderController ActionCreate OpenAPI header parameters
OpenApiOperationController ActionModifies OpenAPI operation
OpenApiPaginatorController ActionCreate OpenAPI query params from CakePHP Paginator Component
OpenApiPathControllerModifies OpenAPI paths
OpenApiPathParamController ActionModify an existing OpenAPI path parameter
OpenApiQueryParamController ActionBuilds OpenAPI query param
OpenApiRequestBodyController ActionModify OpenAPI request body
OpenApiResponseController ActionModify OpenAPI response
OpenApiSchemaEntityModifies OpenAPI schema
OpenApiSchemaPropertyEntity or ClassModifies an OpenAPI schema property or defines OpenApiResponse schema
OpenApiSearchController ActionCreate OpenAPI query params from CakePHP Search plugin
OpenApiSecurityController ActionCreate/modify OpenAPI security
OpenApiDtoQueryDTO class propertyBuilds OpenAPI query param from Data Transfer Objects (deprecated, use OpenApiQueryParam in v2.2.5+)
OpenApiDtoRequestBodyDTO class propertyBuilds OpenAPI request body property from Data Transfer Objects (deprecated, use OpenApiSchemaProperty in v2.2.5+)

Event System

SwaggerBake comes with an event system to allow for further control over your OpenAPI schema.

EventDescription
SwaggerBake.Operation.createdDispatched each time an OpenAPI Path > Operation is created
SwaggerBake.Path.createdDispatched each time an OpenAPI Path is created
SwaggerBake.Schema.createdDispatched each time an OpenAPI Schema is created
SwaggerBake.initializeDispatched during initialization phase on SwaggerBake
SwaggerBake.beforeRenderDispatched before SwaggerBake outputs OpenAPI JSON

Customizing Exception Response Samples

By default, SwaggerBake uses '#/components/schemas/Exception' as your OpenAPI documentations Exception schema. See the default swagger.yml and exceptionSchema in swagger_bake.php for more info. You can further customize with attributes and @throws.

OpenApiResponse

Using the ref or schema properties of OpenApiResponse.

Using the @throws tag and OpenApiExceptionSchemaInterface

Implement SwaggerBake\Lib\OpenApiExceptionSchemaInterface on your exception class, then document the exception with a @throws tag in your controller action's doc block.

/**
 * @throws \App\Exception\MyException
 */
public function add(){}

Example exception class:

class MyException implements OpenApiExceptionSchemaInterface 
{
    public static function getExceptionCode(): string
    {
        return '400';
    }

    public static function getExceptionDescription(): ?string
    {
        return 'An optional description'; // returning null omits the response description
    }

    public static function getExceptionSchema(): Schema|string
    {
        return (new \SwaggerBake\Lib\OpenApi\Schema())  
            ->setTitle('MyException')
            ->setProperties([
                (new SchemaProperty())->setType('string')->setName('code')->setExample('400'),
                (new SchemaProperty())->setType('string')->setName('message')->setExample('error'),
                (new SchemaProperty())->setType('string')->setName('wherever')->setExample('whatever you want')
            ]);
    }
}

Extending Views and Controllers

It's possible to write extensions for SwaggerBake. Read the extensions documentation. There are several other options to extend functionality documented below:

Using Your Own SwaggerUI

You may use your own swagger or redoc install in lieu of the version that comes with SwaggerBake. Simply don't add a custom route as indicated in the installation steps. In this case just reference the generated swagger.json within your userland Swagger UI install.

Using Your Own Controller

You might want to perform some additional logic (checking for authentication) before rendering the built-in Swagger UI. This is easy to do. Just create your own route and controller, then reference the built-in layout and template:

// config/routes.php
$builder->connect('/my-swagger-docs', ['controller' => 'MySwagger', 'action' => 'index']);

To get started, copy SwaggerController into your project.

Note: SwaggerUiComponent has been deprecated in version 2.3.0 and will be removed in version 3.

Using Your Own Layout and Templates

You will need to use your own controller (see above). From there you can copy the layouts and templates into your project and inform your controller action to use them instead. Checkout out the CakePHP documentation on Views for specifics. This can be useful if you'd like to add additional functionality to SwaggerUI (or Redoc) using their APIs or if your project is not installed in your web servers document root (i.e. a sub-folder).

Multiple Instances of Swagger Bake

If your application has multiple APIs that are split into plugins you can generate unique OpenAPI schema, Swagger UI, and Redoc for each plugin. Setup a new swagger_bake.php and swagger.yaml in plugins/OtherApi/config. These configurations should point to your plugins paths and namespaces. Next, create a custom SwaggerController and load the configuration within initialize():

    public function initialize(): void
    {
        parent::initialize();
        Configure::load('OtherApi.swagger_bake', 'default', false); // note: `false` for the third argument is important
         
        /*
         * Only load the component if you are using a version older than v2.3.0. This component will be deprecated 
         * in v3.0.0
         */ 
        $this->loadComponent('SwaggerBake.SwaggerUi');
    }

When running bin/cake swagger bake you will need to specify your plugins swagger_bake config:

bin/cake swagger bake --config OtherApi.swagger_bake

Debug Commands

In addition to swagger bake these console helpers provide insight into how your Swagger documentation is generated.

swagger routes

Displays a list of routes that can be viewed in Swagger.

bin/cake swagger routes

swagger models

Displays a list of models that can be viewed in Swagger.

bin/cake swagger models

Bake Theme

SwaggerBake comes with Bake templates for scaffolding RESTful controllers compatible with SwaggerBake and OpenAPI 3.0 schema. Using the bake theme is completely optional, but will save you some time since the default bake theme is not specifically designed for RESTful APIs.

bin/cake bake controller {Name} --theme SwaggerBake

Common Issues

Swagger UI

No API definition provided.

Verify that swagger.json exists.

SwaggerBakeRunTimeExceptions

Unable to create swagger file. Try creating an empty file first or checking permissions

Create the swagger.json manually matching the path in your config/swagger_bake.php file.

Output file is not writable

Change permissions on your swagger.json file, 764 should do.

Controller not found

Make sure a controller actually exists for the route resource.

Missing routes

Make sure yours route are properly defined in config/routes.php per the CakePHP RESTful routing documentation.

Missing request or response samples

Sample schema is determined using CakePHP naming conventions. Does your controller name match your model names? For customizing response schema see OpenApiResponse.

Missing request schema

Sample schema is determined using CakePHP naming conventions. Does your controller name match your model names? For customizing request schema see OpenApiRequestBody.

Missing CSRF token body

Either disable CSRF protection on your main route in config/routes.php or enable CSRF protection in Swagger UI. The library does not currently support adding this in for you.

HTTP DELETE issues with Swagger UI

Swagger UI sends HTTP DELETE without an accept header. If the record does not exist, an exception is generated. This results in an HTML response being generated which can be quite large and cause the UI to be slow to render. To get around this you can force an accept value on the header using the CakePHP middleware:

# src/Application.php

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $middlewareQueue
        ->add(function(ServerRequestInterface $request, RequestHandlerInterface $handler){
            $accept = $request->getHeader('accept');
            if ($request->getMethod() === 'DELETE' && reset($accept) === '*/*') {
                $request = $request->withHeader('accept', 'application/json');
            }

            return $handler->handle($request);
        });

    // other middleware...
    
    return $middlewareQueue;
}

Read more about CakePHP middleware in the official documentation.

Contribute

Send pull requests to help improve this library. You can include SwaggerBake in your primary Cake project as a local source to make developing easier:

Make a fork of this repository and clone it to your localhost

Remove cnizzardini\cakephp-swagger-bake from your composer.json

Add a paths repository to your composer.json

"minimum-stability": "dev",
"repositories": [
    {
        "type": "path",
        "url": "/absolute/local-path-to/cakephp-swagger-bake",
        "options": {
          "symlink": true
        }
    }
]
  • Run composer require cnizzardini/cakephp-swagger-bake @dev

Undo these steps when you're done. Read the full composer documentation on loading from path here: https://getcomposer.org/doc/05-repositories.md#path

Check out the extensions documentation to add functionality to this project.

Tests + Analysis

PHPUnit Test Suite:

composer test

PHPUnit, PHPCS, PHPSTAN, and PHPMD:

composer analyze

GrumPHP can be used to run tests and static analyzers in a pre-commit hook.

composer grumphp-init

I've set grumphp to be installed globally: https://github.com/phpro/grumphp/blob/master/doc/installation/global.md

Author: cnizzardini
Source Code: https://github.com/cnizzardini/cakephp-swagger-bake 
License: MIT license

#php #cakephp #swagger #openapi 

A delightfully tasty plugin for generating OpenAPI, Swagger and Redoc
Hermann  Frami

Hermann Frami

1656088140

Serverless Openapi Plugin

serverless-openapi-plugin

Serverless plugin to generate AWS serverless architecture from openApi definition.

It also generate validation (using Joi) for headers/query/params and body.

Configuration

On your serverless.yml add:

plugins: 
 -serverless-openapi-plugin

By default the plugin is looking for a definition.yml, but you can override this setting using:

customs: 
 definition: mydefinition.yml

In order to generate handlers, you need to specify the handler name at root or operation level with x-serverless-handler key.

Usage

Simple as:

serverless openapi

Author: jaumard
Source Code: https://github.com/jaumard/serverless-openapi-plugin 
License: 

#serverless #openapi 

Serverless Openapi Plugin
Hermann  Frami

Hermann Frami

1656080760

Serverless Plugin: AWS API Gateway integration Helper

Serverless Plugin: AWS Api Gateway integration helper

Overview

The plugin provides the functionality to merge OpenApiSpecification files (formerly known as swagger) with one or multiple YML files containing the the x-amazon-apigateway extensions. There are several use-cases to keep both information separated, e.g. it is needed to deploy different api gateway integrations depending on a stage environment.

When dealing with functional tests you do not want to test the production environment, but only a mocking response.

The plugin supports YML based OpenApi3 specification files only

Features

  • deploy stage dependent x-amazon-apigateway integrations
  • separate infrastructure (aws) from openapi specification
  • use mock integrations for functional testing
  • auto-generating CORS methods, headers and api gateway mocking response
  • hook into package & deploy lifeCycle and generate combined openApi files on the fly during deployment
  • auto-inject generated openApi file into the Body property of specified API Gateway
  • generate mocking responses without specifying x-amazon-apigateway-integration objects
  • generate request-validation blocks
  • generate all required x-amazon-apigateway-integration objects automatically
  • full proxy generation support with [NEW]: feature: PROXY Manager

See the examples folder for a full working example

Installation & Setup

Run npm install in your Serverless project.

$ npm install --save-dev serverless-openapi-integration-helper

Add the plugin to your serverless.yml file

plugins:
  - serverless-openapi-integration-helper

Plugin configuration

You can configure the plugin under the key openApiIntegration. See See Configuration Reference for a list of available options

The mapping array must be used to configure where the files containing the x-amazon-apigateway-integration blocks are located.

openApiIntegration:
    package: true #New feature! Hook into the package & deploy process
    inputFile: schema.yml
    mapping:
       - stage: [dev, prod] #multiple stages
         path: integrations
       - stage: test #single stage
         path: mocks

In the above example all YML files inside the integrations directory will be processed and merged with the schema.yml file when deploying the dev stage

serverless deploy --stage=dev

To use a different x-amazon-apigateway to perform functional tests (with mocking responses e.g) the directory mock is processed and merged with the schema.yml file when deploying the test stage

serverless deploy --stage=test

Usage

You can setup a fully working API GATEWAY with any openApi 3.0 specification file First create the input file containing the OpenApiSpecification

# ./schema.yml
openapi: 3.0.0
info:
  description: User Registration
  version: 1.0.0
  title: UserRegistration
paths:
  /api/v1/user:
    post:
      summary: adds a user
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Customer'
      responses:
        '201':
          description: user created
components:
  schemas:
    Customer:
      type: object
      required:
        - email_address
        - password
      properties:
        email_address:
          type: string
          example: test@example.com
        password:
          type: string
          format: password
          example: someStrongPassword#

The plugin will generate the x-amazon-apigateway integrations objects for all methods that do not have an integration.

#generate a file containing a gateway mock integration in the directory /mocks
serverless integration create --output mocks --type mock --stage=test

#generate a file containing the production integration in the directory integrations/
serverless integration create --output integrations --type http --stage=prod

Supported types are

  • http_proxy
  • http
  • aws
  • aws_proxy
  • mock

The plugin now generates a merged file during deployment that is automatically injected in your serverless resources

#Create OpenApi File containing mocking responses (usable in functional tests) and deploy to ApiGateway
serverless deploy --stage==test
#Create OpenApi File containing the production integration and deploy to ApiGateway
serverless deploy --stage=prod

The generated output is automatically injected in the resources.Resources.YOUR_API_GATEWAY.Properties.Body property

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        ApiKeySourceType: HEADER
        Body: ~ #autogenerated by plugin
        Description: "Some Description"
        FailOnWarnings: false
        Name: ${opt:stage, self:provider.stage}-some-name
        EndpointConfiguration:
          Types:
            - REGIONAL
    ApiGatewayDeployment:
      Type: AWS::ApiGateway::Deployment
      Properties:
        RestApiId:
          Ref: ApiGatewayRestApi
        StageName: ${opt:stage, self:provider.stage}

Commands

Manual merge

The generate command can be used independently with

serverless integration merge --stage=dev

Of course then the API Gateway Body property has to be specified manually

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        ApiKeySourceType: HEADER
        Body: ${file(openapi-integration/api.yml)}

CORS generator

The plugin can generate full CORS support out of the box.

openApiIntegration:
  cors: true
  ...

If enabled, the plugin generates all required OPTIONS methods as well as the required header informations and adds a mocking response to API Gateway. You can customize the CORS templates by placing your own files inside a directory openapi-integration (in your project root). The following files can be overwritten:

FilenameDescription
headers.ymlAll headers required for CORS support
integration.ymlContains the x-amazon-apigateway-integration block
path.ymlOpenApi specification for the OPTIONS method
response-parameters.ymlThe response Parameters of the x-amazon-apigateway-integration responses

See the EXAMPLES directory for detailed instructions.

Auto Mock Generator

If enabled, the plugin generates mocking responses for all methods that do not have an x-amazon-apigateway-integration block defined. It takes the first 2xx response defined in the openApi specification and generates a simple mocking response on the fly

openApiIntegration:
  autoMock: true
  ...

When using the autoMock feature, you do not need to specify inputPath mappings, since all endpoints are mocked automatically

openApiIntegration:
    package: true
    inputFile: schema.yml
    mapping: ~

VALIDATION generator

The plugin supports full request validation out of the box

openApiIntegration:
  validation: true
  ...

If enabled, the plugin generates the x-amazon-apigateway-request-validators blocks and adds a basic request validation to all methods. You can customize the VALIDATION template by placing your own files inside a directory openapi-integration (in your project root). The following files can be overwritten:

FilenameDescription
request-validator.ymlThe x-amazon-apigateway-request-validators block

See the EXAMPLES directory for detailed instructions.

Proxy Manager

The proxymanager feature automates the complete generation of an HTTP proxy integration. You only have to define the target URL and all necessary AWS integration blocks are generated on-the-fly during deployment.

openApiIntegration:
   cors: true
   validation: true
   mapping:
      - stage: [dev, prod]
        proxyManager:
           type: http_proxy
           baseUrl: https://www.example.com
           pattern: "(?<=api\/v1)\/.+"
  ...

With this setting, no separate integration files need to be created

A combination of your own and auto-generated files is still possible without any problems

Proxy Manager configuration

type

at the moment only http_proxy supported

baseUrl

The base url is required to map the path variable from the openapi specification to the URI from the aws integration.

Example:

#original openapi specification
paths:
   /api/v1/user:
    post:
      ... 

will be translated to

#generated openapi specification output
paths:
   /api/v1/user:
      post:
         ...
         x-amazon-apigateway-integration:
            type: http_proxy
            passthroughBehavior: when_no_match
            httpMethod: POST
            uri: https://www.example.com/api/v1/user

pattern

The pattern can be used to adapt the mapping of the base url using regexp, to remove a prefix, or a version string

Example:

baseUrl: https://www.example.com
pattern: "(?<=api\/v1)\/.+"

will translate the route /api/v1/user to https://www.example.com/user

Configuration Reference

configure the plugin under the key openApiIntegration

openApiIntegration:
  inputFile: schema.yml #required
  package: true #optional, defaults to false 
  inputDirectory: ./ #optional, defaults to ./
  cors: true #optional, defaults to false
  autoMock: true #optional, defaults to false
  validation: true #optional, defaults to false
  mapping: #optional, can be completely blank if autoMock option is enabled
    - stage: [dev, prod] #multiple stages
      path: integrations
      proxyManager: #optional
         type: http_proxy
         baseUrl: https://example.com
         pattern: "(?<=v1)\/.+"
    - stage: test #single stage
      path: mocks/customer.yml
  outputFile: api.yml #optional, defaults to api.yml
  outputDirectory: openapi-integration #optional, defaults to ./openapi-integration

Known Issues

Stage deployment

When using serverless framework only to deploy your aws resources without having any lambda functions or triggers, the AWS Gateway deploymemt does not behave as expected. Any deployment to an existing stage will be ignored, since CloudFormation does not redeploy a stage if the DeploymentIdentifier has not changed.

The plugin serverless-random-gateway-deployment-id solves this problem by adding a random id to the deployment-name and all references to it on every deploy

See the examples folder for a full working example

Variable Resolving

Serverless variables inside the openapi integration files are not resolved correctly when using the package & deploy hooks. This problem can be solved by using the api gateway STAGE VARIABLES.

See the examples folder for a full working example

Example

service:
  name: user-registration

provider:
  name: aws
  stage: dev
  region: eu-central-1

plugins:
  - serverless-openapi-integration-helper
  
openApiIntegration:
  inputFile: schema.yml
  package: true
  mapping:
    - path: integrations
      stage: [dev, prod]
    - path: mocks/customer.yml
      stage: test

functions:

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        ApiKeySourceType: HEADER
        Body: ~
        Description: "Some Description"
        FailOnWarnings: false
        Name: ${opt:stage, self:provider.stage}-some-name
        EndpointConfiguration:
          Types:
            - REGIONAL
    ApiGatewayDeployment:
      Type: AWS::ApiGateway::Deployment
      Properties:
        RestApiId:
          Ref: ApiGatewayRestApi
        StageName: ${opt:stage, self:provider.stage}
serverless deploy --stage=test
serverless deploy --stage=prod

Approach to a functional test of schema validation

The plugin works well in combination with the serverless-plugin-test-helper to automate tests against the deployed api gateway

Install The plugin test helper package

npm install --save-dev serverless-plugin-test-helper

add the plugin as a plugin dependency in your serverless configuration file and configure the plugin according to the Readme

#./serveless.yml
plugins:
  - serverless-plugin-test-helper
  - serverless-openapi-integration-helper

[...]

resources:
   Outputs:
      GatewayUrl: # This is the key that will be used in the generated outputs file
         Description: This is a helper for functional tests
         Value: !Join
            - ''
            - - 'https://'
              - !Ref ApiGatewayRestApi
              - '.execute-api.'
              - ${opt:region, self:provider.region}
              - '.amazonaws.com/'
              - ${opt:stage, self:provider.stage}

   Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        ApiKeySourceType: HEADER
        Body: ~
        Description: User Registration (${opt:stage, self:provider.stage})
        FailOnWarnings: false
        Name: ${opt:stage, self:provider.stage}-gateway
        EndpointConfiguration:
          Types:
            - REGIONAL
    ApiGatewayDeployment:
      Type: AWS::ApiGateway::Deployment
      Properties:
        RestApiId:
          Ref: ApiGatewayRestApi
        StageName: ${opt:stage, self:provider.stage}

Testing the schema validation

Add a functional test (e.g. with jest)

//tests/registration.js
import {getOutput} from 'serverless-plugin-test-helper';
import axios from 'axios';

axios.defaults.adapter = require('axios/lib/adapters/http'); //Todo

const URL = getOutput('GatewayUrl');
test('request validation on registration', async () => {
    expect.assertions(1);
    const {status} = await axios.post(URL + '/api/v1/user',
        {
            "email_address": "test@example.com",
            "password": "someStrongPassword#"
        },
        {
            headers: {
                'Content-Type': 'application/json',
            }
        });
    expect(status).toEqual(201);
});

test('request validation on registration (invalid request)', async () => {
    expect.assertions(1);
    try {
        await axios.post(URL + '/api/v1/user',
            {
                "email": "test@example.com"
            },
            {
                headers: {
                    'Content-Type': 'application/json',
                }
            });
    } catch (e) {
        expect(e.response).toMatchObject({
            statusText: 'Bad Request',
            status: 400
        });
    }
});

Then perform the functional test

serverless deploy --stage=test
npm test
serverless remove --stage=test

The command will

  • merge the openapi specification file with the MOCK integration configured before
  • deploy to API Gateway in an isolated TEST infrastructure environment (your other environments will not be affected since we are deploying to a separated gateway)
  • perform the test and verify that schema validation is correct
  • remove all TEST resources if test succeeded

See the examples folder for a full working example

Feedback is appreciated! If you have an idea for how this plugin/library can be improved (or even just a complaint/criticism) then please open an issue.

Author: yndlingsfar
Source Code: https://github.com/yndlingsfar/serverless-openapi-integration-helper 
License: MIT license

#serverless #openapi #aws 

Serverless Plugin: AWS API Gateway integration Helper
Hermann  Frami

Hermann Frami

1656073080

Serverless OpenAPI Documentation Plugin

Serverless OpenAPI Documentation Plugin  

Generates OpenAPI 3.0.0 documentation from serverless configuration files. OpenAPI is formerly known as Swagger.


Usage

This plugin requires additional configuration to use, see the "Configuration" section for how to configure the plugin to generate documentation.

Below are the commandline options to run the generator:

serverless openapi generate [options]

Options

Plugin: ServerlessOpenAPIDocumentation
openapi generate  ...................... Generate OpenAPI v3 Documentation
    --output / -o ...................... Output file location [default: openapi.yml|json]
    --format / -f ...................... OpenAPI file format (yml|json) [default: yml]
    --indent / -i ...................... File indentation in spaces [default: 2]
    --help / -h   ...................... Help

Configuration

To configure this plugin to generate valid OpenAPI documentation there are two places you'll need to modify in your serverless.yml file, the custom variables section and the http event section for each given function in your service.

This plugin is compatible with the same documentation configuration structure in serverless-aws-documentation and can run beside it.

The custom section of your serverless.yml can be configured as below:

custom:
  documentation:
    version: '1'
    title: 'My API'
    description: 'This is my API'
    models: {}

These configurations can be quite verbose; you can separate it out into it's own file, such as serverless.doc.yml as below:

custom:
  documentation: ${file(serverless.doc.yml):documentation}

functions:
  myFunc:
    events:
      - http:
          path: getStuff
          method: get
          documentation: ${file(serverless.doc.yml):endpoints.myFunc}

For more info on serverless.yml syntax, see their docs.

Models

Models contain additional information that you can use to define schemas for endpoints. You must define the content type for each schema that you provide in the models.

The required directives for the models section are as follow:

  • name: the name of the schema
  • description: a description of the schema
  • contentType: the content type of the described request/response (ie. application/json or application/xml).
  • schema: The JSON Schema (website) that describes the model. You can either use inline YAML to define these, or refer to an external schema file as below
custom:
  documentation:
    models:
      - name: "ErrorResponse"
        description: "This is an error"
        contentType: "application/json"
        schema: ${file(models/ErrorResponse.json)}
      - name: "PutDocumentResponse"
        description: "PUT Document response model (external reference example)"
        contentType: "application/json"
        schema: ${file(models/PutDocumentResponse.json)}
      - name: "PutDocumentRequest"
        description: "PUT Document request model (inline example)"
        contentType: "application/json"
        schema:
          $schema: "http://json-schema.org/draft-04/schema#"
          properties:
            SomeObject:
              type: "object"
              properties:
                SomeAttribute:
                  type: "string"

Functions

To define the documentation for a given function event, you need to create a documentation attribute for your http event in your serverless.yml file.

The documentation section of the event configuration can contain the following attributes:

  • summary: a short description of the method
  • description: a detailed description of the method
  • tags: an array of tags for this event
  • deprecated: boolean indicator that indicates clients should migrate away from this function
  • requestBody: contains description of the request
    • description: a description of the request body
  • requestModels: a list of models to describe the request bodies (see requestModels below)
  • queryParams: a list of query parameters (see queryParams below)
  • pathParams: a list of path parameters (see pathParams below)
  • cookieParams: a list of cookie parameters (see cookieParams below)
  • methodResponses: an array of response models and applicable status codes
    • statusCode: applicable http status code (ie. 200/404/500 etc.)
    • responseBody: contains description of the response
      • description: a description of the body response
    • responseHeaders: a list of response headers (see responseHeaders below)
    • responseModels: a list of models to describe the request bodies (see responseModels below) for each Content-Type
functions:
  createUser:
    handler: "handler.create"
    events:
      - http:
        path: "create"
        method: "post"
        documentation:
          summary: "Create User"
          description: "Creates a user and then sends a generated password email"
          requestBody:
            description: "A user information object"
          requestModels:
            application/json: "PutDocumentRequest"
          pathParams:
            - name: "username"
              description: "The username for a user to create"
              schema:
                type: "string"
                pattern: "^[-a-z0-9_]+$"
          queryParams:
            - name: "membershipType"
              description: "The user's Membership Type"
              schema:
                type: "string"
                enum:
                  - "premium"
                  - "standard"
          cookieParams:
            - name: "SessionId"
              description: "A Session ID variable"
              schema:
                type: "string"
          methodResponses:
            - statusCode: 201
              responseBody:
                description: "A user object along with generated API Keys"
              responseModels:
                application/json: "PutDocumentResponse"
            - statusCode: 500
              responseBody:
                description: "An error message when creating a new user"
              responseModels:
                application/json: "ErrorResponse"

queryParams

Query parameters can be described as follow:

  • name: the name of the query variable
  • description: a description of the query variable
  • required: whether the query parameter is mandatory (boolean)
  • schema: JSON schema (inline or file)
queryParams:
  - name: "filter"
    description: "The filter parameter"
    required: true
    schema:
      type: "string"

pathParams

Path parameters can be described as follow:

  • name: the name of the query variable
  • description: a description of the query variable
  • schema: JSON schema (inline or file)
pathParams:
  - name: "usernameId"
    description: "The usernameId parameter"
    schema:
      type: "string"

cookieParams

Cookie parameters can be described as follow:

  • name: the name of the query variable
  • description: a description of the query variable
  • required: whether the query parameter is mandatory (boolean)
  • schema: JSON schema (inline or file)
cookieParams:
  - name: "sessionId"
    description: "The sessionId parameter"
    required: true
    schema:
      type: "string"

requestModels

The requestModels property allows you to define models for the HTTP Request of the function event. You can define a different model for each different Content-Type. You can define a reference to the relevant request model named in the models section of your configuration (see Defining Models section).

requestModels:
  application/json: "CreateRequest"
  application/xml: "CreateRequestXML"

methodResponses

You can define the response schemas by defining properties for your function event.

For an example of a methodResponses configuration for an event see below:

methodResponse:
  - statusCode: 200
    responseHeaders:
      - name: "Content-Type"
        description: "Content Type header"
        schema:
          type: "string"
    responseModels:
      application/json: "CreateResponse"
      application/xml: "CreateResponseXML"

responseModels

The responseModels property allows you to define models for the HTTP Response of the function event. You can define a different model for each different Content-Type. You can define a reference to the relevant response model named in the models section of your configuration (see Defining Models section).

responseModels:
  application/json: "CreateResponse"
  application/xml: "CreateResponseXML"

responseHeaders and requestHeaders

The responseHeaders/requestHeaders section of the configuration allows you to define the HTTP headers for the function event.

The attributes for a header are as follow:

  • name: the name of the HTTP Header
  • description: a description of the HTTP Header
  • schema: JSON schema (inline or file)
responseHeaders:
  - name: "Content-Type"
    description: "Content Type header"
    schema:
      type: "string"
requestHeaders:
  - name: "Content-Type"
    description: "Content Type header"
    schema:
      type: "string"

Example configuration

Please view the example serverless.yml.

Install

This plugin works for Serverless 1.x and up. Serverless 0.5 is not supported.

To add this plugin to your package.json:

Using npm:

npm install serverless-openapi-documentation --save-dev

Using Yarn:

yarn add serverless-openapi-documentation --dev

Next you need to add the plugin to the plugins section of your serverless.yml file.

plugins:
  - serverless-openapi-documentation

You can confirm the plugin is correctly installed by running:

serverless | grep -i "ServerlessOpenAPIDocumentation"

It should return ServerlessOpenAPIDocumentation as one of the plugins on the list.

Note: Add this plugin after serverless-offline to prevent issues with String.replaceAll being overridden incorrectly.


The configuration is inspired by the format used in serverless-aws-documentation.

Works well with Lincoln OpenAPI Renderer.


Author: Temando
Source Code: https://github.com/temando/serverless-openapi-documentation 
License: MIT license

#serverless #openapi #documentation 

Serverless OpenAPI Documentation Plugin
Rocio  O'Keefe

Rocio O'Keefe

1655837220

Dart OpenAPI Code Generator

Dart OpenAPI Code Generator

openapi_freezed_dio_builder generates client libraries for open api schema yaml files using Freezed and Dio.

This is a build_runner library meant to be included in the dev_dependencies of your project to allow generating of dart source files for client and server stubs for OpenAPI 3.0 schema files (Only yaml is supported right now).

Flutter Screenshot

Usage

  1. Update pubspec.yaml:
 dependencies:
   freezed: any
   json_annotation: ^3.0.1
   openapi_base: any

 dev_dependencies:
   openapi_freezed_dio_builder: any
   json_serializable: ^3.3.0
   build_runner: ^1.10.0
  1. Create your schema file into your lib folder with the extension .openapi.yaml. You can also use a symbolic link.
  2. Optional: Add the base name to your schema
openapi: 3.0.0
info:
  x-dart-name: MyApiName
  1. Run the build_runner:
(flutter) pub run build_runner build --delete-conflicting-outputs
  1. Implement and client. (see below)

Example schema

openapi: 3.0.0
info:
  version: 0.1.0
  title: Example API
  x-dart-name: TestApi

paths:
  /hello/{name}:
    parameters:
      - name: name
        in: path
        required: true
        schema:
          type: string
    get:
      summary: Say Hello World to {name}
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HelloResponse'
components:
  schemas:
    HelloResponse:
      properties:
        message:
          type: string
          description: 'The Hello World greeting ;-)'

Implement Client

Future<void> main() async {
   final client = Api(
      Dio(),
      Uri.parse('https://virtserver.swaggerhub.com/hpoul/Testapi/1.0.0'),
   );
   final blubb = await client.helloNameGet(name: 'Blubb');
   _logger.info('Response: ${blubb.data}');
}
dart run bin/example_client.dart

Try it out

Run in openapi_dart/packages/openapi_freezed_dio_builder/example

Special thanks

This is a fork of openapi_dart - thank you @hpoul for the great work!

Check out my other packages

Installing

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add openapi_freezed_dio_builder

With Flutter:

 $ flutter pub add openapi_freezed_dio_builder

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  openapi_freezed_dio_builder: ^0.9.3

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:openapi_freezed_dio_builder/openapi_freezed_dio_builder.dart';

example/README.md

This example contains example open api specs and their respective generated code.

They can be found at https://github.com/jonasbark/openapi_freezed_dio_builder/tree/master/packages/openapi_freezed_dio_builder/example

  • testapi.openapi.yaml: A very minimal Hello World example
  • petstore.openapi.yaml: The pet store example provided by he open api spec.

See directory for an example usage.

You can also try out: the code generator right inside your browser: https://jonasbark.github.io/openapi_freezed_dio_builder/


Author: jonasbark
Source Code: https://github.com/jonasbark/openapi_freezed_dio_builder 
License: MIT

#flutter #dart #openapi 

Dart OpenAPI Code Generator
Nigel  Uys

Nigel Uys

1654846620

Terraform Provider OpenAPI

Terraform Provider OpenAPI 

This terraform provider aims to minimise as much as possible the efforts needed from service providers to create and maintain custom terraform providers. This provider uses terraform as the engine that will orchestrate and manage the cycle of the resources and depends on a swagger file (hosted on a remote endpoint) to successfully configure itself dynamically at runtime.

What are the main pain points that this terraform provider tries to tackle?

  • As as service provider, you can focus on improving the service itself rather than the tooling around it.
  • Due to the dynamic nature of this terraform provider, the service provider can continue expanding the functionality of the different APIs by introducing new versions, and this terraform provider will be able to discover the new resource versions automatically without the need to add support for those as you would when mantining your own custom Terraform provider.
  • Find consistency across APIs provided by different teams encouraging the adoption of OpenAPI specification for describing, producing, consuming, and visualizing RESTful Web services.

Overview

API terraform provider is a powerful full-fledged terraform provider that is able to configure itself at runtime based on a Swagger specification file containing the definitions of the APIs exposed. The dynamic nature of this provider is what makes it very flexible and convenient for service providers as subsequent upgrades to their APIs will not require new compilations of this provider. The service provider APIs are discovered on the fly and therefore the service providers can focus on their services rather than the tooling around it.

Pre-requirements

  • The service provider hosts APIs documented using OpenApi 2.0 specification and the APIs comply with the OpenAPI Terraform Provider How to guidelines. The service provider API's OpenAPI document must also be available via a discovery endpoint served through HTTP/s or the file system.

Requirements

How to use Terraform Provider OpenAPI

Things to know regarding custom terraform providers

  • Terraform expects third party (in-house) providers to be manually installed in a specific directory. Refer to the OpenAPI Terraform provider installation instructions to learn more about this.
  • Terraform expects terraform provider names to follow a specific naming scheme. The naming scheme for plugins is terraform-<type>-<name>_vX.Y.Z, where <type> is either provider or provisioner, <name> is the provider's name and X.Y.Z is the version of the plugin.

More information about how terraform discovers third party terraform providers and naming conventions here.

OpenAPI Terraform provider installation

There are multiple ways how the OpenAPI Terraform provider can be installed. Please refer to the OpenAPI Terraform provider installation document to learn more about it.

OpenAPI Terraform provider in action

After having provisioned your environment with the OpenAPI Terraform provider you can now write Terraform configuration files using resources provided by the OpenAPI service. Refer to Using the OpenAPI Terraform Provider doc for more details.

Terraform provider documentation

You can generate the Terraform documentation automatically given an already Terraform compatible OpenAPI document using the The OpenAPI Terraform Documentation Renderer library. The OpenAPI document is the source of truth for both the OpenAPI Terraform provider as well as the user facing documentation.

How to publish the provider in the Terraform Registry

The Publishing OpenAPI Terraform providers in the Terraform Registry document describes how service providers can make use of the OpenAPI Terraform provider library to create their own Terraform provider and register it in the Terraform Registry.

References

Additionally, the following documents provide deep insight regarding OpenAPI and Terraform as well as frequently asked questions:

  • How to document contains information about how to define a OpenAPI document following good practises that make it work seamlessly with this terraform provider. Additionally, learn more about what is currently supported.
  • Migrating to Terraform 0.12. This document describes how to update configuration created using Terraform v0.11 to v0.12.
  • FAQ document answers for the most frequently asked questions.

Contributing

Please follow the guidelines from:

References

  • go-swagger: Api terraform provider makes extensive use of this library which offers a very convenient implementation to serialize and deserialize swagger specifications.
  • JsonPath: Json path is used in the plugin external configuration file to define values for provider schema properties that are coming from external files.
Powered by https://www.terraform.ioFollowing The OpenAPI Specification

Author: dikhan
Source Code: https://github.com/dikhan/terraform-provider-openapi
License: Apache-2.0 license

#go #golang #terraform #openapi 

Terraform Provider OpenAPI

Jest Matchers for Asserting That HTTP Responses Satisfy OpenAPI Spec

jest-openapi

Additional Jest matchers for asserting that HTTP responses satisfy an OpenAPI spec.

Problem πŸ˜•

If your server's behaviour doesn't match your API documentation, then you need to correct your server, your documentation, or both. The sooner you know the better.

Solution πŸ˜„

This plugin lets you automatically test whether your server's behaviour and documentation match. It adds Jest matchers that support the OpenAPI standard for documenting REST APIs. In your JavaScript tests, you can simply assert expect(responseObject).toSatisfyApiSpec()

Features:

  • Validates the status and body of HTTP responses against your OpenAPI spec (see example)
  • Validates objects against schemas defined in your OpenAPI spec (see example)
  • Load your OpenAPI spec just once in your tests (load from a filepath or object)
  • Supports OpenAPI 2 and 3
  • Supports OpenAPI specs in YAML and JSON formats
  • Supports $ref in response definitions (i.e. $ref: '#/definitions/ComponentType/ComponentName')
  • Informs you if your OpenAPI spec is invalid
  • Supports responses from axios, request-promise, supertest, superagent, and chai-http
  • Use in Jest, or use our sister package for Mocha and other test runners that support Chai

Installation

npm

npm install --save-dev jest-openapi

yarn

yarn add --dev jest-openapi

Importing

ES6 / TypeScript

import jestOpenAPI from 'jest-openapi';

CommonJS / JavaScript

const jestOpenAPI = require('jest-openapi').default;

Usage

In API tests, validate the status and body of HTTP responses against your OpenAPI spec:

1. Write a test:

// Import this plugin
import jestOpenAPI from 'jest-openapi';

// Load an OpenAPI file (YAML or JSON) into this plugin
jestOpenAPI('path/to/openapi.yml');

// Write your test
describe('GET /example/endpoint', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server (e.g. using axios)
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).toEqual(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).toSatisfyApiSpec();
  });
});

2. Write an OpenAPI Spec (and save to path/to/openapi.yml):

openapi: 3.0.0
info:
  title: Example API
  version: 1.0.0
paths:
  /example:
    get:
      responses:
        200:
          description: Response body should be an object with fields 'stringProperty' and 'integerProperty'
          content:
            application/json:
              schema:
                type: object
                required:
                  - stringProperty
                  - integerProperty
                properties:
                  stringProperty:
                    type: string
                  integerProperty:
                    type: integer

3. Run your test to validate your server's response against your OpenAPI spec:

The assertion passes if the response status and body satisfy openapi.yml:

// Response includes:
{
  status: 200,
  body: {
    stringProperty: 'string',
    integerProperty: 123,
  },
};

The assertion fails if the response body is invalid:

// Response includes:
{
  status: 200,
  body: {
    stringProperty: 'string',
    integerProperty: 'invalid (should be an integer)',
  },
};

Output from test failure:

expect(received).toSatisfyApiSpec() // Matches 'received' to a response defined in your API spec, then validates 'received' against it

expected received to satisfy the '200' response defined for endpoint 'GET /example/endpoint' in your API spec
received did not satisfy it because: integerProperty should be integer

received contained: {
  body: {
      stringProperty: 'string',
      integerProperty: 'invalid (should be an integer)'
    }
  }
}

The '200' response defined for endpoint 'GET /example/endpoint' in API spec: {
  '200': {
    description: 'Response body should be a string',
    content: {
      'application/json': {
        schema: {
          type: 'string'
        }
      }
    }
  },
}

In unit tests, validate objects against schemas defined in your OpenAPI spec:

1. Write a test:

// Import this plugin and the function you want to test
import jestOpenAPI from 'jest-openapi';
import { functionToTest } from 'path/to/your/code';

// Load an OpenAPI file (YAML or JSON) into this plugin
jestOpenAPI('path/to/openapi.yml');

// Write your test
describe('functionToTest()', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Assert that the function returns a value satisfying a schema defined in your OpenAPI spec
    expect(functionToTest()).toSatisfySchemaInApiSpec('ExampleSchemaObject');
  });
});

2. Write an OpenAPI Spec (and save to path/to/openapi.yml):

openapi: 3.0.0
info:
  title: Example API
  version: 1.0.0
paths:
  /example:
    get:
      responses:
        200:
          description: Response body should be an ExampleSchemaObject
          content:
            application/json:
              schema: 
                $ref: '#/components/schemas/ExampleSchemaObject'
components:
  schemas:
    ExampleSchemaObject:
      type: object
      required:
        - stringProperty
        - integerProperty
      properties:
        stringProperty:
          type: string
        integerProperty:
          type: integer

3. Run your test to validate your object against your OpenAPI spec:

The assertion passes if the object satisfies the schema ExampleSchemaObject:

// object includes:
{
  stringProperty: 'string',
  integerProperty: 123,
};

The assertion fails if the object does not satisfy the schema ExampleSchemaObject:

// object includes:
{
  stringProperty: 123,
  integerProperty: 123,
};

Output from test failure:

expect(received).not.toSatisfySchemaInApiSpec(schemaName) // Matches 'received' to a schema defined in your API spec, then validates 'received' against it

expected received to satisfy the 'StringSchema' schema defined in your API spec
object did not satisfy it because: stringProperty should be string

object was: {
    {
      stringProperty: 123,
      integerProperty: 123
    }
  }
}

The 'ExampleSchemaObject' schema in API spec: {
  type: 'object',
  required: [
    'stringProperty'
    'integerProperty'
  ],
  properties: {
    stringProperty: {
      type: 'string'
    },
    integerProperty: {
      type: 'integer'
    }
  }
}

Loading your OpenAPI spec (3 different ways):

1. From an absolute filepath (see above)

2. From an object:

// Import this plugin
import jestOpenAPI from 'jest-openapi';

// Get an object representing your OpenAPI spec
const openApiSpec = {
  openapi: '3.0.0',
  info: {
    title: 'Example API',
    version: '0.1.0',
  },
  paths: {
    '/example/endpoint': {
      get: {
        responses: {
          200: {
            description: 'Response body should be a string',
            content: {
              'application/json': {
                schema: {
                  type: 'string',
                },
              },
            },
          },
        },
      },
    },
  },
};

// Load that OpenAPI object into this plugin
jestOpenAPI(openApiSpec);

// Write your test
describe('GET /example/endpoint', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server (e.g. using axios)
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).toEqual(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).toSatisfyApiSpec();
  });
});

3. From a web endpoint:

// Import this plugin and an HTTP client (e.g. axios)
import jestOpenAPI from 'jest-openapi';
import axios from 'axios';

// Write your test
describe('GET /example/endpoint', () => {
  // Load your OpenAPI spec from a web endpoint
  beforeAll(async () => {
    const response = await axios.get('url/to/openapi/spec');
    const openApiSpec = response.data; // e.g. { openapi: '3.0.0', ... };
    jestOpenAPI(openApiSpec);
  });

  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).toEqual(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).toSatisfyApiSpec();
  });
});

Contributing ✨

If you've come here to help contribute - thanks! Take a look at the contributing docs to get started.

Author: Openapi-library
Source Code: https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi 
License: MIT license

#javascript #jest #http #openapi 

Jest Matchers for Asserting That HTTP Responses Satisfy OpenAPI Spec
Nigel  Uys

Nigel Uys

1652863500

Feishu/Lark Open API Go Sdk, Support ALL Open API & Event Callback

lark       

Feishu/Lark Open API Go Sdk, Support ALL Open API and Event Callback.

Supported Features

  • Many APIs and events
  • Support mock to support test
  • Support isv and self-built apps
  • Support Logger interface
  • Support UserAccessToken
  • Use code generation to create, api and document update timely

Install

go get github.com/chyroc/lark

Support APIs

API Count: 616, Event Count: 90

Click This to See ALL

  • Auth
    • ResendAppTicket
    • GetAccessToken
    • RefreshAccessToken
    • GetUserInfo
  • Contact
    • SearchUserOld
    • CreateUser
    • DeleteUser
    • GetUser
    • GetUserList
    • GetUserListOld
    • BatchGetUser
    • UpdateUserPatch
    • UpdateUser
    • BatchGetUserByID
    • BatchGetUserByIDOld
    • CreateDepartment
    • GetDepartment
    • GetDepartmentList
    • GetDepartmentListOld
    • GetParentDepartment
    • SearchDepartment
    • UpdateDepartmentPatch
    • UpdateDepartment
    • DeleteDepartment
    • UnbindDepartmentChat
    • CreateContactGroup
    • UpdateContactGroup
    • DeleteContactGroup
    • GetContactGroup
    • GetContactGroupList
    • AddContactGroupMember
    • DeleteContactGroupMember
    • GetContactGroupMember
    • GetEmployeeTypeEnumList
    • UpdateEmployeeTypeEnumPatch
    • DeleteEmployeeTypeEnum
    • CreateEmployeeTypeEnum
    • GetContactCustomAttrList
    • CreateContactUnit
    • UpdateContactUnit
    • DeleteContactUnit
    • GetContactUnit
    • GetContactUnitList
    • BindContactUnitDepartment
    • UnbindContactUnitDepartment
    • GetContactUnitDepartmentList
    • GetContactScopeList
  • Message
    • SendEphemeralMessage
    • SendUrgentAppMessage
    • SendUrgentSmsMessage
    • SendUrgentPhoneMessage
    • SendRawMessage
    • SendRawMessageOld
    • BatchSendOldRawMessage
    • ReplyRawMessage
    • DeleteMessage
    • BatchDeleteMessage
    • UpdateMessage
    • UpdateMessageDelay
    • GetMessageReadUserList
    • GetBatchSentMessageReadUser
    • GetBatchSentMessageProgress
    • GetMessageList
    • GetMessageFile
    • GetMessage
    • DeleteEphemeralMessage
    • CreateMessageReaction
    • GetMessageReactionList
    • DeleteMessageReaction
  • Chat
    • CreateChat
    • GetChat
    • GetChatOld
    • UpdateChat
    • DeleteChat
    • GetChatListOfSelf
    • SearchChat
    • GetChatMemberList
    • IsInChat
    • CreateChatManager
    • DeleteChatManager
    • AddChatMember
    • DeleteChatMember
    • JoinChat
    • GetChatAnnouncement
    • UpdateChatAnnouncement
    • GetChatModeration
    • UpdateChatModeration
  • Bot
    • GetBotInfo
    • AddBotToChat
  • Calendar
    • CreateCalendarACL
    • DeleteCalendarACL
    • GetCalendarACLList
    • SubscribeCalendarACL
    • GetPrimaryCalendar
    • CreateCalendar
    • DeleteCalendar
    • GetCalendar
    • GetCalendarList
    • UpdateCalendar
    • SearchCalendar
    • SubscribeCalendar
    • UnsubscribeCalendar
    • SubscribeCalendarChangeEvent
    • CreateCalendarEvent
    • DeleteCalendarEvent
    • GetCalendarEvent
    • GetCalendarEventList
    • UpdateCalendarEvent
    • SearchCalendarEvent
    • SubscribeCalendarEvent
    • CreateCalendarEventAttendee
    • GetCalendarEventAttendeeList
    • DeleteCalendarEventAttendee
    • GetCalendarEventAttendeeChatMemberList
    • GetCalendarFreeBusyList
    • CreateCalendarTimeoffEvent
    • DeleteCalendarTimeoffEvent
    • GenerateCaldavConf
    • CreateCalendarExchangeBinding
    • GetCalendarExchangeBinding
    • DeleteCalendarExchangeBinding
  • Drive
    • SubscribeDriveFile
    • SearchDriveFile
    • GetDriveFileMeta
    • CreateDriveFile
    • DeleteDriveFile
    • DeleteDriveSheetFile
    • GetDriveFolderMeta
    • GetDriveRootFolderMeta
    • GetDriveFolderChildren
    • GetDriveFileStatistics
    • DownloadDriveFile
    • CopyDriveFile
    • CreateDriveFolder
    • MoveDriveFile
    • UploadDriveFile
    • PrepareUploadDriveFile
    • PartUploadDriveFile
    • FinishUploadDriveFile
    • DownloadDriveMedia
    • UploadDriveMedia
    • PrepareUploadDriveMedia
    • PartUploadDriveMedia
    • FinishUploadDriveMedia
    • CreateDriveMemberPermissionOld
    • TransferDriveMemberPermission
    • GetDriveMemberPermissionList
    • CreateDriveMemberPermission
    • DeleteDriveMemberPermission
    • DeleteDriveMemberPermissionOld
    • UpdateDriveMemberPermissionOld
    • UpdateDriveMemberPermission
    • CheckDriveMemberPermission
    • UpdateDrivePublicPermissionV1Old
    • UpdateDrivePublicPermissionV2Old
    • GetDrivePublicPermissionV2
    • GetDrivePublicPermission
    • UpdateDrivePublicPermission
    • BatchGetDriveMediaTmpDownloadURL
    • GetDriveCommentList
    • GetDriveComment
    • CreateDriveComment
    • UpdateDriveComment
    • DeleteDriveComment
    • UpdateDriveCommentPatch
    • CreateDriveFileSubscription
    • GetDriveFileSubscription
    • UpdateDriveFileSubscription
    • CreateDriveDoc
    • GetDriveDocContent
    • GetDriveDocRawContent
    • GetDriveDocMeta
    • CreateSheet
    • GetSheetMeta
    • UpdateSheetProperty
    • BatchUpdateSheet
    • ImportSheet
    • CreateDriveImportTask
    • GetDriveImportTask
    • MoveSheetDimension
    • PrependSheetValue
    • AppendSheetValue
    • InsertSheetDimensionRange
    • AddSheetDimensionRange
    • UpdateSheetDimensionRange
    • DeleteSheetDimensionRange
    • GetSheetValue
    • BatchGetSheetValue
    • SetSheetValue
    • BatchSetSheetValue
    • SetSheetStyle
    • BatchSetSheetStyle
    • MergeSheetCell
    • UnmergeSheetCell
    • SetSheetValueImage
    • FindSheet
    • ReplaceSheet
    • CreateSheetConditionFormat
    • GetSheetConditionFormat
    • UpdateSheetConditionFormat
    • DeleteSheetConditionFormat
    • CreateSheetProtectedDimension
    • GetSheetProtectedDimension
    • UpdateSheetProtectedDimension
    • DeleteSheetProtectedDimension
    • CreateSheetDataValidationDropdown
    • DeleteSheetDataValidationDropdown
    • UpdateSheetDataValidationDropdown
    • GetSheetDataValidationDropdown
    • CreateSheetFilter
    • DeleteSheetFilter
    • UpdateSheetFilter
    • GetSheetFilter
    • CreateSheetFilterView
    • DeleteSheetFilterView
    • UpdateSheetFilterView
    • GetSheetFilterView
    • QuerySheetFilterView
    • CreateSheetFilterViewCondition
    • DeleteSheetFilterViewCondition
    • UpdateSheetFilterViewCondition
    • GetSheetFilterViewCondition
    • QuerySheetFilterViewCondition
    • CreateSheetFloatImage
    • DeleteSheetFloatImage
    • UpdateSheetFloatImage
    • GetSheetFloatImage
    • QuerySheetFloatImage
    • CreateWikiSpace
    • GetWikiSpaceList
    • GetWikiSpace
    • UpdateWikiSpaceSetting
    • DeleteWikiSpaceMember
    • AddWikiSpaceMember
    • CreateWikiNode
    • GetWikiNodeList
    • MoveWikiNode
    • GetWikiNode
    • MoveDocsToWiki
    • GetWikiTask
  • Bitable
    • GetBitableViewList
    • CreateBitableView
    • DeleteBitableView
    • GetBitableRecordList
    • GetBitableRecord
    • CreateBitableRecord
    • BatchCreateBitableRecord
    • UpdateBitableRecord
    • BatchUpdateBitableRecord
    • DeleteBitableRecord
    • BatchDeleteBitableRecord
    • GetBitableFieldList
    • CreateBitableField
    • UpdateBitableField
    • DeleteBitableField
    • GetBitableTableList
    • CreateBitableTable
    • BatchCreateBitableTable
    • DeleteBitableTable
    • BatchDeleteBitableTable
    • UpdateBitableMeta
    • GetBitableMeta
  • MeetingRoom
    • GetMeetingRoomCustomization
    • BatchGetMeetingRoomSummary
    • GetMeetingRoomBuildingList
    • BatchGetMeetingRoomBuilding
    • GetMeetingRoomRoomList
    • BatchGetMeetingRoomRoom
    • BatchGetMeetingRoomFreebusy
    • ReplyMeetingRoomInstance
    • CreateMeetingRoomBuilding
    • UpdateMeetingRoomBuilding
    • DeleteMeetingRoomBuilding
    • BatchGetMeetingRoomBuildingID
    • CreateMeetingRoomRoom
    • UpdateMeetingRoomRoom
    • DeleteMeetingRoomRoom
    • BatchGetMeetingRoomRoomID
    • GetMeetingRoomCountryList
    • GetMeetingRoomDistrictList
  • Jssdk
    • GetJssdkTicket
  • VC
    • ApplyVCReserve
    • UpdateVCReserve
    • DeleteVCReserve
    • GetVCReserve
    • GetVCReserveActiveMeeting
    • GetVCMeeting
    • ListVCMeetingByNo
    • InviteVCMeeting
    • KickoutVCMeeting
    • SetVCHostMeeting
    • EndVCMeeting
    • StartVCMeetingRecording
    • StopVCMeetingRecording
    • GetVCMeetingRecording
    • SetVCPermissionMeetingRecording
    • GetVCDailyReport
    • GetVCTopUserReport
    • GetVCRoomConfig
    • SetVCRoomConfig
  • Application
    • IsApplicationUserAdmin
    • GetApplicationUserAdminScope
    • GetApplicationAppVisibility
    • GetApplicationUserVisibleApp
    • GetApplicationAppList
    • UpdateApplicationAppVisibility
    • GetApplicationAppAdminUserList
    • CheckUserIsInApplicationPaidScope
    • GetApplicationOrderList
    • GetApplicationOrder
    • GetApplicationUnderAuditList
    • GetApplication
    • GetApplicationVersion
    • UpdateApplicationVersion
    • UpdateApplication
    • GetApplicationUsageOverview
    • GetApplicationUsageTrend
    • UpdateApplicationFeedback
    • GetApplicationFeedbackList
  • Mail
    • GetMailUser
    • CreateMailGroup
    • GetMailGroup
    • GetMailGroupList
    • UpdateMailGroupPatch
    • UpdateMailGroup
    • DeleteMailGroup
    • CreateMailGroupMember
    • GetMailGroupMember
    • GetMailGroupMemberList
    • DeleteMailGroupMember
    • CreateMailGroupPermissionMember
    • GetMailGroupPermissionMember
    • GetMailGroupPermissionMemberList
    • DeleteMailGroupPermissionMember
    • CreateMailGroupAlias
    • GetMailGroupAliasList
    • DeleteMailGroupAlias
    • CreatePublicMailbox
    • GetPublicMailbox
    • GetPublicMailboxList
    • UpdatePublicMailboxPatch
    • UpdatePublicMailbox
    • DeletePublicMailbox
    • CreatePublicMailboxMember
    • GetPublicMailboxMember
    • GetPublicMailboxMemberList
    • DeletePublicMailboxMember
    • ClearPublicMailboxMember
    • CreateMailPublicMailboxAlias
    • GetMailPublicMailboxAliasList
    • DeleteMailPublicMailboxAlias
    • CreateMailUserMailboxAlias
    • DeleteMailUserMailboxAlias
    • GetMailUserMailboxAliasList
    • DeleteMailUserMailbox
  • Approval
    • GetApproval
    • GetApprovalInstanceList
    • GetApprovalInstance
    • CreateApprovalInstance
    • ApproveApprovalInstance
    • RejectApprovalInstance
    • TransferApprovalInstance
    • RollbackApprovalInstance
    • CancelApprovalInstance
    • SearchApprovalInstance
    • AddApprovalInstanceSign
    • UploadApprovalFile
    • SearchApprovalTask
    • GetApprovalUserTaskList
    • SearchApprovalCarbonCopy
    • CreateApprovalCarbonCopy
    • PreviewApprovalInstance
    • UpdateApprovalMessage
    • SubscribeApprovalSubscription
    • UnsubscribeApprovalSubscription
  • Helpdesk
    • CreateHelpdeskNotification
    • UpdateHelpdeskNotification
    • GetHelpdeskNotification
    • PreviewHelpdeskNotification
    • SubmitApproveHelpdeskNotification
    • CancelApproveHelpdeskNotification
    • ExecuteSendHelpdeskNotification
    • CancelSendHelpdeskNotification
    • StartHelpdeskService
    • GetHelpdeskTicket
    • UpdateHelpdeskTicket
    • GetHelpdeskTicketList
    • DownloadHelpdeskTicketImage
    • AnswerHelpdeskTicketUserQuery
    • GetHelpdeskTicketCustomizedFields
    • GetHelpdeskTicketMessageList
    • SendHelpdeskTicketMessage
    • SendHelpdeskMessage
    • GetHelpdeskTicketCustomizedFieldList
    • DeleteHelpdeskTicketCustomizedField
    • UpdateHelpdeskTicketCustomizedField
    • CreateHelpdeskTicketCustomizedField
    • GetHelpdeskTicketCustomizedField
    • CreateHelpdeskCategory
    • GetHelpdeskCategory
    • UpdateHelpdeskCategory
    • DeleteHelpdeskCategory
    • GetHelpdeskCategoryList
    • CreateHelpdeskFAQ
    • GetHelpdeskFAQ
    • UpdateHelpdeskFAQ
    • DeleteHelpdeskFAQ
    • GetHelpdeskFAQList
    • GetHelpdeskFAQImage
    • SearchHelpdeskFAQ
    • UpdateHelpdeskAgent
    • GetHelpdeskAgentEmail
    • CreateHelpdeskAgentSchedule
    • DeleteHelpdeskAgentSchedule
    • UpdateHelpdeskAgentSchedule
    • GetHelpdeskAgentSchedule
    • GetHelpdeskAgentScheduleList
    • CreateHelpdeskAgentSkill
    • GetHelpdeskAgentSkill
    • UpdateHelpdeskAgentSkill
    • DeleteHelpdeskAgentSkill
    • GetHelpdeskAgentSkillList
    • GetHelpdeskAgentSkillRuleList
    • SubscribeHelpdeskEvent
    • UnsubscribeHelpdeskEvent
  • Admin
    • GetAdminDeptStats
    • GetAdminUserStats
  • HumanAuth
    • GetFaceVerifyAuthResult
    • UploadFaceVerifyImage
    • CropFaceVerifyImage
    • CreateIdentity
  • AI
    • RecognizeBasicImage
    • RecognizeSpeechStream
    • RecognizeSpeechFile
    • TranslateText
    • DetectTextLanguage
    • DetectFaceAttributes
  • Attendance
    • CreateAttendanceGroup
    • SearchAttendanceGroup
    • GetAttendanceGroup
    • DeleteAttendanceGroup
    • GetAttendanceShift
    • GetAttendanceShiftDetail
    • DeleteAttendanceShift
    • CreateAttendanceShift
    • GetAttendanceUserDailyShift
    • BatchCreateAttendanceUserDailyShift
    • GetAttendanceUserStatsField
    • GetAttendanceUserStatsView
    • UpdateAttendanceUserStatsView
    • GetAttendanceUserStatsData
    • BatchGetAttendanceUserFlow
    • GetAttendanceUserFlow
    • GetAttendanceUserTask
    • BatchCreateAttendanceUserFlow
    • GetAttendanceUserTaskRemedyAllowedRemedyList
    • GetAttendanceUserTaskRemedy
    • CreateAttendanceUserTaskRemedy
    • GetAttendanceUserSettingList
    • UpdateAttendanceUserSetting
    • DownloadAttendanceFile
    • UploadAttendanceFile
    • GetAttendanceUserApproval
    • CreateAttendanceUserApproval
    • UpdateAttendanceRemedyApproval
  • File
    • UploadImage
    • DownloadImage
    • UploadFile
    • DownloadFile
  • OKR
    • GetOKRPeriodList
    • BatchGetOKR
    • GetUserOKRList
  • EHR
    • GetEHREmployeeList
    • DownloadEHRAttachments
  • Tenant
    • GetTenant
  • Search
    • CreateSearchDataSourceItem
    • GetSearchDataSourceItem
    • DeleteSearchDataSourceItem
    • CreateSearchDataSource
    • GetSearchDataSource
    • UpdateSearchDataSource
    • GetSearchDataSourceList
    • DeleteSearchDataSource
  • Hire
    • GetHireJob
    • GetHireJobManager
    • GetHireTalent
    • GetHireAttachment
    • GetHireAttachmentPreview
    • GetHireResumeSource
    • CreateHireNote
    • UpdateHireNote
    • GetHireNote
    • GetHireNoteList
    • GetHireReferralByApplication
    • GetHireJobProcessList
    • CreateHireApplication
    • TerminateHireApplication
    • GetHireApplication
    • GetHireApplicationList
    • GetHireApplicationInterviewList
    • GetHireOfferByApplication
    • GetHireOfferSchema
    • MakeHireTransferOnboardByApplication
    • UpdateHireEmployee
    • GetHireEmployeeByApplication
    • GetHireEmployee
  • Task
    • CreateTaskCollaborator
    • GetTaskCollaboratorList
    • DeleteTaskCollaborator
    • CreateTaskFollower
    • GetTaskFollowerList
    • DeleteTaskFollower
    • CreateTaskReminder
    • GetTaskReminderList
    • DeleteTaskReminder
    • CreateTask
    • GetTask
    • GetTaskList
    • DeleteTask
    • UpdateTask
    • CompleteTask
    • UncompleteTask
    • CreateTaskComment
    • GetTaskComment
    • DeleteTaskComment
    • UpdateTaskComment
  • ACS
    • GetACSAccessRecordPhoto
    • GetACSAccessRecordList
    • GetACSDeviceList
    • GetACSUserFace
    • UpdateACSUserFace
    • GetACSUser
    • UpdateACSUser
    • GetACSUserList
  • Baike
    • CreateBaikeDraft
    • CreateBaikeUpdate
    • GetBaikeEntity
    • GetBaikeEntityList
    • MatchBaikeEntity
    • SearchBaikeEntity
    • HighlightBaikeEntity
  • MDM
    • CreateMDMVendor
    • UpdateMDMVendor
    • GetMDMVendorList
    • GetMDMVendor
    • GetMDMVendorListAll
    • CreateMDMLegalEntity
    • UpdateMDMLegalEntity
    • GetMDMLegalEntityList
    • GetMDMLegalEntity
    • GetMDMLegalEntityListAll
    • CreateMDMInternalOrder
    • UpdateMDMInternalOrder
    • DeleteMDMInternalOrder
    • GetMDMInternalOrder
    • SearchMDMInternalOrder
    • CreateMDMCostCenter
    • UpdateMDMCostCenter
    • DeleteMDMCostCenter
    • GetMDMCostCenter
    • SearchMDMCostCenter
    • CreateMDMDepartmentCostCenterRelationship
    • UpdateMDMDepartmentCostCenterRelationship
    • DeleteMDMDepartmentCostCenterRelationship
    • GetMDMDepartmentCostCenterRelationship
    • SearchMDMDepartmentCostCenterRelationship
    • CreateMDMGlAccount
    • UpdateMDMGlAccount
    • DeleteMDMGlAccount
    • GetMDMDepGlAccount
    • SearchMDMGlAccount
    • CreateMDMCompany
    • UpdateMDMCompany
    • DeleteMDMCompany
    • GetMDMDepCompany
    • SearchMDMCompany
    • CreateMDMGlAccountCompanyRelationship
    • UpdateMDMGlAccountCompanyRelationship
    • DeleteMDMGlAccountCompanyRelationship
    • GetMDMDepGlAccountCompanyRelationship
    • SearchMDMGlAccountCompanyRelationship
    • CreateMDMCompanyBankAccount
    • UpdateMDMCompanyBankAccount
    • DeleteMDMCompanyBankAccount
    • GetMDMDepCompanyBankAccount
    • SearchMDMCompanyBankAccount
    • CreateMDMCompanyAsset
    • UpdateMDMCompanyAsset
    • DeleteMDMCompanyAsset
    • GetMDMDepCompanyAsset
    • SearchMDMCompanyAsset
    • GetMDMConfigList
  • Event
    • GetEventOutboundIpList
  • EventCallback
    • EventV2ApplicationApplicationAppVersionAuditV6
    • EventV2ApplicationApplicationAppVersionPublishApplyV6
    • EventV2ApplicationApplicationAppVersionPublishRevokeV6
    • EventV2ApplicationApplicationCreatedV6
    • EventV2ContactCustomAttrEventUpdatedV3
    • EventV2DriveFileTitleUpdatedV1
    • EventV2DriveFileReadV1
    • EventV2DriveFileEditV1
    • EventV1AppOpen
    • EventV1ShiftApproval
    • EventV1LeaveApprovalV2
    • EventV1OutApproval
    • EventV1WorkApproval
    • EventV2DriveFilePermissionMemberAddedV1
    • EventV2DriveFileTrashedV1
    • EventV2DriveFileDeletedV1
    • EventV2DriveFilePermissionMemberRemovedV1
    • EventV2ApprovalApprovalUpdatedV4
    • EventV1TripApproval
    • EventV1RemedyApproval
    • EventV1ThirdPartyMeetingRoomEventUpdated
    • EventV1ThirdPartyMeetingRoomEventDeleted
    • EventV2MeetingRoomMeetingRoomCreatedV1
    • EventV2MeetingRoomMeetingRoomUpdatedV1
    • EventV2MeetingRoomMeetingRoomStatusChangedV1
    • EventV2MeetingRoomMeetingRoomDeletedV1
    • EventV1ThirdPartyMeetingRoomEventCreated
    • EventV1OrderPaid
    • EventV1AppTicket
    • EventV1AppUninstalled
    • EventV1AppStatusChange
    • EventV2ApplicationApplicationVisibilityAddedV6
    • EventV2ApplicationApplicationFeedbackCreatedV6
    • EventV2ApplicationApplicationFeedbackUpdatedV6
    • EventV2AttendanceUserTaskUpdatedV1
    • EventV2AttendanceUserFlowCreatedV1
    • EventV2AwemeEcosystemAwemeUserBindedAccountV1
    • EventV2TaskTaskUpdateTenantV1
    • EventV2TaskTaskUpdatedV1
    • EventV2TaskTaskCommentUpdatedV1
    • EventV2HelpdeskTicketMessageCreatedV1
    • EventV2HelpdeskTicketCreatedV1
    • EventV2HelpdeskTicketUpdatedV1
    • EventV2HelpdeskNotificationApproveV1
    • EventV2ContactDepartmentCreatedV3
    • EventV2ContactDepartmentDeletedV3
    • EventV2ContactDepartmentUpdatedV3
    • EventV2ContactUserUpdatedV3
    • EventV2ContactUserCreatedV3
    • EventV2ContactUserDeletedV3
    • EventV2ContactScopeUpdatedV3
    • EventV2ContactEmployeeTypeEnumCreatedV3
    • EventV2ContactEmployeeTypeEnumActivedV3
    • EventV2ContactEmployeeTypeEnumDeactivatedV3
    • EventV2ContactEmployeeTypeEnumUpdatedV3
    • EventV2ContactEmployeeTypeEnumDeletedV3
    • EventV2IMMessageReceiveV1
    • EventV2IMMessageReadV1
    • EventV2IMMessageReactionDeletedV1
    • EventV2IMMessageReactionCreatedV1
    • EventV2IMChatDisbandedV1
    • EventV2IMChatUpdatedV1
    • EventV2IMChatMemberBotAddedV1
    • EventV2IMChatMemberBotDeletedV1
    • EventV2IMChatMemberUserAddedV1
    • EventV2IMChatMemberUserWithdrawnV1
    • EventV2IMChatMemberUserDeletedV1
    • EventV2VCMeetingMeetingStartedV1
    • EventV2VCMeetingMeetingEndedV1
    • EventV2VCMeetingJoinMeetingV1
    • EventV2VCMeetingLeaveMeetingV1
    • EventV2VCMeetingRecordingStartedV1
    • EventV2VCMeetingRecordingEndedV1
    • EventV2VCMeetingRecordingReadyV1
    • EventV2VCMeetingShareStartedV1
    • EventV2VCMeetingShareEndedV1
    • EventV2ACSAccessRecordCreatedV1
    • EventV2ACSUserUpdatedV1
    • EventV2CalendarCalendarACLCreatedV4
    • EventV2CalendarCalendarACLDeletedV4
    • EventV2CalendarCalendarEventChangedV4
    • EventV2CalendarCalendarChangedV4
    • EventV1AddBot
    • EventV1RemoveBot
    • EventV1P2PChatCreate
    • EventV1ReceiveMessage
    • EventV1AddUserToChat
    • EventV1RemoveUserFromChat
    • EventV1RevokeAddUserFromChat
    • EventV1ChatDisband
  • AppLink
    • OpenLark
    • OpenMiniProgram
    • OpenWebApp
    • OpenChat
    • OpenCalender
    • OpenCalenderView
    • OpenCalenderEventCreate
    • OpenCalenderAccount
    • OpenDocs
    • OpenBot
    • OpenSSOLogin
    • OpenWebURL
    • OpenTask
    • OpenTaskCreate
    • OpenTaskDetail
    • OpenTaskTab
    • OpenScan

Usage

Example: create lark client

  • for sample bot and app:
cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))
  • processing larksuite (non-China region) request
cli := lark.New(
    lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"),
    lark.WithOpenBaseURL("https://open.larksuite.com"),
    lark.WithWWWBaseURL("https://www.larksuite.com"),
)
  • for need handle event callback:
cli := lark.New(
    lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"),
    lark.WithEventCallbackVerify("<ENCRYPT_KEY>", "<VERIFICATION_TOKEN>"),
)
  • for helpdesk app:
cli := lark.New(
    lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"),
    lark.WithHelpdeskCredential("<HELPDESK_ID>", "HELPDESK_TOKEN"),
)

Example: handle event callback

for more about event callback example, see ./_examples/event_callback.go .

handle message callback example:

cli := lark.New(
    lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"),
    lark.WithEventCallbackVerify("<ENCRYPT_KEY>", "<VERIFICATION_TOKEN>"),
)

// handle message callback
cli.EventCallback.HandlerEventIMMessageReceiveV1(func(ctx context.Context, cli *lark.Lark, schema string, header *lark.EventV2Header, event *lark.EventV2IMMessageReceiveV1) (string, error) {
    _, _, err := cli.Message.Reply(event.Message.MessageID).SendText(ctx, "hi, "+event.Message.Content)
    return "", err
})

http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
    cli.EventCallback.ListenCallback(r.Context(), r.Body, w)
})

fmt.Println("start server ...")
log.Fatal(http.ListenAndServe(":9726", nil))

Example: ISV APP

for more about isv example, see ./_examples/isv.go .

create isv chat:

cli := lark.New(
    lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"),
    lark.WithISV(true),
    lark.WithStore("<NEW_STORE>"),
)

tenantKey1Cli := cli.WithTenant("<TENANT_KEY_1>")
resp, _, err := tenantKey1cli.Chat.CreateChat(ctx, &lark.CreateChatReq{
    Name: ptr.String("<CHAT_NAME_1>"),
})
fmt.Println(resp, err)

Example: get bot info

for more about bot example, see ./_examples/bot.go .

get bot info example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

resp, _, err := cli.Bot.GetBotInfo(ctx, &lark.GetBotInfoReq{})
fmt.Println(resp, err)

Example: send message

for more about send message example, see ./_examples/send_message.go .

send text message example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

resp, _, err := cli.Message.Send().ToChatID("<CHAT_ID>").SendText(ctx, "<TEXT>")
fmt.Println(resp, err)

Example: other message

for more about other message example, see ./_examples/other_message.go .

send delete message example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

resp, _, err := cli.Message.DeleteMessage(ctx, &lark.DeleteMessageReq{
    MessageID: "<MESSAGE_ID>",
})
fmt.Println(resp, err)

Example: chat

for more about chat example, see ./_examples/chat.go .

create chat example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

resp, _, err := cli.Chat.CreateChat(ctx, &lark.CreateChatReq{
    Name: ptr.String("<CHAT_NAME>"),
})
fmt.Println(resp, err)

Example: file

for more about file example, see ./_examples/file.go .

upload image example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

f, err := os.Open("<FILE_PATH>")
if err != nil {
    panic(err)
}
resp, _, err := cli.File.UploadImage(ctx, &lark.UploadImageReq{
    ImageType: lark.ImageTypeMessage,
    Image:     f,
})
fmt.Println(resp, err)

Example: calendar

for more about calendar example, see ./_examples/calendar.go .

create calendar example:

cli := lark.New(lark.WithAppCredential("<APP_ID>", "<APP_SECRET>"))

resp, _, err := cli.Calendar.CreateCalendar(ctx, &lark.CreateCalendarReq{
    Summary: ptr.String("<SUMMARY>"),
})
fmt.Println(resp, err)

Chat

⁣Click Lark Chat Link to discuss.

Docs

https://godoc.org/github.com/chyroc/lark

δΈ­ζ–‡η‰ˆ README

Author: Chyroc
Source Code: https://github.com/chyroc/lark 
License: Apache-2.0 license

#go #golang #bot #openapi 

Feishu/Lark Open API Go Sdk, Support ALL Open API & Event Callback
Best of Crypto

Best of Crypto

1648079400

A General Purpose OpenAPI Code Generator for Algorand

generator

This is a general purpose OpenAPI code generator. It is currently used to completely generate the HTTP code in the Java SDK, and generate some of the HTTP code in our Golang SDK.

Usage

We currently have two HTTP endpoints. One for algod and one for indexer, so in most cases, this tool would be run once with each OpenAPI spec.

Build as a self-executing jar:

~$ mvn package -DskipTests
~$ java -jar target/generator-*-jar-with-dependencies.jar -h

You'll see that there are a number of subcommands:

  • java - the original Java SDK generator.
  • responses - generate randomized test files for SDK unit tests.
  • template - a generator that uses velocity templates rather than Java code to configure the code generation.

Code layout

The command line interface uses JCommander to define the command line interface. See Main.java.

The main code involves an OpenAPI parser / event generator and several listeners for the actual generation.

object layout

Templates

The template subcommand is using Apache Velocity as the underlying template engine. Things like variables, loops, and statements are all supported. So business logic can technically be implemented in the template if it's actually necessary.

Template files

There are three phases: client, query, and model. Each phase must provide two templates, one for the file generation and one to specify the filename to be used. If all results should go to the same file. For query and model generation the template will be executed once for each query / model. If you want to put everything in one file return the same filename twice in a row and the processing will exit early.

phasefilenamepurpose
clientclient.vmClient class with functions to call each query.
clientclient_filename.vmFile to write to the client output directory.
queryquery.vmTemplate to use for generating query files.
queryquery_filename.vmFile to write to the query output directory.
modelmodel.vmTemplate to use for generating model files.
modelmodel_filename.vmFile to write to the model output directory.

Output directories

The template command will only run the templates which have an output directory is provided. So if you just want to regenerate models, only use the -m option.

  -c, --clientOutputDir
    Directory to write client file(s).
  -m, --modelsOutputDir
    Directory to write model file(s).
  -q, --queryOutputDir
    Directory to write query file(s).

Property files

The template subcommand accepts a --propertyFiles option. It can be provided multiple times, or as a comma separated list of files. Property files will be processed and bound to a velocity variable available to templates.

template variables

For details on a type you can put it directly into your template. It will be serialized along with its fields for your reference. Here is a high level description of what is available:

templatevariabletypepurpose
allstrStringHelpers.javaSome string utilities are available. See StringHelpers.java for details. There are simple things like $str.capitalize("someData") -> SomeData, and also some more complex helpers like $str.formatDoc($query.doc, "// ") which will split the document at the word boundary nearest to 80 characters without going over, and add a prefix to each new line.
allorderOrderHelpers.javaSome ordering utilities available. See OrderHelpers.java for details. An example utility function is $order.propertiesWithOrdering($props, $preferred_order), where $props is a list of properties and $preferred_order is a string list to use when ordering the properties list.
allpropFilePropertiesThe contents of all property files are available with this variable. For example if package=com.algorand.v2.algod is in the property file, the template may use ${propFile.package}.
allmodelsHashMap<StructDef, List<TypeDef>>A list of all models.
allqueriesList<QueryDef>A list of all queries.
queryqQueryDefThe current query definition.
modeldefStructDefThe current model definition if multiple files are being generated.
modelpropsList<TypeDef>A list of properties for the current model.

Example usage

In the following example, we are careful to generate the algod code first because the algod models are a strict subset of the indexer models. For that reason, we are able to reuse some overlapping models from indexer in algod.

~$ java -jar generator*jar template
        -s algod.oas2.json
        -t go_templates
        -c algodClient
        -m allModels
        -q algodQueries
        -p common_config.properties,algod_config.properties
~$ java -jar generator*jar template
        -s indexer.oas2.json
        -t go_templates
        -c indexerClient
        -m allModels
        -q indexerQueries
        -p common_config.properties,indexer_config.properties

Test Template

There is a test template that gives you some basic usage in the test_templates directory.

You can generate the test code in the output directory with the following commands:

~$ mkdir output
~$ java -jar target/generator-*-jar-with-dependencies.jar \
    template \
    -s /path/to/a/spec/file/indexer.oas2.json \
    -t test_templates/ \
    -m output \
    -q output \
    -c output \
    -p test_templates/my.properties

Golang Template

The Golang templates are in the go_templates directory.

The Golang HTTP API is only partially generated. The hand written parts were not totally consistent with the spec and that makes it difficult to regenerate them. Regardless, an attempt has been made. In the templates there are some macros which map "generated" values to the hand written ones. For example the query types have this mapping:

#macro ( queryType )
#if ( ${str.capitalize($q.name)} == "SearchForAccounts" )
SearchAccounts## The hand written client doesn't quite match the spec...
#elseif ( ${str.capitalize($q.name)} == "GetStatus" )
Status##
#elseif ( ${str.capitalize($q.name)} == "GetPendingTransactionsByAddress" )
PendingTransactionInformationByAddress##
#elseif ( ${str.capitalize($q.name)} == "GetPendingTransactions" )
PendingTransactions##
#else
${str.capitalize($q.name)}##
#end
#end

Other mappings are more specific to the language, such as the OpenAPI type to SDK type:

#macro ( toQueryType $param )##
#if ( $param.algorandFormat == "RFC3339 String" )
string##
#elseif ( $param.type == "integer" )
uint64##
#elseif ( $param.type == "string" )
string##
#elseif ( $param.type == "boolean" )
bool##
#elseif( $param.type == "binary" )
string##
#else
UNHANDLED TYPE
- ref: $!param.refType
- type: $!param.type
- array type: $!param.arrayType
- algorand format: $!param.algorandFormat
- format: $!param.format
##$unknown.type ## force a template failure because $unknown.type does not exist.
#end
#end

Because of this, we are phasing in code generation gradually by skipping some types. The skipped types are specified in the property files:

common_config.properties

model_skip=AccountParticipation,AssetParams,RawBlockJson,etc,...

algod_config.properties

query_skip=Block,BlockRaw,SendRawTransaction,SuggestedParams,etc,...

indexer_config.properties

query_skip=LookupAssetByID,LookupAccountTransactions,SearchForAssets,LookupAssetBalances,LookupAssetTransactions,LookupBlock,LookupTransactions,SearchForTransactions

Java Template

The Java templates are in the java_templates directory.

These are not used yet, they are the initial experiments for the template engine. Since the Java SDK has used code generation from the beginning, we should be able to fully migrate to the template engine eventually.

Automation

Preparing an external repository for automatic code generation

In general, the automation pipeline will build and run whatever Dockerfile is found in a repository's templates directory. For instructions on how to configure the templates directory, look at the repository template directory example.

If you are trying to verify that automatic code generation works as intended, we recommend creating a testing branch from that repository and using the SKIP_PR=true environment variable to avoid creating pull requests. If all goes according to plan, generated files should be available in the container's /repo directory.

Setting up the automatic generator

The automatic generator scripts depend on certain prerequisites that are listed in automation/REQUIREMENTS.md. Once those conditions have been satisfied, automatically generating code for external repositories should be as easy as building and running a particular SDK's templates/Dockerfile file.


Download Details:
Author: algorand
Source Code: https://github.com/algorand/generator
License:

#algorand  #blockchain  #cryptocurrency #java #golang #openapi 

A General Purpose OpenAPI Code Generator for Algorand
Jarvis  Maggio

Jarvis Maggio

1646809200

Schemathesis: A Modern API Testing tool for Web Applications

Schemathesis

Schemathesis is a modern API testing tool for web applications built with Open API and GraphQL specifications.

It reads the application schema and generates test cases, which will ensure that your application is compliant with its schema (read more about how it works in our research paper).

The application under test could be written in any language; the only thing you need is a valid API schema in a supported format.

Simple to use and yet powerful to uncover hard-to-find errors thanks to the property-based testing approach backed by state-of-the-art Hypothesis library.

Features

  • Content-Type, schema, and status code conformance checks for Open API;
  • Testing of explicit examples from the input schema;
  • Stateful testing via Open API links;
  • Concurrent test execution;
  • Targeted testing;
  • Storing and replaying network requests;
  • Built-in ASGI / WSGI application support;
  • Code samples for easy failure reproduction;
  • Ready-to-go Docker image;
  • Configurable with user-defined checks, string formats, hooks, and targets.

πŸ“£ Schemathesis as a Service πŸ“£

Schemathesis will be available as SaaS soon!

It is freemium with much better visuals for debugging, more checks, and static analysis :)

Signup to get notified when it is ready!

Installation

To install Schemathesis via pip run the following command:

pip install schemathesis

You can also use our Docker image without installing Schemathesis as a Python package.

πŸ“£ Please fill out our quick survey so that we can learn how satisfied you are with Schemathesis, and what improvements we should make. Thank you!

Usage

You can use Schemathesis in the command line directly:

schemathesis run --stateful=links --checks all http://0.0.0.0:8081/schema.yaml

Or via Docker:

docker run schemathesis/schemathesis:stable run \
    --stateful=links --checks all http://0.0.0.0:8081/schema.yaml

https://raw.githubusercontent.com/schemathesis/schemathesis/master/img/schemathesis.gif

Or in your Python tests:

import schemathesis

schema = schemathesis.from_uri("http://0.0.0.0:8081/schema.yaml")


@schema.parametrize()
def test_api(case):
    case.call_and_validate()

CLI is simple to use and requires no coding; the in-code approach gives more flexibility.

Both examples above will run hundreds of requests against the API under test and report all found failures and inconsistencies along with instructions to reproduce them.

πŸ’‘ See a complete working example project in the /example directory. πŸ’‘

Contributing

Any contribution to development, testing, or any other area is highly appreciated and useful to the project. For guidance on how to contribute to Schemathesis, see the contributing guidelines.

Support this project

Hi, my name is Dmitry! I started this project during my work at Kiwi.com. I am grateful to them for all the support they provided to this project during its early days and for the opportunity to evolve Schemathesis independently.

In order to grow the community of contributors and users, and allow me to devote more time to this project, please donate today.

Also, I occasionally write posts about Schemathesis in my blog.

Links

Additional content:

Non-English content:

  • A tutorial (RUS) about Schemathesis by @Stranger6667

License

The code in this project is licensed under MIT license. By contributing to Schemathesis, you agree that your contributions will be licensed under its MIT license.


Author: schemathesis
Source Code: https://github.com/schemathesis/schemathesis
License: MIT License

#graphql #openapi 

Schemathesis: A Modern API Testing tool for Web Applications
Jane  Reid

Jane Reid

1646802000

Prism: Packages for API Mimicking and Contract Testing With OpenAPI V2

Prism is a set of packages for API mocking and contract testing with OpenAPI v2 (formerly known as Swagger) and OpenAPI v3.x.

  • Mock Servers: Life-like mock servers from any API Specification Document.
  • Validation Proxy: Contract Testing for API Consumers and Developers.
  • Comprehensive API Specification Support: OpenAPI v3.1, OpenAPI v3.0, OpenAPI v2.0 (formerly Swagger) and Postman Collections.

Demo of Prism Mock Server being called with curl from the CLI

Note: This branch refers to Prism 3.x, which is the current version most likely you will use. If you're looking for the 2.x version, look at the 2.x branch

Overview

🧰 Installation and Usage

Installation

Prism requires NodeJS >= 12 to properly work.

npm install -g @stoplight/prism-cli

# OR

yarn global add @stoplight/prism-cli

For more installation options, see our installation documentation.

Mocking

Prism can help you create a fake "mock" based off an OpenAPI document, which helps people see how your API will work before you even have it built. Run it locally with the prism mock command to run your API on a HTTP server you can interact with.

prism mock https://raw.githack.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml

Learn more about how the mock server works.

Validation Proxy

Prism can help you check for discrepencies between your API implementation and the OpenAPI document that describes, letting you funnel HTTP traffic through it with the prism proxy command.

prism proxy examples/petstore.oas2.yaml https://petstore.swagger.io/v2

Learn more about how the validation proxy works.

πŸ“– Documentation and Community

🚧 Roadmap

Submit your ideas for new functionality on the Stoplight Roadmap.

❓ FAQs

Cannot access mock server when using Docker?

Prism uses localhost by default, which usually means 127.0.0.1. When using docker the mock server will be unreachable outside of the container unless you run the mock command with -h 0.0.0.0.

Why am I getting 404 errors when I include my basePath?

OpenAPI v2.0 had a concept called "basePath", which was essentially part of the HTTP path the stuff after host name and protocol, and before query string. Unlike the paths in your paths object, this basePath was applied to every single URL, so Prism v2.x used to do the same. In OpenAPI v3.0 they merged the basePath concept in with the server.url, and Prism v3 has done the same.

We treat OAS2 host + basePath the same as OAS3 server.url, so we do not require them to go in the URL. If you have a base path of api/v1 and your path is defined as hello, then a request to http://localhost:4010/hello would work, but http://localhost:4010/api/v1/hello will fail. This confuses some, but the other way was confusing to others. Check the default output of Prism CLI to see what URLs you have available.

Is there a hosted version of Prism?

Yes, hosted mocking is available as part of Stoplight Platform. Learn More

βš™οΈ Integrations

  • Stoplight Studio: Free visual OpenAPI designer that comes integrated with mocking powered by Prism.
  • Stoplight Platform: Collaborative API Design Platform for designing, developing and documenting APIs with hosted mocking powered by Prism.

🏁 Help Others Utilize Prism

If you're using Prism for an interesting use case, contact us for a case study. We'll add it to a list here. Spread the goodness πŸŽ‰

πŸ‘ Contributing

If you are interested in contributing to Prism itself, check out our contributing docs β‡— and code of conduct β‡— to get started.

πŸŽ‰ Thanks

Prism is built on top of lots of excellent packages, and here are a few we'd like to say a special thanks to.

Check these projects out!

🌲 Sponsor Prism by Planting a Tree

If you would like to thank us for creating Prism, we ask that you buy the world a tree.


Author: stoplightio
Source Code: https://github.com/stoplightio/prism
License: Apache-2.0 License

#openapi 

Prism: Packages for API Mimicking and Contract Testing With OpenAPI V2
Ngoc  Anh

Ngoc Anh

1646665200

Pyramid Addon For OpenAPI3 Validation Of Requests and Responses.

Validate Pyramid views against an OpenAPI 3.0 document

Peace of Mind

The reason this package exists is to give you peace of mind when providing a RESTful API. Instead of chasing down preventable bugs and saying sorry to consumers, you can focus on more important things in life.

  • Your API documentation is never out-of-date, since it is generated out of the API document that you write.
  • The documentation comes with try-it-out examples for every endpoint in your API. You don't have to provide (and maintain) curl commands to showcase how your API works. Users can try it themselves, right in their browsers.
  • Your API document is always valid, since your Pyramid app won't even start if the document does not comply with the OpenAPI 3.0 specification.
  • Automatic request payload validation and sanitization. Your views do not require any code for validation and input sanitation. Your view code only deals with business logic. Tons of tests never need to be written since every request, and its payload, is validated against your API document before it reaches your view code.
  • Your API responses always match your API document. Every response from your view is validated against your document and a 500 Internal Server Error is returned if the response does not exactly match what your document says the output of a certain API endpoint should be. This decreases the effects of Hyrum's Law.
  • A single source of truth. Because of the checks outlined above, you can be sure that whatever your API document says is in fact what is going on in reality. You have a single source of truth to consult when asking an API related question, such as "Remind me again, which fields are returned by the endpoint /user/info?".
  • Based on Pyramid, a mature Python Web framework. Companies such as Mozilla, Yelp, RollBar and SurveyMonkey trust Pyramid, and the new pypi.org runs on Pyramid, too. Pyramid is thoroughly tested and documented, providing flexibility, performance, and a large ecosystem of high-quality add-ons.

Building Robust APIs

Features

Getting started

Declare pyramid_openapi3 as a dependency in your Pyramid project.

Include the following lines:

config.include("pyramid_openapi3")
config.pyramid_openapi3_spec('openapi.yaml', route='/api/v1/openapi.yaml')
config.pyramid_openapi3_add_explorer(route='/api/v1/')
  1. Use the openapi view predicate to enable request/response validation:
@view_config(route_name="foobar", openapi=True, renderer='json')
def myview(request):
    return request.openapi_validated.parameters

For requests, request.openapi_validated is available with two fields: parameters and body. For responses, if the payload does not match the API document, an exception is raised.

Advanced configuration

Relative File References in Spec

A feature introduced in OpenAPI3 is the ability to use $ref links to external files (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#referenceObject).

To use this, you must ensure that you have all of your spec files in a given directory (ensure that you do not have any code in this directory as all the files in it are exposed as static files), then replace the pyramid_openapi3_spec call that you did in Getting Started with the following:

config.pyramid_openapi3_spec_directory('path/to/openapi.yaml', route='/api/v1/spec')

Some notes:

  • Do not set the route of your pyramid_openapi3_spec_directory to the same value as the route of pyramid_openapi3_add_explorer.
  • The route that you set for pyramid_openapi3_spec_directory should not contain any file extensions, as this becomes the root for all of the files in your specified filepath.
  • You cannot use pyramid_openapi3_spec_directory and pyramid_openapi3_spec in the same app.

Endpoints / Request / Response Validation

Provided with pyramid_openapi3 are a few validation features:

  • incoming request validation (i.e., what a client sends to your app)
  • outgoing response validation (i.e., what your app sends to a client)
  • endpoint validation (i.e., your app registers routes for all defined API endpoints)

These features are enabled as a default, but you can disable them if you need to:

config.registry.settings["pyramid_openapi3.enable_endpoint_validation"] = False
config.registry.settings["pyramid_openapi3.enable_request_validation"] = False
config.registry.settings["pyramid_openapi3.enable_response_validation"] = False

Warning: Disabling request validation will result in request.openapi_validated no longer being available to use.

Register Pyramid's Routes

You can register routes in your pyramid application. First, write the x-pyramid-route-name extension in the PathItem of the OpenAPI schema.

paths:
  /foo:
    x-pyramid-route-name: foo_route
    get:
      responses:
        200:
          description: GET foo

Then put the config directive pyramid_openapi3_register_routes in the app_factory of your application.

config.pyramid_openapi3_register_routes()

This means is equals to

config.add_route("foo_route", pattern="/foo")

Demo / Examples

There are three examples provided with this package:

Both examples come with tests that exhibit pyramid_openapi's error handling and validation capabilities.

A fully built-out app, with 100% test coverage, providing a RealWorld.io API is available at niteoweb/pyramid-realworld-example-app. It is a Heroku-deployable Pyramid app that provides an API for a Medium.com-like social app. You are encouraged to use it as a scaffold for your next project.

Design defense

The authors of pyramid_openapi3 believe that the approach of validating a manually-written API document is superior to the approach of generating the API document from Python code. Here are the reasons:

Both generation and validation against a document are lossy processes. The underlying libraries running the generation/validation will always have something missing. Either a feature from the latest OpenAPI specification, or an implementation bug. Having to fork the underlying library in order to generate the part of your API document that might only be needed for the frontend is unfortunate.

Validation on the other hand allows one to skip parts of validation that are not supported yet, and not block a team from shipping the document.

The validation approach does sacrifice DRY-ness, and one has to write the API document and then the (view) code in Pyramid. It feels a bit redundant at first. However, this provides a clear separation between the intent and the implementation.

The generation approach has the drawback of having to write Python code even for parts of the API document that the Pyramid backend does not handle, as it might be handled by a different system, or be specific only to documentation or only to the client side of the API. This bloats your Pyramid codebase with code that does not belong there.

Running tests

You need to have pipenv and Python 3.7, 3.8, or 3.9 installed on your machine. Then you can run:

$ make tests

Related packages

These packages tackle the same problem-space:

  • pyramid_oas3 seems to do things very similarly to pyramid_openapi3, but the documentation is not in English and we sadly can't fully understand what it does by just reading the code.
  • pyramid_swagger does a similar thing, but for Swagger 2.0 documents.
  • connexion takes the same "write spec first, code second" approach as pyramid_openapi3, but is based on Flask.
  • bottle-swagger takes the same "write spec first, code second" approach too, but is based on Bottle.
  • pyramid_apispec uses generation with help of apispec and the marshmallow validation library. See above why we prefer validation instead of generation.

Deprecation policy

We do our best to follow the rules below.

  • Support the latest few releases of Python, currently Python 3.7, 3.8, and 3.9.
  • Support the latest few releases of Pyramid, currently 1.10.7 through 2.0.
  • Support the latest few releases of openapi-core, currently 0.13.4 through 0.13.8.
  • See Pipfile.lock for a frozen-in-time known-good-set of all dependencies.

Use in the wild

A couple of projects that use pyramid_openapi3 in production:


Author: Pylons
Source Code: https://github.com/Pylons/pyramid_openapi3
License: MIT License

#python #openapi 

Pyramid Addon For OpenAPI3 Validation Of Requests and Responses.
Ngoc  Anh

Ngoc Anh

1646658000

API Parameter Validator and OpenAPI Document Generator

SpecTree

Yet another library to generate OpenAPI documents and validate requests & responses with Python annotations.

Features

  • Less boilerplate code, only annotations, no need for YAML :sparkles:
  • Generate API document with Redoc UI or Swagger UI :yum:
  • Validate query, JSON data, response data with pydantic :wink:
  • Current support:
    • Flask demo
    • Falcon demo (including ASGI under Falcon 3+)
    • Starlette demo

Quick Start

install with pip: pip install spectree

Examples

Check the examples folder.

Step by Step

  1. Define your data structure used in (query, json, headers, cookies, resp) with pydantic.BaseModel
  2. create spectree.SpecTree instance with the web framework name you are using, like api = SpecTree('flask')
  3. api.validate decorate the route with
    • query
    • json
    • headers
    • cookies
    • resp
    • tags
    • security
  4. access these data with context(query, json, headers, cookies) (of course, you can access these from the original place where the framework offered)
    • flask: request.context
    • falcon: req.context
    • starlette: request.context
  5. register to the web application api.register(app)
  6. check the document at URL location /apidoc/redoc or /apidoc/swagger

If the request doesn't pass the validation, it will return a 422 with a JSON error message(ctx, loc, msg, type).

Falcon response validation

For falcon response, this library only validates against media as it is the serializable object. Response.body(deprecated in falcon 3.0 and replaced by text) is a string representing response content and will not be validated. For no assigned media situation, resp parameter in api.validate should be like Response(HTTP_200=None)

Opt-in type annotation feature

This library also supports the injection of validated fields into view function arguments along with parameter annotation-based type declaration. This works well with linters that can take advantage of typing features like mypy. See the examples section below.

How-To

How to add summary and description to endpoints?

Just add docs to the endpoint function. The 1st line is the summary, and the rest is the description for this endpoint.

How to add a description to parameters?

Check the pydantic document about description in Field.

Any config I can change?

Of course. Check the config document.

You can update the config when init the spectree like:

SpecTree('flask', title='Demo API', version='v1.0', path='doc')

What is Response and how to use it?

To build a response for the endpoint, you need to declare the status code with format HTTP_{code} and corresponding data (optional).

Response(HTTP_200=None, HTTP_403=ForbidModel)
Response('HTTP_200') # equals to Response(HTTP_200=None)
# with custom code description
Response(HTTP_403=(ForbidModel, "custom code description"))

How to secure API endpoints?

For secure API endpoints, it is needed to define the security_schemes argument in the SpecTree constructor. security_schemes argument needs to contain an array of SecurityScheme objects. Then there are two ways to enforce security:

  1. You can enforce security on individual API endpoints by defining the security argument in the api.validate decorator of relevant function/method (this corresponds to define security section on operation level, under paths, in OpenAPI). security argument is defined as a dictionary, where each key is the name of security used in security_schemes argument of SpecTree constructor and its value is required security scope, as is showed in the following example:

Click to expand the code example:

api = SpecTree(security_schemes=[
        SecurityScheme(
            name="auth_apiKey",
            data={"type": "apiKey", "name": "Authorization", "in": "header"},
        ),
        SecurityScheme(
            name="auth_oauth2",
            data={
                "type": "oauth2",
                "flows": {
                    "authorizationCode": {
                        "authorizationUrl": "https://example.com/oauth/authorize",
                        "tokenUrl": "https://example.com/oauth/token",
                        "scopes": {
                            "read": "Grants read access",
                            "write": "Grants write access",
                            "admin": "Grants access to admin operations",
                        },
                    },
                },
            },
        ),
        # ...
    ],
    # ...
)


# Not secured API endpoint
@api.validate(
    resp=Response(HTTP_200=None),
)
def foo():
    ...


# API endpoint secured by API key type or OAuth2 type
@api.validate(
    resp=Response(HTTP_200=None),
    security={"auth_apiKey": [], "auth_oauth2": ["read", "write"]},  # Local security type
)
def bar():
    ...

 

  1. You can enforce security on the whole API by defining the security argument in the SpecTree constructor (this corresponds to the define security section on the root level in OpenAPI). It is possible to override global security by defining local security, as well as override to no security on some API endpoint, in the security argument of api.validate decorator of relevant function/method as was described in the previous point. It is also shown in the following small example:

Click to expand the code example:

api = SpecTree(security_schemes=[
        SecurityScheme(
            name="auth_apiKey",
            data={"type": "apiKey", "name": "Authorization", "in": "header"},
        ),
        SecurityScheme(
            name="auth_oauth2",
            data={
                "type": "oauth2",
                "flows": {
                    "authorizationCode": {
                        "authorizationUrl": "https://example.com/oauth/authorize",
                        "tokenUrl": "https://example.com/oauth/token",
                        "scopes": {
                            "read": "Grants read access",
                            "write": "Grants write access",
                            "admin": "Grants access to admin operations",
                        },
                    },
                },
            },
        ),
        # ...
    ],
    security={"auth_apiKey": []},  # Global security type
    # ...
)

# Force no security
@api.validate(
    resp=Response(HTTP_200=None),
    security={}, # Locally overridden security type
)
def foo():
    ...


# Force another type of security than global one
@api.validate(
    resp=Response(HTTP_200=None),
    security={"auth_oauth2": ["read"]}, # Locally overridden security type
)
def bar():
    ...


# Use the global security
@api.validate(
    resp=Response(HTTP_200=None),
)
def foobar():
    ...

 

What should I return when I'm using the library?

No need to change anything. Just return what the framework required.

How to log when the validation failed?

Validation errors are logged with the INFO level. Details are passed into extra. Check the falcon example for details.

How can I write a customized plugin for another backend framework?

Inherit spectree.plugins.base.BasePlugin and implement the functions you need. After that, init like api = SpecTree(backend=MyCustomizedPlugin).

How to use a customized template page?

SpecTree(page_templates={"page_name": "customized page contains {spec_url} for rendering"})

In the above example, the key "page_name" will be used in the URL to access this page "/apidoc/page_name". The value should be a string that contains {spec_url} which will be used to access the OpenAPI JSON file.

How can I change the response when there is a validation error? Can I record some metrics?

This library provides before and after hooks to do these. Check the doc or the test case. You can change the handlers for SpecTree or a specific endpoint validation.

How to change the default ValidationError status code?

You can change the validation_error_status in SpecTree (global) or a specific endpoint (local). This also takes effect in the OpenAPI documentation.

Demo

Try it with http post :8000/api/user name=alice age=18. (if you are using httpie)

Flask

from flask import Flask, request, jsonify
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response


class Profile(BaseModel):
    name: constr(min_length=2, max_length=40) # Constrained Str
    age: int = Field(
        ...,
        gt=0,
        lt=150,
        description='user age(Human)'
    )

    class Config:
        schema_extra = {
            # provide an example
            'example': {
                'name': 'very_important_user',
                'age': 42,
            }
        }


class Message(BaseModel):
    text: str


app = Flask(__name__)
api = SpecTree('flask')


@app.route('/api/user', methods=['POST'])
@api.validate(json=Profile, resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
def user_profile():
    """
    verify user profile (summary of this endpoint)

    user's name, user's age, ... (long description)
    """
    print(request.context.json) # or `request.json`
    return jsonify(text='it works')


if __name__ == "__main__":
    api.register(app) # if you don't register in api init step
    app.run(port=8000)

Flask example with type annotation

# opt in into annotations feature
api = SpecTree("flask", annotations=True)


@app.route('/api/user', methods=['POST'])
@api.validate(resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
def user_profile(json: Profile):
    """
    verify user profile (summary of this endpoint)

    user's name, user's age, ... (long description)
    """
    print(json) # or `request.json`
    return jsonify(text='it works')

Falcon

import falcon
from wsgiref import simple_server
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response


class Profile(BaseModel):
    name: constr(min_length=2, max_length=40)  # Constrained Str
    age: int = Field(
        ...,
        gt=0,
        lt=150,
        description='user age(Human)'
    )


class Message(BaseModel):
    text: str


api = SpecTree('falcon')


class UserProfile:
    @api.validate(json=Profile, resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
    def on_post(self, req, resp):
        """
        verify user profile (summary of this endpoint)

        user's name, user's age, ... (long description)
        """
        print(req.context.json)  # or `req.media`
        resp.media = {'text': 'it works'}


if __name__ == "__main__":
    app = falcon.API()
    app.add_route('/api/user', UserProfile())
    api.register(app)

    httpd = simple_server.make_server('localhost', 8000, app)
    httpd.serve_forever()

Falcon with type annotations

# opt in into annotations feature
api = SpecTree("falcon", annotations=True)


class UserProfile:
    @api.validate(resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
    def on_post(self, req, resp, json: Profile):
        """
        verify user profile (summary of this endpoint)

        user's name, user's age, ... (long description)
        """
        print(req.context.json)  # or `req.media`
        resp.media = {'text': 'it works'}

Starlette

import uvicorn
from starlette.applications import Starlette
from starlette.routing import Route, Mount
from starlette.responses import JSONResponse
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response


class Profile(BaseModel):
    name: constr(min_length=2, max_length=40)  # Constrained Str
    age: int = Field(
        ...,
        gt=0,
        lt=150,
        description='user age(Human)'
    )


class Message(BaseModel):
    text: str


api = SpecTree('starlette')


@api.validate(json=Profile, resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
async def user_profile(request):
    """
    verify user profile (summary of this endpoint)

    user's name, user's age, ... (long description)
    """
    print(request.context.json)  # or await request.json()
    return JSONResponse({'text': 'it works'})


if __name__ == "__main__":
    app = Starlette(routes=[
        Mount('api', routes=[
            Route('/user', user_profile, methods=['POST']),
        ])
    ])
    api.register(app)

    uvicorn.run(app)

Starlette example with type annotations

# opt in into annotations feature
api = SpecTree("flask", annotations=True)


@api.validate(resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
async def user_profile(request, json=Profile):
    """
    verify user profile (summary of this endpoint)

    user's name, user's age, ... (long description)
    """
    print(request.context.json)  # or await request.json()
    return JSONResponse({'text': 'it works'})

FAQ

ValidationError: missing field for headers

The HTTP headers' keys in Flask are capitalized, in Falcon are upper cases, in Starlette are lower cases. You can use pydantic.root_validators(pre=True) to change all the keys into lower cases or upper cases.

ValidationError: value is not a valid list for the query

Since there is no standard for HTTP queries with multiple values, it's hard to find a way to handle this for different web frameworks. So I suggest not to use list type in query until I find a suitable way to fix it.


Author: 0b01001001
Source Code: https://github.com/0b01001001/spectree
License: Apache-2.0 License

#python #openapi 

API Parameter Validator and OpenAPI Document Generator
Ngoc  Anh

Ngoc Anh

1646650800

How to Create A Modern Python Application From OpenAPI

openapi-python-client

Generate modern Python clients from OpenAPI 3.x documents.

This generator does not support OpenAPI 2.x FKA Swagger. If you need to use an older document, try upgrading it to version 3 first with one of many available converters.

This project is still in development and does not support all OpenAPI features

Why This?

This tool focuses on creating the best developer experience for Python developers by:

  1. Using all the latest and greatest Python features like type annotations and dataclasses.
  2. Having documentation and usage instructions specific to this one generator.
  3. Being written in Python with Jinja2 templates, making it easier to improve and extend for Python developers. It's also much easier to install and use if you already have Python.

Installation

I recommend you install with pipx so you don't conflict with any other packages you might have: pipx install openapi-python-client --include-deps.

Note the --include-deps option which will also make black, isort, and autoflake available in your path so that openapi-python-client can use them to clean up the generated code.

If you use pipx run then the post-generation hooks will not be available unless you install them manually.

You can also install with normal pip: pip install openapi-python-client

Then, if you want tab completion: openapi-python-client --install-completion

Usage

Create a new client

openapi-python-client generate --url https://my.api.com/openapi.json

This will generate a new client library named based on the title in your OpenAPI spec. For example, if the title of your API is "My API", the expected output will be "my-api-client". If a folder already exists by that name, you'll get an error.

If you have an openapi.json file available on disk, in any CLI invocation you can build off that instead by replacing --url with a --path:

openapi-python-client generate --path location/on/disk/openapi.json

Update an existing client

openapi-python-client update --url https://my.api.com/openapi.json

For more usage details run openapi-python-client --help or read usage

Using custom templates

This feature leverages Jinja2's ChoiceLoader and FileSystemLoader. This means you do not need to customize every template. Simply copy the template(s) you want to customize from the default template directory to your own custom template directory (file names must match exactly) and pass the template directory through the custom-template-path flag to the generate and update commands. For instance,

openapi-python-client update \
  --url https://my.api.com/openapi.json \
  --custom-template-path=relative/path/to/mytemplates

Be forewarned, this is a beta-level feature in the sense that the API exposed in the templates is undocumented and unstable.

What You Get

  1. A pyproject.toml file with some basic metadata intended to be used with Poetry.
  2. A README.md you'll most definitely need to update with your project's details
  3. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:
    1. A client module which will have both a Client class and an AuthenticatedClient class. You'll need these for calling the functions in the api module.
    2. An api module which will contain one module for each tag in your OpenAPI spec, as well as a default module for endpoints without a tag. Each of these modules in turn contains one function for calling each endpoint.
    3. A models module which has all the classes defined by the various schemas in your OpenAPI spec

For a full example you can look at the end_to_end_tests directory which has an openapi.json file. "golden-record" in that same directory is the generated client from that OpenAPI document.

OpenAPI features supported

  1. All HTTP Methods
  2. JSON and form bodies, path and query parameters
  3. File uploads with multipart/form-data bodies
  4. float, string, int, date, datetime, string enums, and custom schemas or lists containing any of those
  5. html/text or application/json responses containing any of the previous types
  6. Bearer token security

Configuration

You can pass a YAML (or JSON) file to openapi-python-client with the --config option in order to change some behavior. The following parameters are supported:

class_overrides

Used to change the name of generated model classes. This param should be a mapping of existing class name (usually a key in the "schemas" section of your OpenAPI document) to class_name and module_name. As an example, if the name of the a model in OpenAPI (and therefore the generated class name) was something like "_PrivateInternalLongName" and you want the generated client's model to be called "ShortName" in a module called "short_name" you could do this:

Example:

class_overrides:
  _PrivateInternalLongName:
    class_name: ShortName
    module_name: short_name

The easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the models folder.

project_name_override and package_name_override

Used to change the name of generated client library project/package. If the project name is changed but an override for the package name isn't provided, the package name will be converted from the project name using the standard convention (replacing -'s with _'s).

Example:

project_name_override: my-special-project-name
package_name_override: my_extra_special_package_name

field_prefix

When generating properties, the name attribute of the OpenAPI schema will be used. When the name is not a valid Python identifier (e.g. begins with a number) this string will be prepended. Defaults to "field_".

Example:

field_prefix: attr_

package_version_override

Specify the package version of the generated client. If unset, the client will use the version of the OpenAPI spec.

Example:

package_version_override: 1.2.3

post_hooks

In the config file, there's an easy way to tell openapi-python-client to run additional commands after generation. Here's an example showing the default commands that will run if you don't override them in config:

post_hooks:
   - "autoflake -i -r --remove-all-unused-imports --remove-unused-variables --ignore-init-module-imports ."
   - "isort ."
   - "black ."

Author: openapi-generators
Source Code: https://github.com/openapi-generators/openapi-python-client
License: MIT License

#python #openapi 

How to Create A Modern Python Application From OpenAPI
Ngoc  Anh

Ngoc Anh

1646643600

OpenAPI Core: A Python Library That Adds Client-side Support

openapi-core

About

Openapi-core is a Python library that adds client-side and server-side support for the OpenAPI Specification v3.

Key features

  • Validation of requests and responses
  • Schema casting and unmarshalling
  • Media type and parameters deserialization
  • Security providers (API keys, Cookie, Basic and Bearer HTTP authentications)
  • Custom deserializers and formats
  • Integration with libraries and frameworks

Documentation

Check documentation to see more details about the features. All documentation is in the "docs" directory and online at openapi-core.readthedocs.io

Installation

Recommended way (via pip):

$ pip install openapi-core

Alternatively you can download the code and install from the repository:

$ pip install -e git+https://github.com/p1c2u/openapi-core.git#egg=openapi_core

Usage

Firstly create your specification object:

from json import load
from openapi_core import OpenAPISpec as Spec

with open('openapi.json', 'r') as spec_file:
   spec_dict = load(spec_file)

spec = Spec.create(spec_dict)

Request

Now you can use it to validate against requests

from openapi_core.validation.request.validators import RequestValidator

validator = RequestValidator(spec)
result = validator.validate(request)

# raise errors if request invalid
result.raise_for_errors()

# get list of errors
errors = result.errors

and unmarshal request data from validation result

# get parameters object with path, query, cookies and headers parameters
validated_params = result.parameters
# or specific parameters
validated_path_params = result.parameters.path

# get body
validated_body = result.body

# get security data
validated_security = result.security

Request object should be instance of OpenAPIRequest class (See Integrations).

Response

You can also validate against responses

from openapi_core.validation.response.validators import ResponseValidator

validator = ResponseValidator(spec)
result = validator.validate(request, response)

# raise errors if response invalid
result.raise_for_errors()

# get list of errors
errors = result.errors

and unmarshal response data from validation result

# get headers
validated_headers = result.headers

# get data
validated_data = result.data

Response object should be instance of OpenAPIResponse class (See Integrations).

Related projects

tornado-openapi3

Tornado OpenAPI 3 request and response validation library.

pyramid_openapi3

Pyramid addon for OpenAPI3 validation of requests and responses.

openapi-schema-validator

Python library that validates schema against the OpenAPI Schema Specification v3.0.

openapi-spec-validator

Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0 specification

bottle-openapi-3

OpenAPI 3.0 Support for the Bottle Web Framework


Author: p1c2u
Source Code: https://github.com/p1c2u/openapi-core
License: BSD-3-Clause License

#python #openapi 

OpenAPI Core: A Python Library That Adds Client-side Support