### gRPC Reflection Setup Source: https://github.com/gravity-ui/gateway/blob/main/README.md Installs the necessary package for gRPC reflection and applies patches to protobufjs for compatibility. Includes instructions for postinstall scripts and handling potential Docker build errors. ```shell npm install --save grpc-reflection-js # Add to your project's postinstall script: npx gateway-reflection-patch ``` -------------------------------- ### Install @gravity-ui/gateway Source: https://github.com/gravity-ui/gateway/blob/main/README.md Installs the @gravity-ui/gateway package using npm. ```shell npm install --save @gravity-ui/gateway ``` -------------------------------- ### Basic Gateway Controller Setup Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates how to create a gateway controller by importing Gateway and API schemas, and configuring it for use in a Node.js application. ```javascript import {getGatewayControllers} from '@gravity-ui/gateway'; import Schema from ''; const config = { installation: 'external', env: 'production', includeProtoRoots: ['...'], }; const {controller: gatewayController} = getGatewayControllers({root: Schema}, config); export default gatewayController; ``` -------------------------------- ### Using Gateway API Client in Node.js Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates how to initialize and use the Gravity UI Gateway's API client within a Node.js environment. It shows the configuration options, including installation type, environment, proto roots, timeouts, and certificate paths, and how to make requests to backend services with authentication and request details. ```javascript import {getGatewayControllers} from '@gravity-ui/gateway'; import Schema from ''; const config = { installation: 'external', env: 'production', includeProtoRoots: ['...'], timeout: 25000, // default 25 seconds caCertificatePath: '...', // Optional: paths for mTLS client certificate and key clientCertificatePath: '...', clientKeyPath: '...', }; const {api: gatewayApi} = getGatewayControllers({root: Schema}, config); // Use the API to make requests const result = await gatewayApi.serviceName.actionName({ authArgs: {token: 'auth-token'}, requestId: '123', headers: {}, args: {param1: 'value1'}, ctx: context, }); ``` -------------------------------- ### Service and Action Level Authentication Source: https://github.com/gravity-ui/gateway/blob/main/README.md Provides an example of defining service-level and action-level authentication methods, showing how they override each other based on specificity. ```javascript const schema = { userService: { serviceName: 'users', endpoints: {...}, // Service-level authentication getAuthHeaders: (params) => ({ 'X-User-Service-Auth': params.token, }), getAuthArgs: (req, res) => ({ token: req.authorization.token, serviceSpecificData: req.headers['x-service-data'], }), actions: { getProfile: { path: () => '/profile', method: 'GET', // Uses service-level authentication }, updateProfile: { path: () => '/profile', method: 'PUT', // Action-level authentication (overrides service-level) getAuthHeaders: (params) => ({ 'X-Special-Auth': params.token, }), }, }, }, }; ``` -------------------------------- ### Gateway Configuration Interface Source: https://github.com/gravity-ui/gateway/blob/main/README.md Defines the structure for configuring the Gravity UI Gateway. It includes options for installation, environment, gRPC and Axios client configurations, request lifecycle hooks, proto file inclusion, TLS settings, telemetry, header proxying, debug headers, validation schemas, path encoding, reconnection logic, retry conditions, expected response content types, and authentication. ```typescript import {AxiosRequestConfig} from 'axios'; import {IncomingHttpHeaders} from 'http'; import {IAxiosRetryConfig} from 'axios-retry'; interface OnUnknownActionData { service?: string; action?: string; } interface Stats { service: string; action: string; restStatus: number; grpcStatus?: number; responseSize: number; requestId: string; requestTime: number; requestMethod: string; requestUrl: string; timestamp: number; userId?: string; traceId: string; } type SendStats = ( stats: Stats, headers: IncomingHttpHeaders, ctx: CoreContext, meta: {debugHeaders: Headers}, ) => void; type GrpcRetryCondition = (error: ServiceError) => boolean; type AxiosRetryCondition = IAxiosRetryConfig['retryCondition']; type ControllerType = 'rest' | 'grpc'; type ProxyHeadersFunctionExtra = { service: string; action: string; protopath?: string; protokey?: string; }; type ProxyHeadersFunction = ( headers: IncomingHttpHeaders, type: ControllerType, extra: ProxyHeadersFunctionExtra, ) => IncomingHttpHeaders; type ProxyHeaders = string[] | ProxyHeadersFunction; type ResponseContentType = AxiosResponse['headers']['Content-Type']; type GetAuthHeadersParams> = { actionType: ControllerType; serviceName: string; requestHeaders: Headers; authArgs: AuthArgs | undefined; }; interface AppErrorArgs { code?: string | number; details?: object; debug?: object; } interface AppErrorWrapArgs extends AppErrorArgs { message?: string; } interface AppErrorConstructor { new (message?: string, args?: AppErrorArgs): Error; wrap: (error: Error, args?: AppErrorWrapArgs) => Error; } interface GatewayConfig { // Gateway Installation (external/internal/...). If not provided, determined from process.env.APP_INSTALLATION. installation?: string; // Gateway Environment (production/testing/...). If not provided, determined from process.env.APP_ENV. env?: string; // Additional gRPC client options. grpcOptions?: object; // Additional Axios client options. axiosConfig?: AxiosRequestConfig; // List of actions to connect from the schema. By default, all actions are connected. actions?: string[]; // Called when an unknown service or action is provided. onUnknownAction?: (req: Request, res: Response, data: OnUnknownActionData) => any; // Called before the request is executed. onBeforeAction?: ( req: Request, res: Response, scope: string, service: string, action: string, config?: ApiServiceActionConfig, ) => any; // Called upon successful completion of the request. onRequestSuccess?: (req: Request, res: Response, data: any) => any; // Called in case of unsuccessful request execution. onRequestFailed?: (req: Request, res: Response, error: any) => any; // List of paths to the necessary proto files for the gateway. includeProtoRoots?: string[]; // Configuration of the path to the CA certificate in gRPC. // Set to null to use system certificates by default. caCertificatePath?: string | null; // Configuration of the path to the client certificate for mTLS in gRPC. clientCertificatePath?: string | null; // Configuration of the path to the client private key for mTLS in gRPC. clientKeyPath?: string | null; // Telemetry sending configuration. sendStats?: SendStats; // Configuration of headers sent to the API. proxyHeaders?: ProxyHeaders; // When passing a boolean value, it enables/disables debug headers in the response to the request. // For unary requests to gRPC backends, debug headers will include information from the trailing metadata returned by the backend. withDebugHeaders?: boolean | ((req: Request, res: Response) => boolean); // Validation schema for parameters used when no schema is present in the action. // You can use DEFAULT_VALIDATION_SCHEMA from lib/constants.ts. validationSchema?: object; // Enables encoding of REST path arguments (default is true). encodePathArgs?: boolean; // Configuration for automatic connection re-establishment upon connection error through L3 load balancer (default is true). grpcRecreateService?: boolean; // Customize retry behavior for grpc requests grpcRetryCondition?: GrpcRetryCondition; // Customize retry behavior for rest (axios) requests axiosRetryCondition?: AxiosRetryCondition; // Enable verification of response contentType header. Actual only for REST actions. // This value can be set/redefined in the action config. expectedResponseContentType?: ResponseContentType | ResponseContentType[]; // Function to get authentication arguments for API requests getAuthArgs: (req: Request, res: Response) => Record | undefined; // Function to get authentication headers for API requests getAuthHeaders: (params: GetAuthHeadersParams) => Record | undefined; // Error constructor for handling errors AppError?: AppErrorConstructor; } ``` -------------------------------- ### Custom gRPC Retry Condition Source: https://github.com/gravity-ui/gateway/blob/main/README.md Enables customization of retry behavior for gRPC actions via the `grpcRetryCondition` configuration option. This function evaluates gRPC errors to decide if a retry is warranted. The example illustrates retrying on `RESOURCE_EXHAUSTED` errors. ```javascript const config = { // ...other config options grpcRetryCondition: (error) => { // Custom logic to determine if the request should be retried return error.code === 'RESOURCE_EXHAUSTED'; }, }; ``` -------------------------------- ### Custom REST Retry Condition Source: https://github.com/gravity-ui/gateway/blob/main/README.md Allows customization of the retry logic for REST actions using the `axiosRetryCondition` configuration option. This function determines whether a request should be retried based on the error object. The example shows retrying only on 'TIMEOUT' errors. ```javascript const config = { // ...other config options axiosRetryCondition: (error) => { // Custom logic to determine if the request should be retried return error.code === 'TIMEOUT'; }, }; ``` -------------------------------- ### Gateway Controller Initialization Source: https://github.com/gravity-ui/gateway/blob/main/README.md Shows the basic initialization of gateway controllers, including the mapping of schema scopes to their respective schema definitions and a configuration object. ```javascript import {getGatewayControllers} from '@gravity-ui/gateway'; const { controller, api } = getGatewayControllers({root: rootSchema, anotherScope: anotherSchema}, config); ``` -------------------------------- ### Running Tests Source: https://github.com/gravity-ui/gateway/blob/main/README.md Commands to execute unit and integration tests for the project. Ensures code quality and functionality. ```shell # Run unit tests npm test # Run integration tests npm run test-integration ``` -------------------------------- ### Gateway Level Authentication Configuration Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates setting up authentication at the gateway level using `getAuthArgs` and `getAuthHeaders` configuration options. ```javascript const config = { // ...other config options // Get authentication arguments for request getAuthArgs: (req, res) => ({ token: req.authorization.token, }), // Generate authentication headers for backend requests getAuthHeaders: (params) => { if (!params?.token) return undefined; return { Authorization: `Bearer ${params.token}`, }; }, }; ``` -------------------------------- ### Schema Scopes Configuration Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates how to configure schemas with different scopes for independent gRPC contexts and independent naming. Shows how to access services and actions within specific scopes. ```javascript const schemasByScopes = {scope1: schema1, scope2: schema2}; import {getGatewayControllers} from '@gravity-ui/gateway'; const { controller, api } = getGatewayControllers({root: rootSchema, anotherScope: anotherSchema}, config); // API calls are made by specifying the scope const resultFromRoot = api.root.rootService.rootAction(params); const resultFromAnother = api.anotherScope.anotherService.anotherAction(params); // Invoking methods from the 'root' scope without explicitly specifying the scope const resultFromRoot = api.root.rootService.rootAction(params); const sameResultFromRoot = api.rootService.rootAction(params); ``` -------------------------------- ### gRPC Action Configuration with Reflection Source: https://github.com/gravity-ui/gateway/blob/main/README.md Configures a gRPC action to use reflection for determining service and method structures. Supports different reflection strategies and cache refresh intervals. ```javascript import {GrpcReflection} from '@gravity-ui/gateway'; const schema = { userService: { serviceName: 'users', endpoints: {...}, actions: { getUser: { protoKey: 'users.v1.UserService', action: 'GetUser', reflection: GrpcReflection.OnFirstRequest, // Optional: refresh reflection cache every 3600 seconds (1 hour) reflectionRefreshSec: 3600, }, }, }, }; ``` -------------------------------- ### Connecting Specific Actions Source: https://github.com/gravity-ui/gateway/blob/main/README.md Illustrates how to explicitly connect specific actions from schemas using the 'actions' field in the configuration. Supports wildcard patterns for selecting actions. ```javascript import {getGatewayControllers} from '@gravity-ui/gateway'; import rootSchema from ''; import localSchema from '../shared/schemas'; const config = { installation: 'external', env: 'production', includeProtoRoots: ['...'], actions: [ 'local.*', // All actions from the 'local' scope 'root.serviceA.*', // All actions from 'serviceA' in the 'root' scope 'root.serviceB.getUser', // Only the 'getUser' action from 'serviceB' in the 'root' scope ], }; const {api: gatewayApi} = getGatewayControllers({root: rootSchema, local: localSchema}, config); ``` -------------------------------- ### Connecting Gateway Controller to Express Routes Source: https://github.com/gravity-ui/gateway/blob/main/README.md Shows how to connect the gateway controller to Express routes using expresskit, defining API endpoint mappings and authentication middleware. ```APIDOC POST //:scope/:service/:action: {"target": "", "afterAuth": ["credentials"]} The `prefix` can be any prefix for API endpoints (for example, `/gateway/:service/:action`). ``` -------------------------------- ### Express Route Definition Source: https://github.com/gravity-ui/gateway/blob/main/README.md Illustrates how the gateway controller is used to define an Express route, including the expected route parameters like `:scope`, `:service`, and `:action`. ```javascript { 'POST //:scope/:service/:action': gatewayController } ``` -------------------------------- ### API Route Structure Source: https://github.com/gravity-ui/gateway/blob/main/README.md Describes the structure of API routes handled by the gateway, specifying the HTTP method, prefix, scope, service, and action. ```APIDOC POST //:scope/:service/:action ``` -------------------------------- ### ApiActionConfig Interface Source: https://github.com/gravity-ui/gateway/blob/main/README.md Defines the TypeScript interface for configuring an API action request. It includes parameters for request ID, headers, arguments, context, timeout, callbacks, authentication arguments, user ID, and abort signals, providing a structured way to pass request details. ```typescript interface ApiActionConfig { requestId: string; headers: Headers; args: TRequestData; ctx: Context; timeout?: number; callback?: (response: TResponseData) => void; authArgs?: Record; userId?: string; abortSignal?: AbortSignal; } ``` -------------------------------- ### Action-Specific Proxy Headers Source: https://github.com/gravity-ui/gateway/blob/main/README.md Illustrates how to define proxy headers for a specific API action ('getProfile' in 'userService'). This allows for more granular control over headers on a per-action basis. These headers are merged with gateway-level proxy headers. ```javascript const schema = { userService: { serviceName: 'users', endpoints: {...}, actions: { getProfile: { path: () => '/profile', method: 'GET', proxyHeaders: (headers) => ({...headers, ['x-users-service-action']: 'get-profile'}) }, }, }, }; ``` -------------------------------- ### Custom Error Constructor Source: https://github.com/gravity-ui/gateway/blob/main/README.md Defines a custom error class `CustomError` that extends the built-in `Error` class. It includes properties for `code`, `status`, and `details`. The static `wrap` method ensures that any error is converted into a `CustomError` instance, providing a consistent error structure. ```javascript class CustomError extends Error { constructor(message, options = {}) { super(message); this.name = 'CustomError'; this.code = options.code || 'UNKNOWN_ERROR'; this.status = options.status || 500; this.details = options.details; } static wrap(error) { if (error instanceof CustomError) return error; return new CustomError(error.message, { code: error.code || 'INTERNAL_ERROR', status: error.status || 500, }); } } const config = { // ...other config options ErrorConstructor: CustomError, }; ``` -------------------------------- ### Overriding Endpoints Configuration Source: https://github.com/gravity-ui/gateway/blob/main/README.md Shows how to override specific service endpoints using the GATEWAY_ENDPOINTS_OVERRIDES environment variable, which is useful for testing environments. ```javascript GATEWAY_ENDPOINTS_OVERRIDES = JSON.stringify({ serviceName: { endpoint: 'https://example.com', }, 'example.exampleService': { endpoint: 'https://overrided.example.com', }, }); ``` -------------------------------- ### Contributor License Agreement (CLA) Confirmation Source: https://github.com/gravity-ui/gateway/blob/main/CONTRIBUTING.md When submitting a pull request, contributors must include a confirmation statement agreeing to the terms of the CLA. This statement includes a link to the CLA document. ```text I hereby agree to the terms of the CLA available at: [link]. ``` -------------------------------- ### Gateway Proxy Headers Configuration Source: https://github.com/gravity-ui/gateway/blob/main/README.md Defines a function to set custom headers for gateway requests based on service and action type. It demonstrates how to add a specific header 'x-mail-service-action' for 'mail' services in REST actions. The gateway merges these headers with action-specific headers. ```javascript const proxyHeaders = (headers, actionType, extra) => { const normalizedHeaders = {...headers}; const {service, action, protopath, protokey} = extra; if (actionType === 'rest' && service === 'mail') { normalizedHeaders['x-mail-service-action'] = action; } return normalizedHeaders; }; const {controller: gatewayController} = getGatewayControllers( {root: Schema}, {...config, proxyHeaders}, ); ``` -------------------------------- ### Using `isRetryableGrpcError` for Custom Retry Logic Source: https://github.com/gravity-ui/gateway/blob/main/README.md Shows how to leverage the exported `isRetryableGrpcError` function from `@gravity-ui/gateway` within a custom retry condition for gRPC requests. This allows combining default retryable error checks with custom logic, such as retrying on `RESOURCE_EXHAUSTED`. ```javascript import {isRetryableGrpcError} from '@gravity-ui/gateway'; // Use in your custom retry condition const customGrpcRetryCondition = (error) => { return isRetryableGrpcError(error) || error.code === 'RESOURCE_EXHAUSTED'; }; ``` -------------------------------- ### Request Cancellation with AbortSignal Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates how to cancel a gateway request using an `AbortSignal`. An `AbortController` is created, and its signal is passed to the `abortSignal` parameter of the gateway API call. This is useful for long-running operations where the client might disconnect. ```javascript const abortController = new AbortController(); const result = await gatewayApi.serviceName.actionName({ authArgs: {token: 'auth-token'}, requestId: '123', headers: {}, args: {param1: 'value1'}, ctx: context, abortSignal: abortController.signal, }); ``` -------------------------------- ### Response Content Type Validation (Action Level) Source: https://github.com/gravity-ui/gateway/blob/main/README.md Sets the expected content type for individual actions within a service. Allows specifying a single content type or an array of acceptable types. Throws an error if the response does not match. ```javascript const schema = { userService: { serviceName: 'users', endpoints: {...}, actions: { getProfile: { path: () => '/profile', method: 'GET', expectedResponseContentType: 'application/json', }, getDocument: { path: () => '/document', method: 'GET', expectedResponseContentType: ['application/pdf', 'application/octet-stream'], }, }, }, }; ``` -------------------------------- ### Custom Request Error Handling Source: https://github.com/gravity-ui/gateway/blob/main/README.md Configures the `onRequestFailed` option to handle errors that occur during request processing. This function receives the request, response, and error objects, allowing for custom logging and response formatting. It sends an appropriate status code and JSON response to the client. ```javascript const config = { // ...other config options onRequestFailed: (req, res, error) => { console.error('Request failed:', error); return res.status(error.status || 500).json({ error: error.message, code: error.code, }); }, }; ``` -------------------------------- ### Response Content Type Validation (Gateway Level) Source: https://github.com/gravity-ui/gateway/blob/main/README.md Configures the expected content type for all responses at the gateway level. Ensures API responses adhere to a specified format, such as 'application/json'. ```javascript const config = { // ...other config options expectedResponseContentType: 'application/json', }; ``` -------------------------------- ### Action-Level REST Retry Condition Source: https://github.com/gravity-ui/gateway/blob/main/README.md Demonstrates how to set a specific retry condition for an individual action within a service schema. The `getProfile` action in `userService` is configured to retry only on `ECONNRESET` errors, overriding any global retry conditions. ```javascript const schema = { userService: { serviceName: 'users', endpoints: {...}, actions: { getProfile: { path: () => '/profile', method: 'GET', axiosRetryCondition: (error) => { // Custom logic for this specific action return error.code === 'ECONNRESET'; }, }, }, }, }; ``` -------------------------------- ### Action-Level Request Cancellation Source: https://github.com/gravity-ui/gateway/blob/main/README.md Configures request cancellation at the individual action level using the `abortOnClientDisconnect` option. For the `longRunningOperation` action in `userService`, setting this to `true` enables automatic cancellation if the client disconnects during the request. ```javascript const schema = { userService: { serviceName: 'users', endpoints: {...}, actions: { longRunningOperation: { path: () => '/process', method: 'POST', abortOnClientDisconnect: true, // Enable cancellation for this action }, }, }, }; ``` -------------------------------- ### Default Validation Schema for REST Path Parameters Source: https://github.com/gravity-ui/gateway/blob/main/README.md Presents the default validation schema used for path parameters in REST actions. It specifies a regular expression to validate parameter values, ensuring they do not contain certain forbidden sequences like '..', '?', '#', '\\', or '/'. Invalid values result in a `GATEWAY_INVALID_PARAM_VALUE` error. ```typescript export const DEFAULT_VALIDATION_SCHEMA = { additionalProperties: { oneOf: [ { type: 'number', }, { type: 'string', pattern: '^((?!(\.\.|\?|#|\\|\/)).)*$' }, { type: 'object', }, ], }, }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.