pmax-gateway

A microservices API gateway built on top of ExpressJS

Usage no npm install needed!

<script type="module">
  import pmaxGateway from 'https://cdn.skypack.dev/pmax-gateway';
</script>

README

API GATEWAY

NOTE: Pls check your Content-Length, if Content-Length incorrect, server not response to you.

  • API gateway that proxies all the micro-services
  • Handle authentication
  • Rate request

Prerequisites

Docker networks

Create network docker

docker network create api_gateway

Get network docker info

docker network inspect api_gateway

Setup API GATEWAY

  1. Clone api_gateway

  2. open terminal on root project

  • step 1: build with docker-compose
    docker-compose up --build
  • step 2: go to localhost:3002 or your IP - 0.0.0.0:3002

  • step 3: run command

    docker-compose up -d

Add new service

  • After add new serice to api_gateway, you need to add your service to network layer, example api_gateway and define container name
  • Map service to api_gateway:

Go to /config/gateway.config.yml

Intro

  • endpoints: Endpoints are URLs. API Gateway has two different types of endpoints:

    • API endpoints
    • Service endpoints API Gateway expose APIs through API endpoints. As a gateway, it proxies API requests from API endpoints to microservices referenced in service endpoints.
  • policies: A policy is a set of conditions, action and parameters that are evaluated and act on the API request and response flow within API Gateway. Policies within API Gateway utilize API middleware.

  • pipelines: A pipeline is a set of policies linked to a set of API endpoints. Policies within a pipeline are evaluated and executed sequentially. An API request is received by the API endpoint and routed through the pipeline for policy execution. The last policy within a pipeline is often a proxy policy that will routes the request to a service endpoint.

apiEndpoints

  • Description: API Gateway exposes microservices as APIs through URLs known as apiEndpoints. API consumers may make API requests through the API endpoints.

  • Usage:

