├── .npmignore ├── .npmrc ├── .eslintignore ├── .prettierignore ├── src ├── package.json ├── config.js └── serverless.js ├── prettier.config.js ├── commitlint.config.js ├── .editorconfig ├── .gitignore ├── example ├── simple │ └── serverless.yml ├── base64 │ └── serverless.yml └── oauth2.0 │ └── serverless.yml ├── jest.config.js ├── __tests__ ├── lib │ └── utils.js └── index.test.js ├── LICENSE ├── release.config.js ├── .github └── workflows │ ├── validate.yml │ ├── release.yml │ └── test.yml ├── .eslintrc.js ├── README.md ├── package.json ├── CHANGELOG.md ├── serverless.component.yml └── docs └── configure.md /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | example -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | example 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | CHANGELOG.md 5 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "tencent-component-toolkit": "^2.5.5" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'always', 3 | printWidth: 100, 4 | semi: false, 5 | singleQuote: true, 6 | tabWidth: 2, 7 | trailingComma: 'none' 8 | } 9 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | const Configuration = { 2 | /* 3 | * Resolve and load @commitlint/config-conventional from node_modules. 4 | * Referenced packages must be installed 5 | */ 6 | extends: ['@commitlint/config-conventional'] 7 | } 8 | 9 | module.exports = Configuration 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_size = 2 11 | indent_style = space 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sublime-project 3 | *.sublime-workspace 4 | *.log 5 | .serverless 6 | v8-compile-cache-* 7 | jest/* 8 | coverage 9 | .serverless_plugins 10 | testProjects/*/package-lock.json 11 | testProjects/*/yarn.lock 12 | .serverlessUnzipped 13 | node_modules 14 | .vscode/ 15 | .eslintcache 16 | dist 17 | .idea 18 | build/ 19 | .env* 20 | env.js 21 | package-lock.json 22 | test 23 | yarn.lock -------------------------------------------------------------------------------- /example/simple/serverless.yml: -------------------------------------------------------------------------------- 1 | component: apigateway 2 | app: appDemo 3 | stage: dev 4 | name: apigwDemo 5 | 6 | inputs: 7 | region: ap-guangzhou 8 | protocols: 9 | - http 10 | - https 11 | serviceName: 'sls_apigw_test' 12 | environment: release 13 | endpoints: 14 | - path: / 15 | protocol: HTTP 16 | method: ANY 17 | apiName: index 18 | function: 19 | functionName: serverless-unit-test 20 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const CONFIGS = { 2 | compName: 'apigateway', 3 | compFullname: 'Apigateway', 4 | region: 'ap-guangzhou', 5 | serviceName: 'serverless', 6 | protocols: ['http'], 7 | environment: 'release', 8 | serviceDesc: 'Created by Serverless Component', 9 | tokenLocationMap: { 10 | authorization: 'method.req.header.authorization', 11 | cookie: 'method.req.header.cookie' 12 | } 13 | } 14 | 15 | module.exports = CONFIGS 16 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path') 2 | require('dotenv').config({ path: join(__dirname, '.env.test') }) 3 | 4 | const config = { 5 | verbose: true, 6 | silent: false, 7 | testTimeout: 600000, 8 | testEnvironment: 'node', 9 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$', 10 | testPathIgnorePatterns: ['/node_modules/', '/__tests__/lib/'], 11 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] 12 | } 13 | 14 | module.exports = config 15 | -------------------------------------------------------------------------------- /__tests__/lib/utils.js: -------------------------------------------------------------------------------- 1 | const { ServerlessSDK } = require('@serverless/platform-client-china') 2 | 3 | /* 4 | * Generate random id 5 | */ 6 | const generateId = () => 7 | Math.random() 8 | .toString(36) 9 | .substring(6) 10 | 11 | /* 12 | * Initializes and returns an instance of the serverless sdk 13 | * @param ${string} orgName - the serverless org name. 14 | */ 15 | const getServerlessSdk = (orgName) => { 16 | const sdk = new ServerlessSDK({ 17 | context: { 18 | orgName 19 | } 20 | }) 21 | return sdk 22 | } 23 | 24 | module.exports = { generateId, getServerlessSdk } 25 | -------------------------------------------------------------------------------- /example/base64/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: apigateway 4 | name: apigwDemo 5 | 6 | inputs: 7 | region: ap-guangzhou 8 | protocols: 9 | - http 10 | - https 11 | serviceName: 'sls_apigw_test' 12 | environment: release 13 | endpoints: 14 | - path: / 15 | protocol: HTTP 16 | method: ANY 17 | apiName: index 18 | isBase64Encoded: true 19 | isBase64Trigger: true 20 | base64EncodedTriggerRules: 21 | - name: Accept 22 | value: 23 | - image/jpeg 24 | - name: Content_Type 25 | value: 26 | - image/jpeg 27 | function: 28 | functionName: serverless-unit-test 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Tencent Cloud, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/oauth2.0/serverless.yml: -------------------------------------------------------------------------------- 1 | app: appDemo 2 | stage: dev 3 | component: apigateway 4 | name: apigwDemo 5 | 6 | inputs: 7 | region: ap-guangzhou 8 | protocols: 9 | - http 10 | - https 11 | serviceName: 'sls_apigw_test' 12 | environment: release 13 | endpoints: 14 | - path: /oauth 15 | protocol: HTTP 16 | method: GET 17 | apiName: oauthapi 18 | authType: OAUTH 19 | businessType: OAUTH 20 | serviceType: HTTP 21 | serviceConfig: 22 | method: GET 23 | path: /check 24 | url: http://127.0.0.1:9090 25 | oauthConfig: 26 | loginRedirectUrl: http://127.0.0.1:9090/code 27 | # 请修改为自己的 RSA 公钥 28 | # 生成方式请参考官方文档:https://cloud.tencent.com/document/product/628/38393 29 | publicKey: '{"e":"AQAB","kty":"RSA","n":"xxxxxxxx"}' 30 | tokenLocation: authorization 31 | - path: '/oauthwork' 32 | protocol: HTTP 33 | method: GET 34 | apiName: business 35 | authType: OAUTH 36 | businessType: NORMAL 37 | authRelationApi: 38 | path: /oauth 39 | method: GET 40 | serviceType: MOCK 41 | serviceMockReturnMessage: helloworld 42 | -------------------------------------------------------------------------------- /release.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verifyConditions: [ 3 | '@semantic-release/changelog', 4 | '@semantic-release/git', 5 | '@semantic-release/github' 6 | ], 7 | plugins: [ 8 | [ 9 | '@semantic-release/commit-analyzer', 10 | { 11 | preset: 'angular', 12 | parserOpts: { 13 | noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'] 14 | } 15 | } 16 | ], 17 | [ 18 | '@semantic-release/release-notes-generator', 19 | { 20 | preset: 'angular', 21 | parserOpts: { 22 | noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'] 23 | }, 24 | writerOpts: { 25 | commitsSort: ['subject', 'scope'] 26 | } 27 | } 28 | ], 29 | [ 30 | '@semantic-release/changelog', 31 | { 32 | changelogFile: 'CHANGELOG.md' 33 | } 34 | ], 35 | [ 36 | '@semantic-release/git', 37 | { 38 | assets: ['package.json', 'src/**', 'CHANGELOG.md'], 39 | message: 'chore(release): version ${nextRelease.version} \n\n${nextRelease.notes}' 40 | } 41 | ], 42 | [ 43 | '@semantic-release/github', 44 | { 45 | assets: ['!.env'] 46 | } 47 | ] 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: Validate 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | lintAndFormatting: 9 | name: Lint & Formatting 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | with: 15 | # Ensure connection with 'master' branch 16 | fetch-depth: 2 17 | 18 | - name: Install Node.js and npm 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: 14.x 22 | registry-url: https://registry.npmjs.org 23 | 24 | - name: Retrieve dependencies from cache 25 | id: cacheNpm 26 | uses: actions/cache@v2 27 | with: 28 | path: | 29 | ~/.npm 30 | node_modules 31 | key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} 32 | restore-keys: | 33 | npm-v14-${{ runner.os }}-${{ github.ref }}- 34 | npm-v14-${{ runner.os }}-refs/heads/master- 35 | 36 | - name: Install dependencies 37 | if: steps.cacheNpm.outputs.cache-hit != 'true' 38 | run: | 39 | npm update --no-save 40 | npm update --save-dev --no-save 41 | 42 | - name: Validate Formatting 43 | run: npm run prettier:fix 44 | - name: Validate Lint rules 45 | run: npm run lint:fix 46 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | release: 9 | name: Release 10 | runs-on: ubuntu-latest 11 | env: 12 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v2 16 | with: 17 | persist-credentials: false 18 | 19 | - name: Install Node.js and npm 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: 14.x 23 | registry-url: https://registry.npmjs.org 24 | 25 | - name: Retrieve dependencies from cache 26 | id: cacheNpm 27 | uses: actions/cache@v2 28 | with: 29 | path: | 30 | ~/.npm 31 | node_modules 32 | key: npm-v14-${{ runner.os }}-refs/heads/master-${{ hashFiles('package.json') }} 33 | restore-keys: npm-v14-${{ runner.os }}-refs/heads/master- 34 | 35 | - name: Install dependencies 36 | if: steps.cacheNpm.outputs.cache-hit != 'true' 37 | run: | 38 | npm update --no-save 39 | npm update --save-dev --no-save 40 | - name: Releasing 41 | run: | 42 | npm run release 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 45 | GIT_AUTHOR_NAME: slsplus 46 | GIT_AUTHOR_EMAIL: slsplus.sz@gmail.com 47 | GIT_COMMITTER_NAME: slsplus 48 | GIT_COMMITTER_EMAIL: slsplus.sz@gmail.com 49 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | test: 9 | name: Test 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 2 16 | 17 | - name: Install Node.js and npm 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: 14.x 21 | registry-url: https://registry.npmjs.org 22 | 23 | - name: Retrieve dependencies from cache 24 | id: cacheNpm 25 | uses: actions/cache@v2 26 | with: 27 | path: | 28 | ~/.npm 29 | node_modules 30 | key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} 31 | restore-keys: | 32 | npm-v14-${{ runner.os }}-${{ github.ref }}- 33 | npm-v14-${{ runner.os }}-refs/heads/master- 34 | 35 | - name: Install dependencies 36 | if: steps.cacheNpm.outputs.cache-hit != 'true' 37 | run: | 38 | npm update --no-save 39 | npm update --save-dev --no-save 40 | - name: Running tests 41 | run: npm run test 42 | env: 43 | SERVERLESS_PLATFORM_VENDOR: tencent 44 | GLOBAL_ACCELERATOR_NA: true 45 | TENCENT_APP_ID: ${{ secrets.TENCENT_APP_ID }} 46 | TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} 47 | TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} 48 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['prettier'], 4 | plugins: ['import', 'prettier'], 5 | env: { 6 | es6: true, 7 | jest: true, 8 | node: true 9 | }, 10 | parser: 'babel-eslint', 11 | parserOptions: { 12 | ecmaVersion: 2018, 13 | sourceType: 'module', 14 | ecmaFeatures: { 15 | jsx: true 16 | } 17 | }, 18 | globals: { 19 | on: true // for the Socket file 20 | }, 21 | rules: { 22 | 'array-bracket-spacing': [ 23 | 'error', 24 | 'never', 25 | { 26 | objectsInArrays: false, 27 | arraysInArrays: false 28 | } 29 | ], 30 | 'arrow-parens': ['error', 'always'], 31 | 'arrow-spacing': ['error', { before: true, after: true }], 32 | 'comma-dangle': ['error', 'never'], 33 | curly: 'error', 34 | 'eol-last': 'error', 35 | 'func-names': 'off', 36 | 'id-length': [ 37 | 'error', 38 | { 39 | min: 1, 40 | max: 50, 41 | properties: 'never', 42 | exceptions: ['e', 'i', 'n', 't', 'x', 'y', 'z', '_', '$'] 43 | } 44 | ], 45 | 'no-alert': 'error', 46 | 'no-console': 'off', 47 | 'no-const-assign': 'error', 48 | 'no-else-return': 'error', 49 | 'no-empty': 'off', 50 | 'no-shadow': 'error', 51 | 'no-undef': 'error', 52 | 'no-unused-vars': 'error', 53 | 'no-use-before-define': 'error', 54 | 'no-useless-constructor': 'error', 55 | 'object-curly-newline': 'off', 56 | 'object-shorthand': 'off', 57 | 'prefer-const': 'error', 58 | 'prefer-destructuring': ['error', { object: true, array: false }], 59 | quotes: [ 60 | 'error', 61 | 'single', 62 | { 63 | allowTemplateLiterals: true, 64 | avoidEscape: true 65 | } 66 | ], 67 | semi: ['error', 'never'], 68 | 'spaced-comment': 'error', 69 | strict: ['error', 'global'], 70 | 'prettier/prettier': 'error' 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 腾讯云 API 网关组件 2 | 3 | ## 简介 4 | 5 | 通过 API 网关组件,可以快速,方便的创建,配置和管理腾讯云的 API 网关产品。 6 | 7 | 快速开始: 8 | 9 | 1. [安装](#1-安装) 10 | 2. [配置](#2-配置) 11 | 3. [部署](#3-部署) 12 | 4. [查看状态](#4-查看状态) 13 | 5. [移除](#5-移除) 14 | 15 | ### 1. 安装 16 | 17 | 通过 npm 安装最新版本的 Serverless Framework 18 | 19 | ```bash 20 | $ npm install -g serverless 21 | ``` 22 | 23 | ### 2. 配置 24 | 25 | 本地创建 `serverless.yml` 文件,在其中进行如下配置 26 | 27 | ```bash 28 | $ touch serverless.yml 29 | ``` 30 | 31 | ```yml 32 | # serverless.yml 33 | 34 | org: orgDemo 35 | app: appDemo 36 | stage: dev 37 | component: apigateway 38 | name: apigwDemo 39 | 40 | inputs: 41 | region: ap-guangzhou 42 | protocols: 43 | - http 44 | - https 45 | serviceName: serverless 46 | environment: release 47 | endpoints: 48 | - path: / 49 | protocol: HTTP 50 | method: GET 51 | apiName: index 52 | function: 53 | functionName: myFunction 54 | ``` 55 | 56 | 点此查看[全量配置及配置说明](https://github.com/serverless-components/tencent-apigateway/tree/master/docs/configure.md) 57 | 58 | ### 3. 部署 59 | 60 | 如您的账号未[登陆](https://cloud.tencent.com/login)或[注册](https://cloud.tencent.com/register)腾讯云,您可以直接通过`微信`扫描命令行中的二维码进行授权登陆和注册。 61 | 62 | 通过`sls`命令进行部署,并可以添加`--debug`参数查看部署过程中的信息 63 | 64 | ```bash 65 | $ sls deploy 66 | ``` 67 | 68 | ### 4. 查看状态 69 | 70 | 在`serverless.yml`文件所在的目录下,通过如下命令查看部署状态: 71 | 72 | ``` 73 | $ serverless info 74 | ``` 75 | 76 | ### 5. 移除 77 | 78 | 通过以下命令移除部署的 API 网关 79 | 80 | ```bash 81 | $ sls remove 82 | ``` 83 | 84 | ### 账号配置(可选) 85 | 86 | 当前默认支持 CLI 扫描二维码登录,如您希望配置持久的环境变量/秘钥信息,也可以本地创建 `.env` 文件 87 | 88 | ```bash 89 | $ touch .env # 腾讯云的配置信息 90 | ``` 91 | 92 | 在 `.env` 文件中配置腾讯云的 SecretId 和 SecretKey 信息并保存 93 | 94 | 如果没有腾讯云账号,可以在此[注册新账号](https://cloud.tencent.com/register)。 95 | 96 | 如果已有腾讯云账号,可以在[API 密钥管理](https://console.cloud.tencent.com/cam/capi)中获取 `SecretId` 和`SecretKey`. 97 | 98 | ``` 99 | # .env 100 | TENCENT_SECRET_ID=123 101 | TENCENT_SECRET_KEY=123 102 | ``` 103 | 104 | ## License 105 | 106 | MIT License 107 | 108 | Copyright (c) 2020 Tencent Cloud, Inc. 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@serverless/apigateway", 3 | "main": "src/serverless.js", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "description": "Easily provision Tencent API Gateway using Serverless Components", 8 | "scripts": { 9 | "test": "jest", 10 | "commitlint": "commitlint -f HEAD@{15}", 11 | "lint": "eslint --ext .js,.ts,.tsx .", 12 | "lint:fix": "eslint --fix --ext .js,.ts,.tsx .", 13 | "prettier": "prettier --check '**/*.{css,html,js,json,md,yaml,yml}'", 14 | "prettier:fix": "prettier --write '**/*.{css,html,js,json,md,yaml,yml}'", 15 | "release": "semantic-release", 16 | "release-local": "node -r dotenv/config node_modules/semantic-release/bin/semantic-release --no-ci --dry-run", 17 | "check-dependencies": "npx npm-check --skip-unused --update" 18 | }, 19 | "husky": { 20 | "hooks": { 21 | "pre-commit": "ygsec && lint-staged", 22 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", 23 | "pre-push": "ygsec && npm run lint:fix && npm run prettier:fix" 24 | } 25 | }, 26 | "lint-staged": { 27 | "**/*.{js,ts,tsx}": [ 28 | "npm run lint:fix" 29 | ], 30 | "**/*.{css,html,js,json,md,yaml,yml}": [ 31 | "npm run prettier:fix" 32 | ] 33 | }, 34 | "author": "Tencent Cloud, Inc.", 35 | "license": "MIT", 36 | "dependencies": {}, 37 | "devDependencies": { 38 | "@commitlint/cli": "^8.3.5", 39 | "@commitlint/config-conventional": "^8.3.4", 40 | "@semantic-release/changelog": "^5.0.0", 41 | "@semantic-release/commit-analyzer": "^8.0.1", 42 | "@semantic-release/git": "^9.0.0", 43 | "@semantic-release/npm": "^7.0.4", 44 | "@semantic-release/release-notes-generator": "^9.0.1", 45 | "@serverless/platform-client-china": "^2.1.9", 46 | "@ygkit/secure": "0.0.3", 47 | "babel-eslint": "^10.1.0", 48 | "dotenv": "^8.2.0", 49 | "eslint": "^6.8.0", 50 | "eslint-config-prettier": "^6.10.0", 51 | "eslint-plugin-import": "^2.20.1", 52 | "eslint-plugin-prettier": "^3.1.2", 53 | "husky": "^4.2.5", 54 | "jest": "^25.0.1", 55 | "lint-staged": "^10.0.8", 56 | "prettier": "^1.19.1", 57 | "semantic-release": "^17.0.4" 58 | }, 59 | "directories": { 60 | "doc": "docs", 61 | "example": "example", 62 | "test": "tests" 63 | }, 64 | "repository": { 65 | "type": "git", 66 | "url": "git+https://github.com/serverless-components/tencent-apigateway.git" 67 | }, 68 | "keywords": [ 69 | "serverless-apigateway", 70 | "apigateway", 71 | "serverless", 72 | "serverless-framework", 73 | "serverless-components", 74 | "tencent-cloud" 75 | ], 76 | "bugs": { 77 | "url": "https://github.com/serverless-components/tencent-apigateway/issues" 78 | }, 79 | "homepage": "https://github.com/serverless-components/tencent-apigateway#readme" 80 | } 81 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [0.4.0](https://github.com/serverless-components/tencent-apigateway/compare/v0.3.0...v0.4.0) (2021-07-30) 2 | 3 | 4 | ### Features 5 | 6 | * support api app auth and instance ([a400f2e](https://github.com/serverless-components/tencent-apigateway/commit/a400f2ef0dc7d283c82afc425817e2ae9136cd4e)) 7 | 8 | # [0.3.0](https://github.com/serverless-components/tencent-apigateway/compare/v0.2.1...v0.3.0) (2021-03-29) 9 | 10 | 11 | ### Features 12 | 13 | * update sdk version ([#22](https://github.com/serverless-components/tencent-apigateway/issues/22)) ([c11a8a5](https://github.com/serverless-components/tencent-apigateway/commit/c11a8a512a92e67587791ff8f57c8b9a7fb446a8)) 14 | 15 | ## [0.2.1](https://github.com/serverless-components/tencent-apigateway/compare/v0.2.0...v0.2.1) (2021-03-04) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * relative oauth api update ([8b4b91f](https://github.com/serverless-components/tencent-apigateway/commit/8b4b91f50795928ac1e4a943f36795406d43fe84)) 21 | 22 | # [0.2.0](https://github.com/serverless-components/tencent-apigateway/compare/v0.1.2...v0.2.0) (2021-01-21) 23 | 24 | 25 | ### Features 26 | 27 | * support base64 encode ([dd553b9](https://github.com/serverless-components/tencent-apigateway/commit/dd553b9175b0bc431621bf8c5643dfff2cdd4936)) 28 | 29 | ## [0.1.2](https://github.com/serverless-components/tencent-apigateway/compare/v0.1.1...v0.1.2) (2020-12-17) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * support oauth2.0 ([#19](https://github.com/serverless-components/tencent-apigateway/issues/19)) ([f00455e](https://github.com/serverless-components/tencent-apigateway/commit/f00455ed84c95f3efafbbe67ded790f9673d60c8)) 35 | 36 | ## [0.1.1](https://github.com/serverless-components/tencent-apigateway/compare/v0.1.0...v0.1.1) (2020-11-24) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * update deps ([#18](https://github.com/serverless-components/tencent-apigateway/issues/18)) ([6aee1a9](https://github.com/serverless-components/tencent-apigateway/commit/6aee1a97f7a023288499922db2334bab80cba444)) 42 | 43 | # [0.1.0](https://github.com/serverless-components/tencent-apigateway/compare/v0.0.10...v0.1.0) (2020-10-22) 44 | 45 | 46 | ### Features 47 | 48 | * support type check ([751efae](https://github.com/serverless-components/tencent-apigateway/commit/751efae52bb0605e755c478fc2cea473f251ef45)) 49 | 50 | ## [0.0.10](https://github.com/serverless-components/tencent-apigateway/compare/v0.0.9...v0.0.10) (2020-09-07) 51 | 52 | 53 | ### Bug Fixes 54 | 55 | * update deps ([2bb2620](https://github.com/serverless-components/tencent-apigateway/commit/2bb26206ae4c52c284c007f13b64bbba7db38393)) 56 | 57 | ## [0.0.9](https://github.com/serverless-components/tencent-apigateway/compare/v0.0.8...v0.0.9) (2020-09-02) 58 | 59 | 60 | ### Bug Fixes 61 | 62 | * update tencnet-component-toolkit for api mark ([05357d9](https://github.com/serverless-components/tencent-apigateway/commit/05357d90bab8d8de70c050dafb3fae64d71d16ba)) 63 | 64 | ## [0.0.8](https://github.com/serverless-components/tencent-apigateway/compare/v0.0.7...v0.0.8) (2020-08-27) 65 | 66 | 67 | ### Bug Fixes 68 | 69 | * apigw state not exits error ([c158018](https://github.com/serverless-components/tencent-apigateway/commit/c1580180d889be8f888d6e0d50120e886abc575a)) 70 | * custom domain cname error ([9f310ae](https://github.com/serverless-components/tencent-apigateway/commit/9f310ae3f2c8e28b1cd36a641e7bb937aac17140)) 71 | * fix prop length is null issue ([3151d7e](https://github.com/serverless-components/tencent-apigateway/commit/3151d7e4300a3608222fc1f1843ab8680d8e1a4b)) 72 | * make isDefaultMapping default to true ([9fd81f6](https://github.com/serverless-components/tencent-apigateway/commit/9fd81f6a257314b45a4f283f9d77ab70ca8c2d65)) 73 | * repeat create api service ([cb3fadb](https://github.com/serverless-components/tencent-apigateway/commit/cb3fadb7dbda7af61c6fd6dc74daa96ec3f1c701)) 74 | * update deps ([12613d9](https://github.com/serverless-components/tencent-apigateway/commit/12613d9f16a9f56e73745bee1c014efe750661dc)) 75 | * update deps for netTypes config ([3958d8a](https://github.com/serverless-components/tencent-apigateway/commit/3958d8a25d51a86bd9774687678c45659a5c69c4)) 76 | * update error message ([82126ac](https://github.com/serverless-components/tencent-apigateway/commit/82126ace7873592dca6729434436c7d1207a14a1)) 77 | * update get credential error message ([fe858ae](https://github.com/serverless-components/tencent-apigateway/commit/fe858aea75cb0f0bc41f266c3a2a8c101c47939b)) 78 | * upgrade deps ([0969935](https://github.com/serverless-components/tencent-apigateway/commit/0969935416b56800b6a879748697554b7c11a950)) 79 | 80 | 81 | ### Features 82 | 83 | * init v2 ([2b428e6](https://github.com/serverless-components/tencent-apigateway/commit/2b428e668a4a2b9bc6f940c97e4c74a85b2521aa)) 84 | * support netTypes config ([7382331](https://github.com/serverless-components/tencent-apigateway/commit/7382331e42d573faa6fd12acdf37e176557d04e2)) 85 | * support no input create ([b86bc4d](https://github.com/serverless-components/tencent-apigateway/commit/b86bc4d23517ca169708c77393f19885618f0b3b)) 86 | * upgrade to v2 with toolkit ([#13](https://github.com/serverless-components/tencent-apigateway/issues/13)) ([f5271e1](https://github.com/serverless-components/tencent-apigateway/commit/f5271e132b1ec9a0b5a34e3854f76f2292ea93fb)) 87 | -------------------------------------------------------------------------------- /src/serverless.js: -------------------------------------------------------------------------------- 1 | const { Component } = require('@serverless/core') 2 | const { Apigw } = require('tencent-component-toolkit') 3 | const { ApiTypeError } = require('tencent-component-toolkit/lib/utils/error') 4 | const CONFIGS = require('./config') 5 | 6 | class ServerlessComponent extends Component { 7 | getCredentials() { 8 | const { tmpSecrets } = this.credentials.tencent 9 | 10 | if (!tmpSecrets || !tmpSecrets.TmpSecretId) { 11 | throw new ApiTypeError( 12 | 'CREDENTIAL', 13 | 'Cannot get secretId/Key, your account could be sub-account and does not have the access to use SLS_QcsRole, please make sure the role exists first, then visit https://cloud.tencent.com/document/product/1154/43006, follow the instructions to bind the role to your account.' 14 | ) 15 | } 16 | 17 | return { 18 | SecretId: tmpSecrets.TmpSecretId, 19 | SecretKey: tmpSecrets.TmpSecretKey, 20 | Token: tmpSecrets.Token 21 | } 22 | } 23 | 24 | getDefaultProtocol(protocols) { 25 | return String(protocols).includes('https') ? 'https' : 'http' 26 | } 27 | 28 | async deploy(inputs) { 29 | console.log(`Deploying API Gateway`) 30 | 31 | // get tencent cloud credentials 32 | const credentials = this.getCredentials() 33 | 34 | const apigw = new Apigw(credentials, inputs.region) 35 | 36 | inputs.oldState = this.state 37 | inputs.serviceId = inputs.serviceId || this.state.serviceId 38 | 39 | // make default config 40 | inputs.region = inputs.region || CONFIGS.region 41 | inputs.serviceName = inputs.serviceName || CONFIGS.serviceName 42 | inputs.protocols = inputs.protocols || CONFIGS.protocols 43 | inputs.environment = inputs.environment || CONFIGS.environment 44 | inputs.serviceDesc = inputs.serviceDesc || CONFIGS.serviceDesc 45 | inputs.endpoints = inputs.endpoints.map((item) => { 46 | if (item.oauthConfig) { 47 | item.oauthConfig.tokenLocation = 48 | CONFIGS.tokenLocationMap[item.oauthConfig.tokenLocation] || item.oauthConfig.tokenLocation 49 | } 50 | return item 51 | }) 52 | 53 | const deployRes = await apigw.deploy(inputs) 54 | this.state = deployRes 55 | 56 | const apiOutput = [] 57 | if (deployRes.apiList && deployRes.apiList.length > 0) { 58 | deployRes.apiList.forEach((api) => { 59 | const output = { 60 | path: api.path, 61 | method: api.method, 62 | apiId: api.apiId, 63 | authType: api.authType, 64 | businessType: api.businessType, 65 | internalDomain: api.internalDomain || undefined, 66 | isBase64Encoded: api.isBase64Encoded, 67 | usagePlanId: api.usagePlan && api.usagePlan.usagePlanId, 68 | secretIds: 69 | api.usagePlan && 70 | api.usagePlan.secrets && 71 | api.usagePlan.secrets.secretIds && 72 | api.usagePlan.secrets.secretIds.length > 0 && 73 | api.usagePlan.secrets.secretIds.join(',') 74 | } 75 | if (api.authRelationApiId) { 76 | output.authRelationApiId = api.authRelationApiId 77 | } 78 | apiOutput.push(output) 79 | }) 80 | } 81 | 82 | const outputs = { 83 | url: `${this.getDefaultProtocol(deployRes.protocols)}://${deployRes.subDomain}/${ 84 | deployRes.environment 85 | }/`, 86 | protocols: deployRes.protocols, 87 | subDomain: deployRes.subDomain, 88 | environment: deployRes.environment, 89 | region: inputs.region, 90 | serviceId: deployRes.serviceId, 91 | apis: apiOutput 92 | } 93 | 94 | if (deployRes.customDomains && deployRes.customDomains.length > 0) { 95 | outputs.customDomains = [] 96 | deployRes.customDomains.forEach((domain) => { 97 | if (domain.isBinded === false) { 98 | outputs.customDomains.push({ 99 | domain: domain.subDomain, 100 | cname: domain.cname, 101 | message: domain.message 102 | }) 103 | } else { 104 | outputs.customDomains.push({ 105 | domain: domain.subDomain, 106 | cname: domain.cname 107 | }) 108 | } 109 | }) 110 | } 111 | 112 | return outputs 113 | } 114 | 115 | async remove(inputs) { 116 | console.log(`Removing API Gateway`) 117 | 118 | // get tencent cloud credentials 119 | const credentials = this.getCredentials() 120 | 121 | const { state } = this 122 | const apigw = new Apigw(credentials, state.region) 123 | 124 | // support force delete api gateway by command param: --inputs force=true 125 | if (inputs.force === true) { 126 | try { 127 | state.created = true 128 | if (state.apiList && state.apiList.length > 0) { 129 | state.apiList = state.apiList.map((item) => { 130 | item.created = true 131 | if (item.usagePlan) { 132 | item.usagePlan.created = true 133 | if (item.usagePlan.secrets) { 134 | item.usagePlan.secrets = item.usagePlan.secrets.map((up) => { 135 | up.created = true 136 | return up 137 | }) 138 | } 139 | } 140 | return item 141 | }) 142 | } 143 | } catch (e) {} 144 | } 145 | if (state && state.serviceId) { 146 | await apigw.remove(state) 147 | } 148 | this.state = {} 149 | return {} 150 | } 151 | } 152 | 153 | module.exports = ServerlessComponent 154 | -------------------------------------------------------------------------------- /__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const { generateId, getServerlessSdk } = require('./lib/utils') 2 | 3 | const appId = process.env.TENCENT_APP_ID 4 | const endpoints = [ 5 | { 6 | path: '/test', 7 | protocol: 'HTTP', 8 | method: 'GET', 9 | apiName: 'indextest', 10 | function: { 11 | functionName: 'serverless-unit-test' 12 | }, 13 | usagePlan: { 14 | usagePlanName: 'slscmp', 15 | usagePlanDesc: 'sls create', 16 | maxRequestNum: 1000 17 | }, 18 | auth: { secretName: 'secret' } 19 | }, 20 | { 21 | path: '/ws-scf', 22 | protocol: 'WEBSOCKET', 23 | method: 'GET', 24 | apiName: 'WS-SCF-API', 25 | function: { 26 | transportFunctionName: 'serverless-unit-test', 27 | registerFunctionName: 'serverless-unit-test', 28 | cleanupFunctionName: 'serverless-unit-test' 29 | } 30 | }, 31 | { 32 | path: '/ws', 33 | protocol: 'WEBSOCKET', 34 | apiName: 'WS-WS-API', 35 | method: 'GET', 36 | serviceType: 'WEBSOCKET', 37 | serviceConfig: { 38 | url: 'ws://test.com', 39 | path: '/', 40 | method: 'GET' 41 | } 42 | }, 43 | { 44 | path: '/mo', 45 | protocol: 'HTTP', 46 | method: 'GET', 47 | apiName: 'mo', 48 | serviceType: 'MOCK', 49 | serviceMockReturnMessage: 'test mock response' 50 | }, 51 | { 52 | path: '/auto', 53 | protocol: 'HTTP', 54 | apiName: 'HTTP-PROXY', 55 | method: 'GET', 56 | serviceType: 'HTTP', 57 | serviceConfig: { 58 | url: 'http://www.test.com', 59 | path: '/test', 60 | method: 'GET' 61 | } 62 | }, 63 | { 64 | path: '/base64', 65 | protocol: 'HTTP', 66 | method: 'GET', 67 | apiName: 'base64', 68 | function: { 69 | functionName: 'serverless-unit-test' 70 | }, 71 | isBase64Encoded: true, 72 | isBase64Trigger: true, 73 | base64EncodedTriggerRules: [ 74 | { 75 | name: 'Accept', 76 | value: ['image/jpeg'] 77 | }, 78 | { 79 | name: 'Content_Type', 80 | value: ['image/jpeg'] 81 | } 82 | ] 83 | }, 84 | // below two api is for oauth2.0 test 85 | { 86 | path: '/oauth', 87 | protocol: 'HTTP', 88 | method: 'GET', 89 | apiName: 'oauthapi', 90 | authType: 'OAUTH', 91 | businessType: 'OAUTH', 92 | serviceType: 'HTTP', 93 | serviceConfig: { 94 | method: 'GET', 95 | path: '/check', 96 | url: 'http://127.0.0.1:9090' 97 | }, 98 | oauthConfig: { 99 | loginRedirectUrl: 'http://127.0.0.1:9090/code', 100 | publicKey: '{"e":"AQAB","kty":"RSA","n":"xxxxxxxx"}', 101 | tokenLocation: 'authorization' 102 | // tokenLocation: 'method.req.header.cookie', 103 | } 104 | }, 105 | { 106 | path: '/oauthwork', 107 | protocol: 'HTTP', 108 | method: 'GET', 109 | apiName: 'business', 110 | authType: 'OAUTH', 111 | businessType: 'NORMAL', 112 | authRelationApi: { 113 | path: '/oauth', 114 | method: 'GET' 115 | }, 116 | serviceType: 'MOCK', 117 | serviceMockReturnMessage: 'helloworld' 118 | } 119 | ] 120 | const instanceYaml = { 121 | org: appId, 122 | app: 'appDemo', 123 | component: 'apigateway@dev', 124 | name: `apigateway-integration-tests-${generateId()}`, 125 | stage: 'dev', 126 | inputs: { 127 | // region: 'ap-guangzhou' 128 | protocols: ['http', 'https'], 129 | serviceName: 'sls_apigw_test', 130 | environment: 'release', 131 | endpoints 132 | } 133 | } 134 | 135 | const credentials = { 136 | tencent: { 137 | SecretId: process.env.TENCENT_SECRET_ID, 138 | SecretKey: process.env.TENCENT_SECRET_KEY 139 | } 140 | } 141 | 142 | const sdk = getServerlessSdk(instanceYaml.org, appId) 143 | 144 | it('deploy apigateway service', async () => { 145 | const instance = await sdk.deploy(instanceYaml, credentials) 146 | 147 | expect(instance).toBeDefined() 148 | expect(instance.instanceName).toEqual(instanceYaml.name) 149 | expect(instance.environment).toEqual(instanceYaml.environment) 150 | 151 | expect(instance.state).toBeDefined() 152 | expect(instance.state.serviceName).toEqual(instanceYaml.inputs.serviceName) 153 | 154 | // outputs 155 | expect(instance.outputs).toBeDefined() 156 | const { outputs, state } = instance 157 | const { serviceId, apis } = outputs 158 | const stateApiList = state.apiList 159 | expect(serviceId).toBeDefined() 160 | 161 | instanceYaml.inputs.serviceId = serviceId 162 | 163 | expect(apis).toBeDefined() 164 | expect(apis.length).toEqual(endpoints.length) 165 | expect(apis[0].path).toEqual(endpoints[0].path) 166 | expect(apis[0].method).toEqual(endpoints[0].method) 167 | 168 | expect(stateApiList).toBeDefined() 169 | expect(stateApiList.length).toEqual(endpoints.length) 170 | 171 | // scf api 172 | expect(stateApiList[0].usagePlan).toBeDefined() 173 | expect(stateApiList[0].usagePlan.secrets).toBeDefined() 174 | expect(stateApiList[0].usagePlan.usagePlanId).toBeDefined() 175 | 176 | endpoints[0].usagePlan.usagePlanId = stateApiList[0].usagePlan.usagePlanId 177 | 178 | // ws api 179 | expect(stateApiList[1].apiName).toEqual(endpoints[1].apiName) 180 | expect(stateApiList[1].path).toEqual(endpoints[1].path) 181 | expect(stateApiList[1].method).toEqual(endpoints[1].method) 182 | 183 | expect(stateApiList[2].apiName).toEqual(endpoints[2].apiName) 184 | expect(stateApiList[2].path).toEqual(endpoints[2].path) 185 | expect(stateApiList[2].method).toEqual(endpoints[2].method) 186 | 187 | // mock api 188 | expect(stateApiList[3].apiName).toEqual(endpoints[3].apiName) 189 | expect(stateApiList[3].path).toEqual(endpoints[3].path) 190 | expect(stateApiList[3].method).toEqual(endpoints[3].method) 191 | 192 | // backend http api 193 | expect(stateApiList[4].apiName).toEqual(endpoints[4].apiName) 194 | expect(stateApiList[4].path).toEqual(endpoints[4].path) 195 | expect(stateApiList[4].method).toEqual(endpoints[4].method) 196 | 197 | // base64 api 198 | expect(stateApiList[5].apiName).toEqual(endpoints[5].apiName) 199 | expect(stateApiList[5].path).toEqual(endpoints[5].path) 200 | expect(stateApiList[5].method).toEqual(endpoints[5].method) 201 | expect(stateApiList[5].isBase64Encoded).toEqual(endpoints[5].isBase64Encoded) 202 | 203 | // oauth api 204 | expect(stateApiList[6].apiName).toEqual(endpoints[6].apiName) 205 | expect(stateApiList[6].path).toEqual(endpoints[6].path) 206 | expect(stateApiList[6].method).toEqual(endpoints[6].method) 207 | expect(stateApiList[6].authType).toEqual(endpoints[6].authType) 208 | expect(stateApiList[6].businessType).toEqual(endpoints[6].businessType) 209 | 210 | // oauth business api 211 | expect(stateApiList[7].apiName).toEqual(endpoints[7].apiName) 212 | expect(stateApiList[7].path).toEqual(endpoints[7].path) 213 | expect(stateApiList[7].method).toEqual(endpoints[7].method) 214 | expect(stateApiList[7].authType).toEqual(endpoints[7].authType) 215 | expect(stateApiList[7].businessType).toEqual(endpoints[7].businessType) 216 | expect(stateApiList[7].authRelationApiId).toEqual(stateApiList[6].apiId) 217 | }) 218 | 219 | it('remove apigateway service', async () => { 220 | await sdk.remove(instanceYaml, credentials) 221 | const result = await sdk.getInstance( 222 | instanceYaml.org, 223 | instanceYaml.stage, 224 | instanceYaml.app, 225 | instanceYaml.name 226 | ) 227 | 228 | expect(result.instance.instanceStatus).toEqual('inactive') 229 | }) 230 | -------------------------------------------------------------------------------- /serverless.component.yml: -------------------------------------------------------------------------------- 1 | name: apigateway 2 | version: 0.4.2 3 | author: 'Tencent Cloud, Inc' 4 | org: 'Tencent Cloud, Inc' 5 | description: API 网关组件, 允许用户创建部署一个 API 网关。 6 | keywords: 'tencent, serverless, apigateway' 7 | repo: 'https://github.com/serverless-components/tencent-apigateway' 8 | readme: 'https://github.com/serverless-components/tencent-apigateway/tree/master/README.md' 9 | license: MIT 10 | main: ./src 11 | webDeployable: false 12 | 13 | actions: 14 | deploy: 15 | definition: Easily provision Tencent API Gateway 16 | inputs: 17 | serviceId: 18 | type: string 19 | regex: '^service-(\w){8,}$' 20 | instanceId: 21 | type: string 22 | serviceName: 23 | type: string 24 | description: Name of API Gateway 25 | default: serverless 26 | regex: '^[a-zA-Z][a-zA-Z0-9(_)]{0,48}[a-zA-Z0-9]?$' 27 | serviceDesc: 28 | type: string 29 | default: Created by Serverless Component 30 | region: 31 | type: string 32 | default: ap-guangzhou 33 | description: Region for API Gateway 34 | protocols: 35 | type: array 36 | default: 37 | - http 38 | items: 39 | - type: string 40 | allow: 41 | - http 42 | - https 43 | netTypes: 44 | type: array 45 | default: 46 | - OUTER 47 | items: 48 | - type: string 49 | allow: 50 | - OUTER 51 | - INNER 52 | environment: 53 | type: string 54 | default: release 55 | allow: 56 | - release 57 | - test 58 | - prepub 59 | endpoints: 60 | type: array 61 | items: 62 | - type: object 63 | keys: 64 | path: 65 | type: string 66 | method: 67 | type: string 68 | allow: 69 | - ANY 70 | - GET 71 | - POST 72 | - PUT 73 | - DELETE 74 | - HEAD 75 | apiName: 76 | type: string 77 | apiDesc: 78 | type: string 79 | enableCORS: 80 | type: boolean 81 | serviceType: 82 | type: string 83 | allow: 84 | - SCF 85 | - WEBSOCKET 86 | - MOCK 87 | - HTTP 88 | authType: 89 | type: string 90 | allow: 91 | - NONE 92 | - SECRET 93 | - OAUTH 94 | - APP 95 | app: 96 | type: object 97 | keys: 98 | name: 99 | type: string 100 | id: 101 | type: string 102 | description: 103 | type: string 104 | businessType: 105 | type: string 106 | allow: 107 | - NORMAL 108 | - OAUTH 109 | responseType: 110 | type: string 111 | allow: 112 | - HTML 113 | - JSON 114 | - TEST 115 | - BINARY 116 | - XML 117 | serviceTimeout: 118 | type: number 119 | min: 1 120 | max: 1800 121 | # be is HTTP 122 | serviceConfig: 123 | type: object 124 | keys: 125 | url: 126 | type: string 127 | path: 128 | type: string 129 | method: 130 | type: string 131 | allow: 132 | - ANY 133 | - GET 134 | - POST 135 | - PUT 136 | - DELETE 137 | - HEAD 138 | oauthConfig: 139 | type: object 140 | keys: 141 | loginRedirectUrl: 142 | type: string 143 | publicKey: 144 | type: string 145 | tokenLocation: 146 | type: string 147 | allow: 148 | - authorization 149 | - cookie 150 | authRelationApi: 151 | type: object 152 | keys: 153 | path: 154 | type: string 155 | method: 156 | type: string 157 | allow: 158 | - ANY 159 | - GET 160 | - POST 161 | - PUT 162 | - DELETE 163 | - HEAD 164 | # param for frontend request 165 | param: 166 | type: array 167 | items: 168 | - type: object 169 | keys: 170 | name: 171 | type: string 172 | position: 173 | type: string 174 | allow: 175 | - PATH 176 | - HEADER 177 | - QUERY 178 | - BODY 179 | required: 180 | type: boolean 181 | type: 182 | type: string 183 | allow: 184 | - string 185 | - int 186 | - long 187 | - float 188 | - double 189 | - boolean 190 | desc: 191 | type: string 192 | function: 193 | type: object 194 | keys: 195 | # for SCF 196 | isIntegratedResponse: 197 | type: boolean 198 | functionQualifier: 199 | type: string 200 | functionName: 201 | type: string 202 | # for ws 203 | transportFunctionName: 204 | type: string 205 | registerFunctionName: 206 | type: string 207 | cleanupFunctionName: 208 | type: string 209 | # customize domains 210 | customDomains: 211 | type: array 212 | items: 213 | - type: object 214 | keys: 215 | domain: 216 | type: string 217 | required: true 218 | certificateId: 219 | type: string 220 | isDefaultMapping: 221 | type: boolean 222 | pathMappingSet: 223 | type: array 224 | items: 225 | - type: object 226 | keys: 227 | path: 228 | type: string 229 | environment: 230 | type: string 231 | allow: 232 | - release 233 | - test 234 | - prepub 235 | protocols: 236 | type: array 237 | items: 238 | - type: string 239 | allow: 240 | - http 241 | - https 242 | remove: 243 | definition: Remove your Express.js application 244 | -------------------------------------------------------------------------------- /docs/configure.md: -------------------------------------------------------------------------------- 1 | # 配置文档 2 | 3 | ## 完整配置 4 | 5 | ```yml 6 | # serverless.yml 7 | 8 | org: orgDemo #(可选) 用于记录组织信息,默认值为您的腾讯云账户 appid 9 | app: appDemo #(可选) 该应用名称 10 | stage: dev #(可选) 用于区分环境信息,默认值为 dev 11 | component: apigateway # (必填) 组件名称,此处为 apigateway 12 | name: apigwDemo # (必填) 实例名称 13 | 14 | inputs: 15 | serviceId: service-8dsikiq6 16 | region: ap-shanghai 17 | protocols: 18 | - http 19 | - https 20 | serviceName: serverless 21 | serviceDesc: the serverless service 22 | environment: release 23 | netTypes: 24 | - OUTER 25 | - INNER 26 | customDomains: 27 | - domain: abc.com 28 | # 如要添加https,需先行在腾讯云-SSL证书进行认证获取cettificateId 29 | certificateId: abcdefg 30 | isForcedHttps: true # 是否强制https,如果为true,必须配置 certificateId (SSL证书 ID) 31 | # 如要设置自定义路径映射,请设置为 false 32 | isDefaultMapping: false 33 | pathMappingSet: 34 | - path: / 35 | environment: release 36 | protocols: 37 | - http 38 | - https 39 | endpoints: 40 | # 前端类型: WEBSOCKET, 后端类型: SCF 41 | - path: / 42 | method: GET 43 | protocol: WEBSOCKET 44 | function: 45 | # 前端类型为WEBSOCKET且后端为SCF时, transportFunctionName 为是 46 | transportFunctionName: myFunction 47 | registerFunctionName: myFunction 48 | cleanupFunctionName: myFunction 49 | # 前端类型: WEBSOCKET, 后端类型: HTTP 50 | - path: /ws 51 | protocol: WEBSOCKET 52 | apiName: 'test-ws' 53 | method: GET 54 | serviceType: WEBSOCKET 55 | serviceConfig: 56 | url: 'ws://www.test.com' 57 | path: / 58 | method: GET 59 | # 前端类型: HTTP, 后端类型: SCF 60 | - path: /test/{abc}/{cde} 61 | apiId: api-id 62 | apiDesc: Serverless REST API 63 | method: GET 64 | enableCORS: true 65 | responseType: HTML 66 | serviceTimeout: 10 67 | isBase64Encoded: false 68 | isBase64Trigger: false 69 | base64EncodedTriggerRules: 70 | - name: Accept 71 | value: 72 | - image/jpeg 73 | - name: Content_Type 74 | value: 75 | - image/jpeg 76 | param: 77 | - name: abc 78 | position: PATH 79 | required: 'TRUE' 80 | type: string 81 | defaultValue: abc 82 | desc: mytest 83 | - name: cde 84 | position: PATH 85 | required: 'TRUE' 86 | type: string 87 | defaultValue: abc 88 | desc: mytest 89 | function: 90 | isIntegratedResponse: true 91 | functionQualifier: $LATEST 92 | functionName: myFunction 93 | usagePlan: 94 | usagePlanId: 1111 95 | usagePlanName: slscmp 96 | usagePlanDesc: sls create 97 | maxRequestNum: -1 98 | maxRequestNumPreSec: 1000 99 | auth: 100 | secretName: secret 101 | secretIds: 102 | - xxx 103 | # 前端类型: HTTP, 后端类型: MOCK 104 | - path: /mo 105 | protocol: HTTP 106 | method: GET 107 | apiName: 'mock-api' 108 | serviceType: MOCK 109 | serviceMockReturnMessage: 'mock response content' 110 | # 前端类型: HTTP, 后端类型: HTTP 111 | - path: /rest 112 | protocol: HTTP 113 | apiName: 'test-http' 114 | method: GET 115 | serviceType: HTTP 116 | serviceConfig: 117 | url: 'http://www.test.com' 118 | path: /test 119 | method: GET 120 | # 下面两个为互相关联的 oauth2.0 接口示例 121 | # 参考文档 https://cloud.tencent.com/document/product/628/38393 122 | - path: '/oauth' 123 | protocol: 'HTTP' 124 | method: 'GET' 125 | apiName: 'oauthapi' 126 | authType: 'OAUTH' 127 | businessType: 'OAUTH' 128 | serviceType: 'HTTP' 129 | serviceConfig: 130 | method: 'GET' 131 | path: '/check' 132 | url: 'http://10.64.47.103:9090' 133 | oauthConfig: 134 | loginRedirectUrl: 'http://10.64.47.103:9090/code' 135 | publicKey: '{"e":"AQAB","kty":"RSA","n":"dkdd"}' 136 | tokenLocation: 'method.req.header.authorization' 137 | # // tokenLocation: 'method.req.header.cookie', 138 | - path: '/oauthwork' 139 | protocol: 'HTTP' 140 | method: 'GET' 141 | apiName: 'business' 142 | authType: 'OAUTH' 143 | businessType: 'NORMAL' 144 | authRelationApi: 145 | path: '/oauth' 146 | method: 'GET' 147 | serviceType: 'MOCK' 148 | serviceMockReturnMessage: 'helloworld' 149 | ``` 150 | 151 | ## 配置说明 152 | 153 | ### 主要函数说明 154 | 155 | | 参数 | 必选 | 参数类型 | 默认值 | 描述 | 156 | | ------------- | :--: | :-----------------------------: | :------------: | :------------------------------------------------------------------------- | 157 | | serviceId | 否 | string | | 网关服务 ID | 158 | | instanceId | 否 | string | | 网关实例 ID,填写则使用独享型实例创建 API 网关,否则创建共享型实例(该项只能在创建时指定,创建后无法修改) | 159 | | region | 是 | string | `ap-guangzhou` | 服务的部署区域 | 160 | | protocols | 是 | string[] | `['http']` | 服务的前端请求类型,http 和 https | 161 | | serviceName | 否 | string | `serverless` | 用户自定义的服务名称。 如果该参数未传递,则由系统自动生成一个唯一名称 | 162 | | netTypes | 否 | string[] | `['OUTER']` | 网络类型列表,用于指定支持的访问类型,INNER 为内网访问,OUTER 为外网访问。 | 163 | | serviceDesc | 否 | string | | 用户自定义的服务描述说明 | 164 | | environment | 是 | string | `release` | 服务要发布的环境的名称,支持三种环境: test、prepub、 release | 165 | | endpoints | 是 | [Endpoint](#Endpoint)[] | | API,配置参数参考、 | 166 | | customDomains | 否 | [CustomDomain](#CustomDomain)[] | `[]` | 自定义域名 | 167 | 168 | ### Endpoint 169 | 170 | API 参数说明 171 | 172 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 173 | | ------------------------- | :--: | :-----------------------------------: | :------: | :---------------------------------------------------------------------------------------------------------------- | 174 | | apiId | 否 | string | | API 的唯一 ID | 175 | | protocol | 否 | string | `HTTP` | 指定的前端 API 类型,支持 `HTTP`、`WEBSOCKET` | 176 | | path | 是 | string | | API 路径 | 177 | | method | 是 | string | | 请求方法 | 178 | | serviceType | 否 | string | `SCF` | 指定的后端类型,支持:`SCF`、`HTTP`、MOCK | 179 | | description | 否 | string | | API 描述 | 180 | | enableCORS | 否 | boolean | `false` | 是否启用跨域访问。 true:启用, false:不启用 | 181 | | function | 是 | [Function](#Function) | | 对应的 Serverless 云函数 | 182 | | usagePlan | 否 | [UsagePlan](#UsagePlan) | | 基于 API 维度的使用计划 | 183 | | auth | 否 | [SecretAuth](#SecretAuth) | | API 密钥鉴权设置 | 184 | | serviceTimeout | 否 | number | `15` | API 的后端服务超时时间,单位为秒 | 185 | | responseType | 否 | string | | 返回类型: `HTML`、`JSON`、`TEST`、`BINARY`、`XML` | 186 | | param | 否 | [RequestParameter](#RequestParameter) | | 前端请求参数 | 187 | | serviceConfig | 否 | [ServiceConfig](#ServiceConfig) | | API 的后端服务配置 | 188 | | serviceMockReturnMessage | 否 | string | | Mock 接口类型返回结果,如果 `serviceType` 设置为 `MOCK`,此参数必须 | 189 | | authType | 否 | string | `NONE` | 鉴权类型,支持:`NONE`(免鉴权)、`SECRET`(密钥对),`OAUTH`(Oauth2.0),`APP`(应用鉴权) | 190 | | app | 否 | [App](#App) | `NONE` | API 绑定 APP 配置 | 191 | | businessType | 否 | string | `NORMAL` | 业务类型,支持:`NORMAL`、`OAUTH` | 192 | | oauthConfig | 否 | [OauthConfig](#OauthConfig) | | Oauth2.0 鉴权,授业 API 后端配置,当 `authType` 为 `OAUTH`, 并且 businessType 为 `OAUTH` 时,此参数必须 | 193 | | authRelationApi | 否 | [AuthRelationApi](#AuthRelationApi) | | Oauth2.0 鉴权,业务 API 关联授业 API 配置,当 `authType` 为 `OAUTH`, 并且 businessType 为 `NORMAL` 时,此参数必须 | 194 | | isBase64Encoded | 否 | boolean | `false` | 是否开启 Base64 编码,只有后端为 scf 时才会生效 | 195 | | isBase64Trigger | 否 | boolean | `false` | 是否开启 Base64 编码的 header 触发,只有后端为 scf 时才会生效 | 196 | | base64EncodedTriggerRules | 否 | [Base64Rule](#Base64Rule)[] | [] | Header 触发 Base64 编码规则,总规则数不能超过 10,只有 `isBase64Trigger` 设置为 `true` 才有效 | 197 | 198 | - API 类型补充说明 199 | 200 | | 前端 API 类型 (参数:protocol) | 后端服务类型 (参数:serviceType) | 201 | | ----------------------------- | ------------------------------- | 202 | | HTTP (默认) | SCF (默认) | 203 | | | HTTP | 204 | | | MOCK | 205 | | WEBSOCKET | SCF (默认) | 206 | | | WEBSOCKET | 207 | 208 | ### Function 209 | 210 | 关联云函数参数配置 211 | 212 | > 此时 `serviceType` 必须为 `SCF` 213 | 214 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 215 | | --------------------- | :--: | :-----: | :--------: | :----------------------------------------------- | 216 | | isIntegratedResponse | 否 | boolean | `false` | 是否开启响应集成,当前端类型为`HTTP`时生效 | 217 | | functionQualifier | 否 | string | `$DEFAULT` | scf 函数版本 | 218 | | functionName | 是 | string | | 云函数的名称 | 219 | | transportFunctionName | 否 | string | | 传输函数的名称,`protocol` 为 `WEBSOCKET` 时必须 | 220 | | registerFunctionName | 否 | string | | 注册函数的名称,`protocol` 为 `WEBSOCKET` 时必须 | 221 | | cleanupFunctionName | 否 | string | | 清理函数的名称,`protocol` 为 `WEBSOCKET` 时必须 | 222 | 223 | ### ServiceConfig 224 | 225 | API 的后端服务配置 226 | 227 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 228 | | ------ | :--: | :----: | :----: | :----------------------------------------------------------------- | 229 | | url | 是 | string | | API 的后端服务 url,如果 `serviceType` 是 `HTTP`,则此参数必传 | 230 | | path | 是 | string | | API 的后端服务路径,如果 `serviceType` 是 `HTTP`,则此参数必传 | 231 | | method | 是 | string | | API 的后端服务请求方法,如果 `serviceType` 是 `HTTP`,则此参数必传 | 232 | 233 | ### UsagePlan 234 | 235 | 使用计划参数说明 236 | 237 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 238 | | ------------------- | :--: | :----: | :----: | :---------------------------------------------- | 239 | | usagePlanId | 是 | string | | 用户自定义的基于 API 的使用计划 ID | 240 | | usagePlanName | 是 | string | | 用户自定义的基于 API 的使用计划名称 | 241 | | usagePlanDesc | 是 | string | | 用户自定义的基于 API 的使用计划描述 | 242 | | maxRequestNum | 是 | number | `-1` | 允许的请求总数。默认情况下将使用 `-1`,表示禁用 | 243 | | maxRequestNumPreSec | 是 | number | `-1` | 每秒最大请求数。默认情况下将使用 `-1`,表示禁用 | 244 | 245 | ### SecretAuth 246 | 247 | 密钥鉴权参数说明 248 | 249 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 250 | | ---------- | :--: | :------: | :----: | :-------------------- | 251 | | secretName | 是 | string | | 用户自定义的密钥名称 | 252 | | secretIds | 否 | string[] | | 用户自定义的 SecretId | 253 | 254 | ### RequestParameter 255 | 256 | 前端请求参数说明 257 | 258 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 259 | | ------------ | :--: | :-----: | :----: | :-------------------------------------------- | 260 | | name | 是 | string | | 请求参数名称 | 261 | | position | 是 | string | | 参数位置,仅支持`PATH`,`QUERY`和`HEADER`类型 | 262 | | type | 是 | string | | 参数类型,如 String 和 int. | 263 | | defaultValue | 是 | string | | 参数默认值 | 264 | | required | 是 | boolean | | 参数是否是, true: 是; false: 否 | 265 | | desc | 是 | string | | 参数备注/描述 | 266 | 267 | ### CustomDomain 268 | 269 | 自定义域名 270 | 271 | | 参数 | 必选 | 类型 | 默认值 | | 描述 | 272 | | ---------------- | :--: | :-------------------: | :--------: | :-------------------------------------------------------------- | ---- | 273 | | domain | 是 | string | | 需要绑定的自定义域名 | 274 | | certificateId | 否 | string | | 自定义域名的证书,如果设置为 https,则为必需。 | 275 | | isDefaultMapping | 否 | boolean | `true` | 是否使用默认路径映射。 如果要自定义路径映射,请设为`false` | 276 | | pathMappingSet | 否 | [PathMap](#PathMap)[] | `[]` | 自定义路径映射, 当 `isDefaultMapping` 为 `false` 时,此参数必须 | 277 | | protocols | 否 | string[] | `['http']` | 绑定自定义域协议类型,支持 http 和 https | 278 | | isForcedHttps | 否 | boolean | `false` | 是否强制 HTTPS。 | 279 | 280 | ### PathMap 281 | 282 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 283 | | ----------- | :--: | :----: | :----: | :------------- | 284 | | path | 是 | string | | 自定义映射路径 | 285 | | environment | 是 | string | | 自定义映射环境 | 286 | 287 | ### OauthConfig 288 | 289 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 290 | | ---------------- | :--: | :----: | :----: | :---------------------------------------------------------------------------------- | 291 | | loginRedirectUrl | 是 | string | | 重定向地址,用于引导用户登录操作 | 292 | | publicKey | 是 | string | | 公钥,用于验证用户 token | 293 | | tokenLocation | 是 | string | | token 传递位置,支持: `method.req.header.authorization`、`method.req.header.cookie` | 294 | 295 | 有关授业 API 的公钥生成,参考腾讯云官方文档:https://cloud.tencent.com/document/product/628/38393 296 | 297 | ### AuthRelationApi 298 | 299 | Oauth2.0 鉴权,业务 API 关联授业 API 配置,当 `authType` 为 `OAUTH`, 并且 businessType 为 `NORMAL` 时,此参数必须 300 | 301 | | 参数 | 必选 | 类型 | 默认值 | 描述 | 302 | | ------ | :--: | :----: | :----: | :------------------------- | 303 | | path | 是 | string | | 关联 `授业 API` 的请求路径 | 304 | | method | 是 | string | | 关联 `授业 API` 的请求路径 | 305 | 306 | ###### APP 307 | 308 | API 绑定 APP 配置 309 | 310 | 参考:https://cloud.tencent.com/document/product/628/55087 311 | 312 | | 参数名称 | 必选 | 类型 | 描述 | 313 | | ----------- | :--: | :----- | :------------------ | 314 | | name | 否 | string | 用户自定义 APP 名称 | 315 | | id | 否 | string | APP ID | 316 | | description | 否 | string | 用户自定义 APP 描述 | 317 | 318 | ### Base64Rule 319 | 320 | Header 触发 Base64 编码规则,总规则数不能超过 10,只有 `isBase64Trigger` 设置为 `true` 才有效 321 | 322 | 参考: https://tcloud-dev.oa.com/document/product/628/16924?!preview&preview_docmenu=1&lang=cn&!document=1#Base64EncodedTriggerRule 323 | 324 | | 参数名称 | 类型 | 描述 | 325 | | -------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | 326 | | name | string | 进行编码触发的 header,可选值 "Accept"和"Content_Type" 对应实际数据流请求 header 中的 Accept 和 Content-Type | 327 | | value | string[] | 进行编码触发的 header 的可选值数组, 数组元素的字符串最大长度为 40,元素可以包括数字,英文字母以及特殊字符,特殊字符的可选值为: . + \* - / \_ | 328 | 329 | 例如 `value` 可以配置为: 330 | 331 | ```yaml 332 | value: 333 | - application/zip 334 | ``` 335 | 336 | ### 关于 API 网关 Base64 编码 337 | 338 | > 注意:开启 API 网关 Base64 编码的后端必须是 `云函数` 339 | 340 | 如果需要开启 API 网关 Base64 编码,必须配置 `isBase64Encoded` 为 `true`,此时每次请求的请求内容都会被 Base64 编码后再传递给云函数。如果想要部分请求 Base64 编码,可以通过配置 `isBase64Trigger` 为 `true`,配置 `base64EncodedTriggerRules` Header 触发规则,此时 API 网关将根据触发规则对请求头进行校验,只有拥有特定 Content-Type 或 Accept 请求头的请求会被 Base64 编码后再传递给云函数,不满足条件的请求将不进行 Base64 编码,直接传递给云函数。 341 | 342 | 官方介绍文档:https://cloud.tencent.com/document/product/628/51799 343 | --------------------------------------------------------------------------------