# Create service
# Create aggregate interface
# Configuration input
- The definition of configuration input includes 3 parts: request header, request body and Query parameters
- Supports JSON and XML type request bodies
- Comes with verification rules
- Support custom scripts to implement complex logic verification
Data verification follows the JSON Schema specification. For details, see:
http://json-schema.org/specification.html (opens new window)
http://json-schema.org/understanding-json-schema/ (opens new window)
# Configure verification results
- When the verification fails, FizzGate will put the reason for the verification failure (for example: the order ID cannot be empty) into the validateMsg field of the context.
- You can customize the message format returned to the caller, such as msgCode, message
- Support custom response headers
- Support custom scripts to process verification results
# Configuration steps (v2)
# Step instructions
- An aggregate interface can contain multiple steps
- One step can contain multiple requests (i.e. call multiple interfaces), supporting RESTful/Dubbo/gRPC interfaces
- The steps are executed in series sequence
- Multiple requests within one step are executed in parallel
# Basic information of configuration steps
Support RESTful/Dubbo/gRPC interface
The gRPC service needs to enable the reflection function, example:
server = ServerBuilder.forPort(port)
.addService(new UserService())
.addService(new ShoppingCartService())
// gRPC reflection enabled
.addService(ProtoReflectionService.newInstance())
.build();
# Interface input and output parameters of the configuration step
Fields support multiple levels, separated by dots, such as user.name or user.age
The request body and response body of the RESTful interface support JSON and XML content types. The system will convert XML to JSON and configure it in JSON format during configuration. The XML and JSON conversion rules are as follows:
Each element (node) will be converted into a JSON object, and sub-elements will be converted into fields of the JSON object
The attribute name of the element is converted into a field of the JSON object, and the field name will be prefixed with a hyphen.
When the element has attributes, the content of the element is converted to the #text field of the JSON object
<?xml version="1.0" encoding="utf-8"?> <library> <owner>John Doe</owner> <book id="007">James Bond</book> <book id="000">Book for the dummies</book> </library>
Convert to JSON:
{ "library": { "owner": "John Doe", "book": [ { "-id": "007", "#text": "James Bond" }, { "-id": "000", "#text": "Book for the dummies" } ] } }
<?xml version="1.0" encoding="utf-8"?> <library> <owner>John Doe</owner> <date>2021-03-31</date> </library>
Convert to JSON:
{ "library": { "owner": "John Doe", "date": "2021-03-31" } }
<?xml version="1.0" encoding="utf-8"?> <library> <book>James Bond</book> </library>
Converted to JSON by default:
{ "library": { "book": "James Bond" } }
It can be converted to JSON by specifying the array node path /library/book:
{ "library": { "book": ["James Bond"] } }
# Configuration steps (v3)
# Editor description
The v3 version adds a new API aggregation editor, which supports arrangement in the form of a flow chart, which is convenient and intuitive. Features and limitations are as follows:
- Support request node and container node
- Support conditional components and loop components
- Supports concurrent and serial execution
- Supports branching and aggregation
- An aggregate interface can contain several nodes (request nodes or container nodes)
- A container node can contain 0 or several request nodes
- A container node can only contain at most one start node and at most one end node.
- Nodes within the container cannot connect to nodes outside the container
# API Aggregation Editor
# Operation Guide
- Drag the node on the left to the right area to add it
- Drag the conditional component and loop component on the left to the request node or container node on the right to add components.
- Double-click the node obtained on the right to edit the node properties
- Click the component area below the node to edit component properties (as shown in the picture above, circle 2 areas)
# Sample
# Data conversion
Supports configuration of fixed values, reference values, functions and scripts
# Fixed value
# Reference value
# Function
For function-related documents, please refer to: Built-in function list>>
# Script
# Asterisk *
The asterisk wildcard can receive a reference value of the returned object type, and the fields in the returned object will be merged into the target object.
Example: If: step1.request2.response.body = {"userName": "FizzGate", "userID": 999} Then the output of the entire interface is {"userName": "FizzGate", "userID": 999, "a": 123}
# Tilde ~
The tilde wildcard is used to transparently transmit data. If the tilde wildcard is configured, the configuration of other fields will be ignored. The tilde wildcard can receive any data type, and the received value will be directly assigned to the corresponding body, request header or Query parameter.
Example: If: step1.request2.response.body = {"userName": "FizzGate", "userID": 999} Then the output of the entire interface is {"userName": "FizzGate", "userID": 999}, and other fields (a, dubbo_result, grpc_result) will be ignored.
# Priority and coverage order
Fixed value < reference value/function < script < asterisk* < tilde~
When a field is configured with multiple types of values, they are covered in the above order, and the wildcard has the highest priority.
# Reference value specification
Get the value of the input parameter request header aaa
input.request.headers.aaa
Get the value of the bbb field in the request body
input.request.body.bbb
Get the value of the fff field of the input URL Query parameter
input.request.params.fff
Get the value of the request header ccc of request1 in step 1
step1.request1.request.headers.ccc
Get the value of the response body ddd of request1 in step 1
step1.request1.response.body.ddd
Get the value of eee in the result of step 1
step1.result.eee
Get the value of the response code of request1 in step 1
step1.request1.response.httpStatus
Get the value of public resource account.name
g.account.name
Default value: input.request.body.bbb|123
The pipe character | is followed by the default value. When the reference value is empty, the default value is returned.
- Support single value reference, such as: string, int, etc. -Supports references to object types
input: represents the input data of the caller, such as the parameters submitted on the H5 page
stepN.requestN: Represents the relevant parameters of calling interface N in step N
stepN.result: represents the conversion result of step N
g: represents public resources (management background: gateway management->public resources)
For example: there is a public resource account={"name":"abc","password":"123456"}, g.account.name means referencing the value of name in account: abc, g.account means referencing the value of account: {"name":"abc","password":"123456"}
# Jsonpath specification
Note: Reference values only support the following JsonPath operations
- Use single quotes for strings, for example: ['name']
- Filter operations are separated by spaces, for example: [?(@.type == 1)]
Support operations | Description |
---|---|
@ | Current node (used as a predicate of filter expression) |
* | Universal match, which can represent a name or number. |
.. | Deep scan. It can be understood as a recursive search. |
.<name> | represents a child node |
['<name>' (, '<name>')] | Represents one or more child nodes |
[<number> (, <number>)] | Represents one or more array subscripts (the negative sign is the reciprocal) |
[?(<expression>)] | Filter expression. The expression result must be a Boolean value. |
Supports filtering operators (spaces must be added on both sides of the operator) | Description |
---|---|
== | left is equal to right (note that 1 is not equal to '1') |
!= | Not equal to |
< | less than |
<= | Less than or equal to |
> | Greater than |
>= | Greater than or equal to |
=~ | Match regular expression [?(@.name =~ /foo.*?/i)] |
in | The left side exists on the right side [?(@.size in ['S', 'M'])] |
nin | The left side does not exist on the right side |
Support tail function | Description |
---|---|
min() | Calculate the minimum value of an array of numbers |
max() | Calculate the maximum value of a numeric array |
avg() | Calculate the average of an array of numbers |
sum() | Calculate the summary value of an array of numbers |
length() | Counts the number of elements in a numeric array |
Example:
If the return body of request 1 in step 1 is as follows:
{
"name": "ABCD",
"data": [
{
"id": 1,
"title": "title 1",
"hits": 32344
},
{
"id": 2,
"title": "title 2",
"hits": 566
},
{
"id": 3,
"title": "title 3",
"hits": 7889
},
{
"id": 4,
"title": "title 4",
"hits": 100
},
{
"id": 5,
"title": "title 5",
"hits": 1688
}
]
}
The following results can be obtained through the reference value expression in the above figure:
{
"hits": [
32344,
566,
7889,
100,
1688
],
"name": "ABCD",
"totalHits": 42587,
"allTitleList": [
"title 1",
"title 2",
"title 3",
"title 4",
"title 5"
],
"id2Title": "title 2"
}
For more examples, please refer to the JsonPath official documentation: https://github.com/json-path/JsonPath
# Fallback and preprocessing conditions
Fallback:
When an exception occurs in the calling interface (such as timeout, network or system exception), a fallback scheme can be configured:
- Stop: terminate the request and return immediately
- Continue: Continue with subsequent operations and set the default fallback json
Preprocessing: Determine whether to call the interface based on conditions, and call the interface only when the script returns true
# Configuration step result processing
Supports data conversion of the return results of each interface called in the step. If the data conversion rules are not configured, the results will be returned as they are and stored in the context for subsequent use.
Supports processing the return results of one or more interfaces called in the step, and storing the processed results in the context for subsequent use. If not configured, it will not be processed.
# Configure output
Configure the results returned to the caller
-Support configuring response headers -Support configuring response body
- Support custom scripts to handle complex business logic
# Script
# Introduction
FizzGate
supports service orchestration through custom scripts:
- Verify input content through script in configuration input;
- In Configuration Output, the output content is defined through scripts, which can also be refined to the script processing of a certain output field;
- In configuration step, define the return content of configuration input parameters and configuration response through script;
- In Result Verification, you can fully customize the verification logic through scripts and verify the output content.
FizzGate
supports two scripting languages, javascript
and groovy
, allowing developers to flexibly choose the language they are familiar with for service orchestration.
If you use javascript
, you can obtain a series of tool functions through the common
object to facilitate logical processing;
In groovy
, all tool functions are mounted under context
, and you can use them easily.
# Script writing format
# javascript
When writing JavaScript scripts, you need to write them in the following fixed format. function name dyFunc
cannot be modified.
The return value can only be basic types, such as string/number/boolean
, and the object/array
type must be returned after serialization through JSON.stringify
.
FizzGate executes javascript scripts by calling the js engine, and then captures the execution results. It can only obtain basic data types.
Before the object/array type is captured, the
toString
method on the prototype will be called, and the result is a string of[object type]
, which is not the expected data, so it must be serialized throughJSON.stringify()
jsonString and then return.
Do not use document and other APIs in js
function dyFunc(paramsJsonStr) {
var ctx = JSON.parse(paramsJsonStr)['context'];
// do something...
// return string/number/boolean/jsonString
return JSON.stringify({});
}
# groovy
When writing groovy scripts, you can return any data type supported by groovy.
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
// do something...
// return any result
return result
# Configuration input - script verification
When editing the service orchestration interface, it is allowed to perform customized script verification on the input data in configuration input to verify whether the request header, request body, and query parameters pass the verification.
The returned verification result must be a serialized array, and:
- If the verification passes, an empty array is returned;
- If the verification fails, the error message of the failed verification will be pushed into the array and returned.
Reference example:
javascript
function dyFunc(paramsJsonStr) {
var ctx = JSON.parse(paramsJsonStr)['context'];
// Get the data input by the user of the aggregation interface
// Get request headers
var token = common.getInputReqHeader(ctx, 'token');
// Get request parameters
var account = common.getInputReqParam(ctx, 'account');
var validate = [];
//Verify request parameters
if (!token) {
// Push the error message of failed verification to validate
validate.push('missing token');
}
if (!account) {
validate.push('missing account');
}
// Return the array validate after serialization
// An empty array indicates that the verification passed, and a non-empty array indicates that the verification failed.
return JSON.stringify(validate);
}
groovy
// Get the data input by the user of the aggregation interface
// Get request headers
String token = context.getInputReqHeader('token')
// Get request parameters
String account = context.getInputReqAttr('params').get('account')
List<String> validate = new LinkedList<>()
//Verify request parameters
if (token == null || token.trim().isEmpty()) {
//Add the error message of failed verification to validate
validate.add('missing token')
}
if (account == null || account.trim().isEmpty()) {
validate.add('missing account')
}
// An empty array indicates that the verification passed, and a non-empty array indicates that the verification failed.
return validate
# Configure output
# Output complete response
When editing the service orchestration interface, you are allowed to customize the output results in Configuration Output.
For the return result, it is recommended to return it in the data structure of {status code, request information, request result}
. The example is as follows:
{
"msgCode": 0, // status code
"message": "success", // Request information
"data": { //Request result
"count": 1
}
}
When the script is executed internally, an exception is detected and the request needs to be terminated. You can add _stopAndResponse: true
to the response result for interruption and directly return the current result to the user.
{
"msgCode": 1, // status code
"message": "request error",
"_stopAndResponse": true // Terminate the request and return the response result
}
Configuration output script example:
//The javascript script function name cannot be modified
function dyFunc(paramsJsonStr) {
var context = JSON.parse(paramsJsonStr)['context'];
var data = common.getStepRespBody(context, 'step2', 'request1', 'data');
// do something
// Customize the return result. If the returned Object contains the _stopAndResponse=true field, the request will be terminated and the script result will be responded to the client (mainly used in scenarios where abnormal situations require terminating the request)
var result = { // There are no other special requirements for the data structure in result. The msgCode/message/data field is only an example.
// _stopAndResponse: true,
msgCode: '0',
message: '',
data: data
};
// When the return result is Array or Object, it must be converted into a json string first.
return JSON.stringify(result);
}
# Single field output script processing
When editing the service orchestration interface, it is allowed to customize the value of a single field through script processing in configuration output.
In field configuration, after selecting Script, you can configure the value of a single field through script.
The result of the script execution here is only assigned to a single field.
//The javascript script function name cannot be modified
function dyFunc(paramsJsonStr) {
var context = JSON.parse(paramsJsonStr)['context'];
var token = common.getStepRespBody(context, 'step2', 'request1', 'token');
// do something
var memberId = parseToken(token);
return memberId;
}
# Configuration steps
Same as Configuration Input - Script Verification and Configuration Output above.
# Result verification
Result verification refers to verifying the data finally returned to the user.
The returned verification result must be a serialized array, and:
- If the verification passes, an empty array is returned;
- If the verification fails, the error message of the failed verification will be pushed into the array and returned.
Reference example:
javascript
function dyFunc(paramsJsonStr) {
var ctx = JSON.parse(paramsJsonStr)['context'];
// Get the data input by the user of the aggregation interface
// Get request headers
var token = common.getInputReqHeader(ctx, 'token');
// Get request parameters
var account = common.getInputReqParam(ctx, 'account');
var validate = [];
//Verify request parameters
if (!token) {
// Push the error message of failed verification to validate
validate.push('missing token');
}
if (!account) {
validate.push('missing account');
}
// Return the array validate after serialization
// An empty array indicates that the verification passed, and a non-empty array indicates that the verification failed.
return JSON.stringify(validate);
}
groovy
// Get the data input by the user of the aggregation interface
// Get request headers
String token = context.getInputReqHeader('token')
// Get request parameters
String account = context.getInputReqAttr('params').get('account')
List<String> validate = new LinkedList<>()
//Verify request parameters
if (token == null || token.trim().isEmpty()) {
//Add the error message of failed verification to validate
validate.add('missing token')
}
if (account == null || account.trim().isEmpty()) {
validate.add('missing account')
}
// An empty array indicates that the verification passed, and a non-empty array indicates that the verification failed.
return validate
# context
in javascript script
The context
in the javascript
script is only in the scope of the scope function and is passed in as the first parameter of function dyFunc(paramsJsonStr){}
.
function dyFunc(paramsJsonStr) {
// The paramsJsonStr passed in is only a string, which needs to be serialized through JSON.parse to obtain `context`
var ctx = JSON.parse(paramsJsonStr)['context'];
// do something...
}
context
data structure description:
interface context {
debug: boolean; // Whether DEBUG mode
elapsedTimes: elapsedTime[]; // Time consuming for each operation
input: { //Customer input and interface return result
request: { // request
path: string; // Request path
method: string; // Request method POST/GET/PUT/DELETE/...
headers: {
[head: string]: any;
}; // Request header
body: {
[field: string]: any;
}; // Request body
params: {
[param: string]: any;
}; // response body
};
response: { // response
headers: {
[head: string]: any;
}; // response header
body: {
[field: string]: any;
}; // Response body The response of the aggregate interface
};
};
[stepName: string]: { // step
[requestName: string]: { // interface
request: { // // Request related parameters
url: string; // Request path
method: string; // Request method POST/GET/PUT/DELETE/...
headers: {
[head: string]: any;
}; // Request header
body: {
[body: string]: any;
}; // Request body
params: {
[param: string]: any;
}; // response body
};
response: { // Response The interface response converted according to the conversion rules
headers: {
[head: string]: any;
}; // response header
body: {
[field: string]: any;
}; // response body
};
}
};
result: string | number | boolean; // object/array needs to be serialized using JSON.stirngify
}
interface elapsedTime {
[acticeName: string]: number; // Operation name: Time-consuming
}
In order to facilitate the use of context
in scripts, we provide two script tool functions, javascript
and groovy
.
# Tool function——javascript
common.getInputReq(ctx)
:Get the request object in the context client
ctx
: context
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getInputReq(ctx); var path = req.path; // Request path var method = req.method; // Request method var headers = req.headers; // Request headers var body = req.body; // Request body var params = req.params; // Request parameters // do something... // return anything string return ''; }
common.getStepReq(ctx, stepName, requestName)
:Get the request object of the request interface in the context step
ctx
: contextstepName
: step name in the configuration steprequestName
: the request name corresponding to stepName in the configuration step
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getStepReq(ctx, 'step1', 'request1'); var url = req.url; //Request path var method = req.method; // Request method var headers = req.headers; // Request headers var body = req.body; // Request body var params = req.params; // Request parameters // do something... // return anything string return ''; }
common.getStepResp(ctx, stepName, requestName)
Get the response object of the request interface in the context step
ctx
: contextstepName
: step name in the configuration steprequestName
: the request name corresponding to stepName in the configuration step
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var stepResp = common.getStepResp(ctx, 'step1', 'request1'); // do something... // return anything string return ''; }
common.getInputReqHeader(ctx, headerName)
Get client request headers
ctx
: contextheaderName
: request header field name [optional], if not passed, all request headers will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getInputReqHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
common.getInputReqParam(ctx, paramName)
Get client URL request parameters (query string)
ctx
: context- paramName URL parameter name [optional], if not passed, all request parameters will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqParam(ctx, 'page'); // do something... // return anything string return ''; }
common.getInputReqBody(ctx, field)
Get client request body
ctx
: contextfield
field name [optional], if not passed, the entire request body will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
common.getInputRespHeader(ctx, headerName)
Get the response headers returned to the client
ctx
: contextheaderName
response header field name [optional], if not passed, all response headers will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputRespHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
common.getInputRespBody(ctx, field)
Get the response body returned to the client
ctx
: contextfield
field name [optional], if not passed, the entire response body will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
common.getStepReqHeader(ctx, stepName, requestName, headerName)
Get the request header of the interface called in the step
ctx
context [required]stepName
step name [required]requestName
requested interface name [required]headerName
request header field name [optional], if not passed, all request headers will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepReqHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
common.getStepReqParam(ctx, stepName, requestName, paramName)
Get the URL parameters of the interface called in the step
ctx
context [required]stepName
step name [required]requestName
requested interface name [required]paramName
URL parameter name [optional], if not passed, all URL parameters will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqParam(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
common.getStepReqBody(ctx, stepName, requestName, field)
Get the request body of the interface called in the step
ctx
context [required]stepName
step name [required]requestName
requested interface name [required]field
field name [optional], if not passed, the entire request body will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
common.getStepRespHeader(ctx, stepName, requestName, headerName)
Get the response header of the interface called in the step
ctx
context [required]stepName
step name [required]requestName
requested interface name [required]headerName
response header field name [optional], if not passed, all response headers will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepRespHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
common.getStepRespBody(ctx, stepName, requestName, field)
Get the response header of the interface called in the step
ctx
context [required]stepName
step name [required]requestName
requested interface name [required]field
field name [optional], if not passed, the entire response header will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepRespBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
common.getStepResult(ctx, stepName, field)
Get step results
ctx
context [required]stepName
step name [required]field
field name [optional], if not passed, the entire step result object will be returned
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var list = common.getStepResult(ctx, 'step1', 'list'); // do something... // return anything string return ''; }
# Tool function——groovy
context.getInputReq()
Get the request object in the context client
Map<String, Object> req = context.getInputReq()
context.getStepReq(stepName, requestName)
:Get the request object of the request interface in the context step
stepName
: step name in the configuration steprequestName
: the request name corresponding to stepName in the configuration step
Map<String, Object> req = context.getStepReq('step1', 'request1')
context.getStepResp(stepName, requestName)
Get the response object of the request interface in the context step
stepName
: step name in the configuration steprequestName
: the request name corresponding to stepName in the configuration step
context.getInputReqHeader(headerName)
Get client request headers
headerName
: request header field name [optional], if not passed, all request headers will be returned
context.getInputReqParam(paramName)
Get client URL request parameters (query string)
- paramName URL parameter name [optional], if not passed, all request parameters will be returned
context.getInputReqBody(field)
Get client request body
field
field name [optional], if not passed, the entire request body will be returned
context.getInputRespHeader(headerName)
Get the response headers returned to the client
headerName
response header field name [optional], if not passed, all response headers will be returned
context.getInputRespBody(field)
Get the response body returned to the client
field
field name [optional], if not passed, the entire response body will be returned
context.getStepReqHeader(ctx, stepName, requestName, headerName)
Get the request header of the interface called in the step
stepName
step name [required]requestName
requested interface name [required]headerName
request header field name [optional], if not passed, all request headers will be returned
context.getStepReqParam(stepName, requestName, paramName)
Get the URL parameters of the interface called in the step
stepName
step name [required]requestName
requested interface name [required]paramName
URL parameter name [optional], if not passed, all URL parameters will be returned
context.getStepReqBody(stepName, requestName, field)
Get the request body of the interface called in the step
stepName
step name [required]requestName
requested interface name [required]field
field name [optional], if not passed, the entire request body will be returned
context.getStepRespHeader(stepName, requestName, headerName)
Get the response header of the interface called in the step
stepName
step name [required]requestName
requested interface name [required]headerName
response header field name [optional], if not passed, all response headers will be returned
context.getStepRespBody(stepName, requestName, field)
Get the response header of the interface called in the step
stepName
step name [required]requestName
requested interface name [required]field
field name [optional], if not passed, the entire response header will be returned
context.getStepResult(stepName, field)
Get step results
stepName
step name [required]field
field name [optional], if not passed, the entire step result object will be returned
# Throw an exception
When you want to abort the request in the script, you can do it in the following way
Returning an object that contains a property with _stopAndResponse equal to true, FizzGate will terminate subsequent operations and return the object to the caller.
# Redirect
Redirection can be achieved through scripts. The script returns an object and this object contains both _stopAndResponse=true and _redirectUrl attributes. The value of _redirectUrl is the redirected target URL. FizzGate will terminate subsequent operations and redirect. A sample JavaScript script is as follows:
# Configure routing
At this point, the interface configuration of the service orchestration is completed. At this time, the interface cannot be accessed through the gateway. You need to configure the route in the gateway management-routing management.
- The testing function of versions below v2.0.0 needs to configure routing before it can be tested, and the front-end and back-end service names and paths of routing need to be consistent;
- The testing function of v2.0.0 or above does not require routing configuration by default and can be tested directly. You can enable test routing configuration by modifying the aggregate_test_auth configuration item in application.yml. Formal interfaces still need to be configured with routing before they can be accessed.
# Online test
-Support online real-time testing
- Supports isolation of test interfaces and formal interfaces
- Supports return context, allowing you to view the input and output of each step and request during the entire execution process -Supports saving historical test records
Supports debugging mode, which can be used in both test interfaces and official interfaces. Modifications can be republished to take effect in real time. In debugging mode, request logs and messages will be printed, which is mainly used to troubleshoot online problems.
# Script execution exception
When the script executes abnormally, exception information will be recorded in the context.
- exceptionMessage exception message
- exceptionStacks exception stack information
- exceptionData script data that caused the exception
//Context data structure design
//Context, used to save customer input and output and the input and output results of each step
var context = {
//Whether DEBUG mode
debug:false,
// exception info
exceptionMessage: "",
exceptionStacks: "",
exceptionData: "", // such as script source code that cause exception
// ... other fields
}
Add returnContext=true to the request to return the context. Example of exception information:
# Import and Export
Import and export are mainly used to synchronize interface configurations between various environments. After the development environment is configured, it is exported to the test environment for testing. After testing, it is exported to the production environment for release.
# Publish|Offline and review
Currently there are two entrances for release|offline application.
- Batch release: Batch release of the interfaces in the release order
- Batch rollback: batch rollback of the interfaces in the release order
- Publish: publish to the gateway in real time
- Rollback: Supports rollback to any version in the history. You can specify a version in the release history for rollback.
- Offline: Delete the interface from the gateway, and it can be brought online again through the publishing function in the background
# Release process description
The permissions to apply for release, review, release and offline functions can be flexibly assigned to different roles as needed. For example: developers can only apply for release, superior leaders can review, and operation and maintenance or testers can perform release, rollback or offline. In the development, testing and pre-production environments, in order to facilitate developer debugging, the application release, review, release and offline functions can also be assigned to developers.
# Configure request headers
Service orchestration will bring the following request headers by default when calling the backend interface: host,X-Real-IP,X-Forwarded-Proto,X-Forwarded-For
It can be modified in the application.yml configuration file of fizz-gateway-node:
gateway:
aggr:
# set headers when calling the backend API
proxy_set_headers: host,X-Real-IP,X-Forwarded-Proto,X-Forwarded-For