apiEndpoints:
  help:                 # name, used as reference in pipeline
    host: '*'           # required, '*' will not check for host name
    paths: /help        # optional, by default will serve all requests - same as *

  api:                  # name, used as reference in pipeline
    host: '*.com'       # wildcard pattern support
    paths:
      - '/v1/*'         # string or array of strings
      - '/v2/*'

  example:              # name, used as reference in pipeline
    host: 'example.com'
    paths: /v2/*        # string or array of strings

  example2:              # It is possible to provide an array of matching conditions in the same apiEndpoint
    - host: 'example2.com'
      paths: /v2/*
      methods: ["GET", "OPTIONS"]
      scopes: ["example2:read"]

    - host: 'example2.com'
      paths: /v2/*
      methods: ["PUT", "POST", "PATCH", "DELETE"]
      scopes: ["example2:write"]
  • Options
Name Description
host the hostname to accept requests on
paths an array of paths
methods an array of methods required to accept requests on
scopes an array of scopes required to access such resource
  • Host The host value is a string that will be matched against the ‘HOST’ header of the request.

Examples: Any Domain and Path

apiEndpoints:
  help:
    host: '*'
    paths: /help

Match: cdn.test.example.com/help, example.com/help, no HOST header 404: cdn.test.example.com, example.com/admin

One Domain with No Subdomains and Path

apiEndpoints:
  help:
    host: 'example.com'
    paths: /help

Match: example.com/help 404: test.example.com/help, example.com

Any 1st Level Subdomain of One Domain and Path

apiEndpoints:
  help:
    host: '*.example.com'
    paths: /help
  • Paths Paths can be either a string or array of strings. Wildcard patterns are supported. Paths follow the APIJS routes conventions - Link

Examples:

Exact String Match

  • paths: /admin
  • match: /admin only
  • 404: /admin/bob; /admin/charlie/1; /staff

Deep Level Match without Parent

  • paths: /admin/*
  • match: /admin/bob; /admin/charlie/1
  • 404: /admin

Deep Level Match with Parent

  • paths: ['/admin','/admin/*']
  • match: /admin; /admin/bob; /admin/charlie/1
  • 404: /staff

One Level Match without Parent with Variable Assignment

  • paths: '/admin/:id'
  • match: /admin/bob; /admin/charlie
  • id: bob; charlie
  • 404: /admin; /staff

Multi level Sub Dir Match without Parent with Variable Assignments

  • paths: '/admin/:group/:id'
  • match: /admin/ops/bob
  • group: ops
  • id: bob
  • 404: /admin; /admin/bob; /admin/alex/bob/charlie

Multi Multiple Level Sub Dir Match without Parent

  • paths: ['/student/*', '/teacher/*','/admin/*']
  • match: - /admin/… multi-level - /student/… multi-level - /teacher/… multi-level
  • 404: - / - /admin; /teacher; /student - /staff

Overlapping The order of the API endpoints specified matters. It is possible to specifiy overlapping patterns through wildcards. More specific patterns should be specified first for prioritized evaluation before more general matching.

Example:

apiEndpoints:
  tabby:
    host: '*.tabby.cat.com'
    paths: '*'                # optional, if not specified will default to *
  cat:
    host: '*.cat.com'
  com:
    host: '*.com'
  • Scopes The scopes value is an array of strings that specifies the required scopes that the current credential needs to have in order to access the resource.

Example apiEndpoints: tabby: host: '.tabby.cat.com' paths: '' scopes: - read - write - delete The following api endpoint will be accesible only if the current user has read, write and delete scopes.

serviceEndpoints

  • Description: API Gateway receives API requests on apiEndpoints, processes them, and then proxies them to downstream microservices. The serviceEndpoints section specifies the URLs of these proxied microservices.
  • Usage:
serviceEndpoints:             # downstream microservices
  cats:                       # name, used as a reference in pipeline
    url: "http://auth_service"
  dogs:                       # name, used as a reference in pipeline
    urls:                     # multiple urls can be used with load balancing
      - "http://dogs1.example.com"
      - "http://dogs2.example.com"
  • Description A serviceEndpoint must have either a url property with a single string or a urls property with an array of strings.
  • Options
Name Description
url the protocol and hostname to proxy requests to
urls an array of URLs, used with load balancing

pipelines

  • Description The pipelines section specify the core API Gateway’s operations by tying together all entities declared in the sections above, through the request and response flow.

Pipelines are an ordered list of policies that are executed for requests received from all linked apiEndpoints.

  • Usage Below is a gateway.config.yml that will start API Gateway on http port 3000. It exposes an single apiEndpoint named ‘api’ that listens on all hosts at the root (/) path. There is one pipeline named ‘default’ that will process all requests for the ‘api’.
http:
  port: 3000

serviceEndpoints:
  example: # will be referenced in proxy policy
    url: 'http://example.com'

apiEndpoints:
  api:
    host: '*'
    paths: /

pipelines:
  default:
    apiEndpoints:
      - api
    policies:
      -
        simple-logger: # policy name
          -   # array of objects with condition\action properties
            condition: #optional,; defaults to always execute
              name: pathExact
              path: /v1
            action:
              message: "${req.method} ${req.originalUrl}"
      -
        proxy: # policy name
          -    # array of objects with condition\action properties
            action:
              serviceEndpoint: example # see declaration above
  • Condition/Action Objects in Policy Policy contains a list of actions with parameters. Each action can be gated by a condition.
Name Required Description
condition Optional A rule that must be satisfied to trigger its corresponding action
action Action Parameters for for this specific step

Full example

http:
  port: 3000
apiEndpoints:
  login:
    host: '*'
    paths: /api/v1/login
    methods: ["POST"]
    scopes: ["auth:read"]
  auth:
    host: '*'
    paths: /api/v1/auth*
    methods: ["POST", "GET"]
    scopes: ["auth:read"]
serviceEndpoints:
  auth:
    url: 'http://service_auth'
policies:
  - shd_jwt
  - shd_rewrite
  - proxy
  - rate-limit
pipelines:
  auth:
    apiEndpoints:
      - auth
    policies:
      - shd_jwt:
      - rate-limit:
          - action:
              max: 60
              windowMs: 1000
      - proxy:
          - action:
              serviceEndpoint: auth
              changeOrigin: true
  auth2:
    apiEndpoints:
      - login
    policies:
      - shd_rewrite:
          - action:
              search: /api/v1/login
              replace: /api/v1/auth/login
      - rate-limit:
          - action:
              max: 60
              windowMs: 1000
      - proxy:
          - action:
              serviceEndpoint: auth
              changeOrigin: true