Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
A dynamic API Gateway which updates REST endpoints, GraphQL schema, WebSocket handlers and access control policies by integrating metadata of discovered remote services.
moleculer-api는 MSA 환경에서 마이크로 서비스들의 API 스키마 조각을 수집하고, 무중단으로 통합 API를 업데이트하여 제공하는 웹 서버 컴포넌트입니다.
서비스 API 스키마는 분산 서비스 프로시저의 호출, 또는 중앙 메시징 서비스에 대한 이벤트 발행 및 구독을 응용 프로토콜(REST, GraphQL, WebSocket 등)에 맵핑합니다. 서비스 API 스키마는 JSON 포맷으로 구성되어있으며, 응용 프로토콜 별 API 맵핑과 그에 대한 접근 제어로 구성되어 있습니다.
{
branch: "master",
policy: {},
protocol: {
REST: {
basePath: "/storage",
routes: [
{
path: "/",
method: "GET",
call: {
action: "storage.get",
params: {
offset: "@query.offset:number",
limit: "@query.limit:number",
},
},
},
{
path: "/upload",
method: "POST",
call: {
action: "storage.create",
params: {
file: "@body.file",
meta: {
tags: {
identityId: "@context.auth.identity.sub",
},
allowedContentTypes: ["text/*", "image/*", "application/pdf"],
private: false,
},
},
},
},
{
path: "/upload-stream",
method: "POST",
description: "not a production purpose, need a wrapper action to make this safe",
call: {
action: "storage.createWithStream",
params: "@body.file",
implicitParams: false,
},
},
{
path: "/download/:id",
method: "GET",
call: {
action: "storage.getURL",
params: {
id: "@path.id",
expiryHours: "@query.expiryHours:number",
prompt: "@query.prompt:boolean",
promptAs: "@query.promptAs:string",
},
map: `({ response }) => ({
$status: response ? 303 : 404,
$headers: response ? { "Location": response } : undefined,
})`,
},
},
{
path: "/:id",
method: "GET",
call: {
action: "storage.find",
params: {
id: "@path.id",
},
map: `({ response }) => ({
$status: response ? 200 : 404,
$body: response,
})`,
},
},
{
path: "/:id",
method: "PUT",
call: {
action: "storage.update",
params: {
id: "@path.id",
// id, name, tags, private, contentType
},
},
},
{
path: "/:id",
method: "DELETE",
call: {
action: "storage.delete",
params: {
id: "@path.id",
},
},
},
],
},
},
}
{
branch: "master",
policy: {},
protocol: {
GraphQL: {
typeDefs: `
extend type Query {
storage: StorageQuery!
}
type StorageQuery {
files(offset: Int = 0, limit: Int = 10): FileList!
file(id: ID!): File
}
type File {
id: ID!
name: String!
contentType: String!
tags: JSON!
private: Boolean!
byteSize: Int!
size: String!
url(expiryHours: Int = 2, prompt: Boolean = false, promptAs: String): String!
updatedAt: DateTime!
createdAt: DateTime!
}
type FileList {
offset: Int!
limit: Int!
# it is not exact value
total: Int!
entries: [File!]!
hasNext: Boolean!
hasPrev: Boolean!
}
extend type Mutation {
storage: StorageMutation!
}
type StorageMutation {
upload(file: Upload!): File!
update(id: ID!, name: String, tags: JSON, private: Boolean): File!
delete(id: ID!): Boolean!
}
`,
resolvers: {
Query: {
storage: `() => ({})`,
},
Mutation: {
storage: `() => ({})`,
},
StorageMutation: {
upload: {
call: {
action: "storage.create",
params: {
file: "@args.file",
meta: {
allowedContentTypes: [],
private: false,
},
},
},
},
update: {
call: {
action: "storage.update",
params: {},
},
},
delete: {
call: {
action: "storage.delete",
params: {},
}
},
},
StorageQuery: {
file: {
call: {
action: "storage.find",
params: {
id: "@args.id[]",
},
},
},
files: {
call: {
action: "storage.get",
params: {
offset: "@args.offset",
limit: "@args.limit",
},
},
},
},
File: {
url: {
call: {
action: "storage.getURL",
params: {
id: "@source.id[]",
expiryHours: "@args.expiryHours",
prompt: "@args.prompt",
promptAs: "@args.promptAs",
},
},
},
size: (({ source }: any) => {
const { byteSize = 0 } = source;
const boundary = 1000;
if (byteSize < boundary) {
return `${byteSize} B`;
}
let div = boundary;
let exp = 0;
for (let n = byteSize / boundary; n >= boundary; n /= boundary) {
div *= boundary;
exp++;
}
const size = byteSize / div;
return `${isNaN(size) ? "-" : size.toLocaleString()} ${"KMGTPE"[exp]}B`;
}).toString(),
},
FileList: {
hasPrev: `({ source }) => source.offset > 0`,
}
},
},
},
}
{
branch: "master",
policy: {
call: [
{
actions: ["user.update"],
description: "A user can update the user profile which is belongs to own account.",
scope: ["user.write"],
filter: (({ context, params }) => {
console.log(context);
if (params.id) {
return context.auth.identity.sub === params.id;
}
return false;
}).toString(),
},
],
},
protocol: {
GraphQL: {
typeDefs: `
extend type Query {
viewer: User
user(id: Int, identityId: String, username: String, where: JSON): User
}
extend type Mutation {
createUser(input: UserInput!): User!
updateUser(input: UserInput!): User!
}
input SportsUserInput {
id: Int
username: String
birthdate: Date
gender: Gender
name: String
pictureFileId: String
}
type User {
id: Int!
username: String!
name: String!
birthdate: Date
gender: Gender
pictureFile: File
}
`,
resolvers: {
User: {
pictureFile: {
call: {
if: "({ source }) => !!source.pictureFileId",
action: "storage.find",
params: {
id: "@source.pictureFileId[]",
},
},
},
},
Mutation: {
createUser: {
call: {
action: "user.create",
params: "@args.input",
implicitParams: false,
},
},
updateUser: {
call: {
action: "user.update",
params: "@args.input",
implicitParams: false,
},
},
},
},
},
},
}
{
branch: "master",
policy: {},
protocol: {
REST: {
description: "update user's FCM registration token",
basePath: "/notification",
routes: [
{
method: "PUT",
path: "/update-token",
call: {
action: "notification.updateToken",
params: {
identityId: "@context.auth.identity.sub",
token: "@body.token",
},
},
},
],
},
},
}
{
branch: "master",
policy: {},
protocol: {
WebSocket: {
basePath: "/chat",
description: "...",
routes: [
/* bidirectional streaming chat */
{
path: "/message-stream/:roomId",
call: {
action: "chat.message.stream",
params: {
roomId: "@path.roomId",
},
},
},
/* pub/sub chat */
{
path: "/message-pubsub/:roomId",
subscribe: {
events: `({ path }) => ["chat.message." + path.roomId]`,
},
publish: {
event: `({ path }) => "chat.message." + path.roomId`,
params: "@message",
},
},
/* pub/sub video */
{
path: "/video-pubsub",
subscribe: {
events: ["chat.video"],
},
publish: {
event: "chat.video",
params: {
id: "@context.id",
username: "@query.username",
data: "@message",
},
filter: `({ params }) => params.id && params.username && params.data`,
},
},
/* streaming video */
{
path: "/video-stream/:type",
call: {
action: "chat.video.stream",
params: {
id: "@context.id",
type: "@path.type",
},
},
},
],
},
},
}
Gateway는 특정 서비스 API 스키마의 추가, 제거 및 업데이트시 기존 통합 API 스키마에 병합을 시도하고, 성공시 무중단으로 라우터를 업데이트하며 그 결과를 원격 서비스에 다시 보고합니다.
분산 서비스의 API 스키마를 수집하고 병합하여 API를 실시간으로 업데이트
Polyglot 하거나 서로 다른 서비스 브로커에 기반한 서비스들의 API 스키마를 수집하고 병합 할 수 있음
개발 편의 및 충돌 방지를 위한 API 브랜칭 및 버저닝 기능
상태 검사 및 API 문서 생성 (WIP)
미들웨어 방식의 요청 흐름 제어
Error
Logging
Body Parser
Helmet
CORS
Serve Static File
HTTP/HTTPS/HTTP2
(확장 가능)
미들웨어 방식의 컨텍스트 생성 제어
Authn/Authz
Locale
Correlation ID
IP Address
User-Agent
Request
(확장 가능)
응용 프로토콜 플러그인
REST
GraphQL
WebSocket
(확장 가능)
접근 제어 정책 플러그인
OAuth2 scope 기반 접근 제어
JavaScript FBAC; Function Based Access Control 기반 접근 제어
(확장 가능)
The project is available under the MIT license.
API Gateway는 최초에 Moleculer MSA 라이브러리를 배경으로 개발되었지만, 확장성을 위해서 강한 디커플링을 방침으로 개발되고 있습니다.
API Gateway는 분산 서비스 및 중앙 메시징 서비스와의 네트워킹을 서비스 브로커에게 위임합니다. 서비스 브로커는 분산 서비스들의 네트워킹을 위임 받으며, call
, publish
, subscribe
, discover
, report
등의 주요 네트워킹 인터페이스(커넥터)를 가진 어댑터와 결합됩니다.
Service Broker
서비스 브로커는 분산 서비스들의 네트워킹을 위임 받으며, call
, publish
, subscribe
, discover
, report
등의 주요 네트워킹 인터페이스(커넥터)를 가진 어댑터와 결합됩니다.
브로커는 위 커넥터들의 특정 인터페이스를 구현하는 단일한 객체로 구현됩니다.
MoleculerAPIGateway
서비스를 minxin에 포함해 moleculer.ServiceSchema
를 확장 할 수 있습니다.
MoleculerServiceBroker
를 이용해 직접 moleculer.ServiceSchema
를 구현 할 수 있습니다.
기타 MSA 라이브러리를 응용해 ServiceBroker
인터페이스를 구현 할 수 있습니다.
예시 코드는 를 참고 할 수 있습니다.
플러그인은 서비스 API 스키마의 포맷과 기능을 확장하는데 쓰입니다. 플러그인은 위임된 스키마에 대한 검증, 해석, 작동 방식을 정의하고 구현합니다.
각 프로토콜 플러그인은 해당 프로토콜 스키마의 양식을 정의하고, 스키마 병합, 요청 프록시, 의존성 파악, 서버 확장 핸들러 등을 구현합니다.
각 접근 제어 플러그인은 해당 접근 제어 스키마의 양식을 정의하고, call
, publish
, subscribe
커넥터의 정책을 해석하고 접근 제어를 판단하는 핸들러를 구현합니다.
프토토콜 플러그인별 스키마 양식은 API Schema 섹션을 참조하십시오. 이 섹션에서는 기본 플러그인의 구동 방식을 개괄적으로 설명합니다.
REST 프로토콜은 분산 서비스에 대한 call
, publish
커넥터를 특정 엔드포인트에 맵핑합니다. HTTP 요청의 Paylo,ad는 미들웨어를 통해 파싱되어 params
커넥터를 통해 변환되어 call
, publish
커넥터로 전달됩니다.
엔드포인트가 중복되는 경우 병합을 발생시킨 출처 노드로 디버그 메세지가 report
되며 병합에 실패합니다.
API Catalog를 통해서 엔드포인트 별 적용된 정책 및 커넥터와 그 파라미터에 대한 설명을 제공합니다.
TODO: $headers, $status, $body field for REST response
GraphQL 프로토콜은 분산 서비스에 대한 call
및 publish
, subscribe
커넥터를 특정 타입의 필드에 맵핑합니다. HTTP 요청의 Payload는 미들웨어를 통해 파싱되어 params
커넥터를 통해 변환되어 call
, publish
, subscribe
, map
커넥터로 전달됩니다.
GraphQL 스키마 생성에 실패하는 경우 병합을 발생시킨 출처 노드로 디버그 메세지가 report
되며 병합에 실패합니다.
API Catalog를 통해서 각 GraphQL Type 별 적용된 정책 및 커넥터와 그 파라미터에 대한 설명을 제공합니다.
서비스 API 스키마를 통해서 GraphQL Custom Scalar 정의를 추가 할 수 없습니다. Gateway 생성시 플러그인 옵션을 통해 Scalar 정의를 추가하거나 오버라이드 할 수 있습니다. 기본적으로 DateTime
, Date
, Time
, JSON
가 포함되어있습니다.
TODO: WIP
요청 상태를 기반으로 API 요청에 활용되는 커넥터입니다. 접근 제어 및 stateless 커넥터를 연계 할 수 있습니다.
커넥터
어댑터에 위임
연결 가능한 커넥터
개요
call
O
params
, map
분산 서비스 액션을 호출합니다.
publish
O
params
중앙 메시징 서비스에 이벤트를 발행합니다.
subscribe
O
map
중앙 메시징 서비스에서 이벤트를 구독합니다.
GraphQL의 Subscription
타입이나 WebSocket 프로토콜 등을 사용하지 않거나, 분산 시스템에 중앙 메시징 서비스를 제공 할 수 없는 경우엔 publish
, subscribe
커넥터를 구현하지 않아도 무관합니다.
요청 상태가 없는 커넥터입니다.
커넥터
어댑터에 위임
개요
map
X
Inline JavaScript Function String을 VM에서 해석하여 주어진 객체나 응답 객체를 변환합니다.
params
X
요청 페이로드에서 위의 타 커넥터들로 전달 할 객체를 생성합니다.
discover
O
분산 서비스의 업데이트나 종료를 감지하고, 노드, 서비스 API Schema, 액션 및 이벤트 구독, 발행 정보를 수집합니다.
health
O
분산 서비스 및 액션, 중앙 메시징 서비스의 상태 확인을 제공합니다.
reporter
O
출처 노드로 디버그 메세지를 전달합니다.
logger
O
Gateway의 로깅 인스턴스를 제공합니다.
서비스 API 스키마는 서비스 브로커에 의존해 Gateway로 수집되고 처리됩니다. Moleculer 어댑터로 작성된 서비스 브로커의 경우 기본적으로 ServiceSchema
의 metadata.api
필드에서 서비스 API 스키마가 수집되기를 기대합니다.
서비스 API 스키마의 병합은 서비스 노드의 연결, 종료, 스키마 변경시 발생합니다. 서비스 API 스키마는 자신의 스키마를 병합 할 브랜치를 스키마에 명시합니다. Gateway에는 기본적으로 master
브랜치가 생성되어있으며, master
브랜치는 제거 될 수 없습니다.
Integration Process
병합 규칙은 다음과 같습니다.
discover
discover
발생 즉시 병합 요청이 생성됩니다.
프로토콜 플러그인을 따라 스키마 포맷에 대한 검증을 거칩니다.
포맷 에러는 병합 요청 메세지 리스트에 포함됩니다.
접근 제어를 우회하는 엔드포인트에 대한 경고가 병합 요청 메세지 리스트에 포합됩니다.
검증 성공시 병합 요청이 큐에 삽입되면서 특정 시간(2초를 기본값) 동안 debounce 후 순차적으로 처리됩니다.
큐에서 특정 서비스에 대한 병합 요청이 다수인 경우 마지막 요소만 유효합니다.
프로토콜 플러그인에서 integrationDependencyResolver
가 구현된 경우 (eg. GraphQL) 큐 안에서 처리 순서가 조정 될 수 있습니다.
검증 실패시 report
단계로 건너 뜁니다.
hash
서비스 API 스키마에서 branch
, description
, deprecated
등의 메타 정보를 제외한 스키마 객체 전체를 MD5 해싱하여 고유한 버전 해시를 생성합니다.
게이트웨이에 버전이 존재하지 않는 경우에는 스키마를 업데이트하기로 합니다.
서비스 노드의 연결이 끊긴 경우는 연관된 스키마의 노드풀에서 노드를 삭제합니다.
이 때 연관된 스키마들에서 노드풀이 빈 스키마들을 제거하기로 합니다.
update
master
브랜치의 스키마는 경우에는 모든 브랜치에 병합이 시도됩니다.
이 때 master
외의 브랜치에서 스키마의 서비스명이 중복되는 경우 병합하지 않습니다. 기존 스키마의 우선 순위가 높습니다.
이외의 브랜치에 병합하는 경우에는 주어진 브랜치에만 병합이 시도됩니다.
프로토콜 플러그인을 따라 각 프로토콜별 핸들러를 생성합니다.
병합에 성공하면 생성된 Gateway API 스키마 버전에 latest
태그 및 8 글자의 숏 해시(eg. abcdefgh
)가 태그로 부착됩니다.
옵션이 활성화된 경우 브랜치별 API Catalog를 업데이트합니다.
옵션이 활성화된 경우 브랜치별 Service Catalog를 업데이트합니다.
report
병합 요청의 메세지 리스트를 기반으로 디버그 메세지를 생성합니다.
병합 요청의 출처 노드로 디버그 메세지를 report
합니다.
Branch Strategy Diagram
브랜치간 병합 전략을 표로 도식하면 다음과 같습니다.
표에서 a@v1
는 a
서비스 스키마 중 v1
버전을 의미합니다.
이벤트/브랜치
master
dongwook
비고
initial schema
(empty)
N/A
a
added to master
a@v1
N/A
a
updated to master
a@v2
N/A
b
added to dongwook
a@v2
a@v2
b@v1
새로운 b
서비스를 dongwook
브랜치로 분기해서 작업; 충돌하지 않는 스키마들은 복제되지 않고 참조됩니다.
a
updated to master
a@v3
a@v3
b@v1
master
브랜치의 업데이트는 모든 브랜치로 전파됩니다.
a
updated to dongwook
a@v3
a@v4
b@v1
master
이외의 브랜치의 업데이트는 자기 브랜치로만 전파됩니다.
a
updated to master
a@v3-2
a@v4
b@v1
충돌하는 경우 자기 브랜치 스키마의 우선 순위가 높습니다.
c
added to master
a@v3-2
c@v1
a@v5
b@v1
c@v1
master
브랜치의 업데이트는 모든 브랜치로 전파됩니다.
b
added to master
a@v3-2
b@v1
c@v1
a@v5
b@v1
c@v1
개발된 b
서비스를 dongwook
브랜치에서 master
브랜치로 변경
a
updated to master
a@v5
b@v1
c@v1
a@v5
b@v1
c@v1
수정된 a
서비스를 dongwook
브랜치에서 master
브랜치로 변경
dongwook
branch removed
a@v5
b@v1
c@v1
N/A
Routing Rule
Gateway 웹 서버는 [/~BRANCH[@TAG]]/<ENDPOINT>
의 규칙대로 API 엔드포인트를 라우트합니다. 첫번째 경로 조각을 브랜치(master
를 기본값으로)로 두번째 경로 조각을 태그(latest
를 기본값으로)로 이하 경로를 API 엔드포인트로 해석합니다.
라우트 예시
간략
브랜치 포함
태그 포함
GET /players/1
GET /~master/players/1
GET /~master@latest/players/1
-
-
GET /~master@h4g3f2e1/players/1
-
GET /~dongwook/players/1
GET /~dongwook@latest/players/1
-
-
GET /~dongwook@a4b3c2d1/players/1
POST /graphql
POST /~master/graphql
GET /~master@latest/graphql
-
POST /~dongwook/graphql
GET /~dongwook@latest/graphql
-
GET /~ws-dev/chat
GET /~ws-dev@latest/chat
테이블의 각 행은 동일한 버전의 핸들러로 연결됩니다.
브랜치 이름 규칙
영문 소문자 및 숫자, -
, _
만 허용됩니다.
기존 스키마 엔드포인트나 플러그인의 base 경로와 중복될 수 없습니다.
태그 이름 규칙
영문 소문자 및 숫자로만 구성됩니다.
Configure and run the gateway server.
yarn add moleculer-api
npm i --save moleculer-api
Add moleculer-api
package from npm.
import { APIGateway, APIGatewayOptions } from "moleculer-api";
const options: APIGatewayOptions = {
// ...
};
const gateway = new APIGateway(options);
gateway.start()
.then(() => {
// ...
});
const { APIGateway } = require("moleculer-api");
const options = {
// ...
};
const gateway = new APIGateway(options);
gateway.start()
.then(() => {
// ...
});
And write entry script like above. For now, let's skip setting detailed options.
2020-11-17T07:25:17.944Z info dwkimqmit.local/broker[0]/moleculer: Moleculer v0.14.11 is starting...
2020-11-17T07:25:17.946Z info dwkimqmit.local/broker[0]/moleculer: Namespace: <not defined>
2020-11-17T07:25:17.947Z info dwkimqmit.local/broker[0]/moleculer: Node ID: dwkimqmit.local-58669
2020-11-17T07:25:17.947Z info dwkimqmit.local/broker[0]/moleculer: Strategy: RoundRobinStrategy
2020-11-17T07:25:17.947Z info dwkimqmit.local/broker[0]/moleculer: Discoverer: LocalDiscoverer
2020-11-17T07:25:17.948Z info dwkimqmit.local/broker[0]/moleculer: Serializer: JSONSerializer
2020-11-17T07:25:17.953Z info dwkimqmit.local/broker[0]/moleculer: Validator: FastestValidator
2020-11-17T07:25:17.954Z info dwkimqmit.local/broker[0]/moleculer: Registered 13 internal middleware(s).
2020-11-17T07:25:17.964Z info dwkimqmit.local/server: gateway context factories have been applied id, ip, locale, cookie, userAgent, request, auth
2020-11-17T07:25:17.968Z info dwkimqmit.local/server: gateway server middleware have been applied: cors, bodyParser, logging, error
2020-11-17T07:25:17.969Z info dwkimqmit.local/server/application: gateway server application has been started: http<HTTPRoute>, ws<WebSocketRoute>
2020-11-17T07:25:17.971Z info dwkimqmit.local/server: gateway server protocol has been started: http
2020-11-17T07:25:17.971Z info dwkimqmit.local/server: gateway server has been started and listening on: http://localhost:8080, ws://localhost:8080
2020-11-17T07:25:17.972Z info dwkimqmit.local/schema: schema policy plugin has been started: filter, scope
2020-11-17T07:25:17.972Z info dwkimqmit.local/schema: schema protocol plugin has been started: GraphQL, REST, WebSocket
2020-11-17T07:25:17.973Z info dwkimqmit.local/schema: master (0 services) branch has been created
2020-11-17T07:25:17.991Z info dwkimqmit.local/schema/master: master (0 services) branch succeeded 1239eb4a (0 schemata, 0 routes) -> 7a2db312 (0 schemata, 4 routes) version compile:
(+) /graphql (http:POST): GraphQL HTTP operation endpoint
(+) /graphql (ws): GraphQL WebSocket operation endpoint
(+) /graphql (http:GET): GraphQL Playground endpoint
(+) /~status (http:GET): master branch introspection endpoint
2020-11-17T07:25:17.991Z info dwkimqmit.local/schema: master (0 services) branch has been updated
2020-11-17T07:25:17.992Z info dwkimqmit.local/schema: schema registry has been started
2020-11-17T07:25:17.993Z info dwkimqmit.local/broker[0]/moleculer: '$api' service is registered.
2020-11-17T07:25:17.995Z info dwkimqmit.local/broker[0]/moleculer: Service '$api' started.
2020-11-17T07:25:17.997Z info dwkimqmit.local/broker[0]/moleculer: '$node' service is registered.
2020-11-17T07:25:17.997Z info dwkimqmit.local/broker[0]/moleculer: Service '$node' started.
2020-11-17T07:25:17.998Z info dwkimqmit.local/broker[0]/moleculer: Service '$api' started.
2020-11-17T07:25:17.998Z info dwkimqmit.local/broker[0]/moleculer: ✔ ServiceBroker with 2 service(s) is started successfully in 3ms.
2020-11-17T07:25:17.999Z info dwkimqmit.local/broker[0]: service broker has been started: moleculer
2020-11-17T07:25:19.997Z info dwkimqmit.local/server/application: master (0 services) handler mounted for http<HTTPRoute> component
2020-11-17T07:25:19.998Z info dwkimqmit.local/server/application: master (0 services) handler mounted for ws<WebSocketRoute> component
With default options configuration, A gateway will run on localhost 8080 port with HTTP protocol. And basic placeholder scheme for GraphQL plugin, playground for GraphQL and a default status check endpoint will be set.
http://localhost:8080/~status An endpoint to show the status each API integrations. It will show the integration status from oldest version to latest version with detailed integrations belong to each versions by each branches (only master branch initially).
{
"branch": "master",
"latestUsedAt": "2020-11-17T07:45:03.322Z",
"parentVersion": null,
"latestVersion": "7a2db312",
"versions": [
{
"version": "7a2db312",
"fullVersion": "7a2db312e34f6105efb5ec107137763b",
"routes": [
"/graphql (http:POST): GraphQL HTTP operation endpoint",
"/graphql (ws): GraphQL WebSocket operation endpoint",
"/graphql (http:GET): GraphQL Playground endpoint",
"/~status (http:GET): master branch introspection endpoint"
],
"integrations": []
},
{
"version": "1239eb4a",
"fullVersion": "1239eb4a8416af46c0448426b51771f5",
"routes": [],
"integrations": []
}
],
"services": []
}
http://localhost:8080/graphql A playground endpoint which is set from GraphQL Protocol Plugin.
API Gateway constructor options.
APIGatewayOptions type is a kind of container for all the subordinate components' options.
type APIGatewayOptions = {
brokers: RecursivePartial<ServiceBrokerOptions>[],
schema: RecursivePartial<SchemaRegistryOptions>,
server: RecursivePartial<APIServerOptions>,
logger: LoggerConstructorOptions,
} & RecursivePartial<APIGatewayOwnOptions>;
name
default
description
brokers
-
Service Broker constructor options. Can configure multiple brokers for a single gateway. Service Broker discovers remote services and works as a delegator for calling remote service procedures and also deals with central event messages.
schema
-
Schema Registry constructor options. Schema Registry handles the integration of remote service API schema and creates API handlers. Can disable or configure detailed options for each API Schema Plugins like GraphQL, REST and WebSocket, etc.
server
-
API Server constructor options. Can configure API Server update policy, server components (HTTP, WebSocket server) and network interface (HTTP, HTTPS) detailed options, middleware options and request context factory options.
logger
-
Options for the gateway itself rather inner components.
type APIGatewayOwnOptions = {
skipProcessEventRegistration: boolean;
};
name
default
description
skipProcessEventRegistration
false
Set true to not to set default handlers for process interrupt signals like SIGINT.
Service Broker options are consist of common properties and delegator specific properties. The common properties show below.
type ServiceBrokerOptions = {
registry: ServiceRegistryOptions;
batching: BatchingPoolOptions;
function: InlineFunctionOptions;
reporter: ReporterOptions;
log: {
event: boolean;
call: boolean;
},
} & ServiceBrokerDelegatorConstructorOptions;
name
default
description
registry
-
Options for the ServiceRegistry which collect remote services, available procedures and event types, etc.
batching
-
function
-
Options for inline function (JS function notation string) sandbox.
reporter
-
Options for remote service reporter instance which reports API integration status, error or logging in inline function sandbox, etc.
log.event
true
Enable logging event messages.
log.call
true
Enable logging remote procedure call.
type ServiceRegistryOptions = {
examples: {
processIntervalSeconds: number;
queueLimit: number;
limitPerActions: number;
limitPerEvents: number;
streamNotation: string;
omittedNotation: string;
omittedLimit: number;
redactedNotation: string;
redactedParamNameRegExps: RegExp[];
};
healthCheck: {
intervalSeconds: number;
};
};
name
default
description
examples
-
Options for the ServiceRegistry action (remote procedure), event example collecting feature.
examples.processIntervalSeconds
5
Consume example queue for every given intervals.
examples.queueLimit
50
Example queue size.
examples.limitPerActions
10
Maximum number of examples for a single action (remote procedure).
examples.limitPerEvents
10
Maximum number of examples for a single event.
examples.streamNotation
*STREAM*
Replace stream request and response of an example to given string.
examples.omittedNotation
*OMITTED*
Truncate example object's string property and append given suffix for...
examples.omittedLimit
100
The strings longer than given length.
examples.redactedNotation
*REDACTED*
React example object's string property to given string for...
examples.redactedParamNameRegExps
[
/password/i,
/secret/i,
/credential/i,
/key/i,
/token/i,
]
Matched strings with given regular expressions.
healthCheck
-
Options for the ServiceRegistry health check feature.
healthCheck.intervalSeconds
10
Health check for every given intervals.
type BatchingPoolOptions = {
batchingKey: (...args: any[]) => any;
entryKey: (batchingParams: any) => any;
failedEntryCheck: (entry: any) => boolean;
entriesLimit: number;
};
name
default
description
batchingKey
(hash function)
A keygen function for the key of same batching arguments. Create hash string with args object by default.
entryKey
(hash function)
A keygen function for the variable params of each batched entries.
failedEntryCheck
entry => entry && entry.batchingError
A function to determine whether each entries are failed or not in a batch response. By default, a remote procedure which supports batching should response { ..., batchingError: true }
object for failed entry.
entriesLimit
100
Maximum number of entries for a single batch.
type InlineFunctionOptions = {
util: {[key: string]: any};
};
name
default
description
util
{}
Any kind of object which can be accessed as global util
variable from inline functions.
type ReporterOptions = {
tableWidthZoomFactor: number;
};
name
default
description
tableWidthZoomFactor
1
A reporter sends a report which is consist of raw messages and a string that prints messages as a shape of a table. For that table, set a zoom factor of the width.
Specific options for the Service Broker Delegator. Can choose only one among supported delegators. Currently moleculer delegator is supported.
type ServiceBrokerDelegatorConstructorOptions = {
moleculer?: MoleculerServiceBrokerDelegatorOptions;
[otherDelegatorKey: string]?: never;
};
name
default
description
moleculer
-
moleculer delegator can be configured with moleculer broker own options and few extra options like below.
import * as Moleculer from "moleculer";
type MoleculerServiceBrokerDelegatorOptions = Moleculer.BrokerOptions & {
batchedCallTimeout: (itemCount: number) => number;
streamingCallTimeout: number;
streamingToStringEncoding: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";
services: Moleculer.ServiceSchema[];
};
name
default
description
batchedCallTimeout
(return 5-60s based on item count)
A function to calculate the timeout options for a batched call.
streamingCallTimeout
3600000 (1 hour)
A timeout options for a streaming call (ms).
streamingToStringEncoding
base64
An encoding which is used to transform streaming data to buffer data. This is for the case that non-root property of payload is a readable stream. Because moleculer service broker can pipe only a single streaming data at once in a single params, a gateway needs to transform non-root streaming data to buffer data before proxy the action call. Try to check your moleculer service broker transporter options and this option for a malformed streaming data issue.
services
[]
Given Moleculer.ServiceSchema[]
would be registered on moleculer service broker started. This is for the testing convenience.
Service Registry options are consist of own options for the registry itself and Protocol, Policy, this two type of Plugin constructor options.
type SchemaRegistryOptions = {
maxVersions: number;
maxUnusedSeconds: number;
protocol: ProtocolPluginConstructorOptions,
policy: PolicyPluginConstructorOptions,
};
name
default
description
maxVersions
10
Maximum number of old versions for each branches.
maxUnusedSeconds
1800
Maximum unused duration until deleting non-master branches.
protocol
-
Options for Protocol Plugins.
policy
-
Options for Policy Plugins.
A ProtocolPlugin handles mapping Public API to calling internal services' procedure, publishing and subscribing event messages.
type ProtocolPluginConstructorOptions = {
REST: RecursivePartial<RESTProtocolPluginOptions> | false;
GraphQL: RecursivePartial<GraphQLProtocolPluginOptions> | false;
WebSocket: RecursivePartial<WebSocketProtocolPluginOptions> | false;
}
name
default
description
REST
-
Options for REST Protocol Plugin.
GraphQL
-
WebSocket
-
WIP
A PolicyPlugin handles access controls (authorization) while calling internal services' procedure, publishing and subscribing event messages.
type PolicyPluginConstructorOptions = {
scope: RecursivePartial<ScopePolicyPluginOptions> | false;
filter: RecursivePartial<FilterPolicyPluginOptions> | false;
};
name
default
description
scope
-
Options for Scope Policy Plugins.
filter
-
Options for Filter Policy Plugins.