您好,登錄后才能下訂單哦!
這篇文章主要講解了“Fizz Gateway網關腳本功能的高級用法教程”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Fizz Gateway網關腳本功能的高級用法教程”吧!
校驗不通過時,Fizz會把校驗失敗的原因(如:訂單ID不能為空)放到上下文的validateMsg字段里
可以自定義返回給調用方的報文格式,如 msgCode, message
支持自定義響應頭
支持自定義腳本處理校驗結果
一個聚合接口可包含多個步驟
一個步驟可包含多個請求(即調用多個接口)
步驟間是串聯順序執行
一個步驟內的多個請求并行執行
支持配置固定值,引用值和腳本
#固定值
#腳本
#星號 *
星號通配符可以接收一個返回對象類型的引用值,返回對象里的字段會合并到目標對象里
樣例:userInfo = {"userName": "Fizz", "userID": 1234}
#優先級與覆蓋順序
固定值 < 引用值 < 腳本 < 星號*
當一個字段配置了多種類型的值時按以上順序覆蓋,星號優先級最高
#引用值規范
# 獲取入參請求頭aaa的值 input.request.headers.aaa # 獲取入參請求體bbb字段的值 input.request.body.bbb # 獲取入參URL Query參數fff字段的值 input.request.params.fff # 獲取步驟1里request1的請求頭ccc的值 step1.request1.request.headers.ccc # 獲取步驟1里request1的響應體ddd的值 step1.request1.response.body.ddd # 獲取步驟1結果里eee的值 step1.result.eee
支持單值引用,如:string,int等
支持對象類型的引用
input: 表示調用方的輸入數據,如H5頁面提交上來的參數
stepN.requestN: 表示步驟N里調用接口N的相關參數
stepN.result: 表示步驟N的轉換結果
#Fallback與預處理條件
Fallback:
當調用接口發生異常(如超時、網絡或系統異常)可配置fallback方案:
Stop: 終止請求并立即返回
Continue: 繼續后續的操作,且要設置默認的fallback json
預處理: 根據條件判斷是否要調用接口,腳本返回true時才調用接口
#配置步驟結果處理
配置返回給調用方的結果
支持配置響應頭
支持配置響應體
支持自定腳本處理復雜的業務邏輯
Fizz
支持通過自定義腳本進行服務編排:
在 配置輸入 中 通過 腳本校驗 輸入內容;
在 配置輸出 中 通過 腳本 定義 輸出內容,也可以細化到 某個輸出字段的 腳本處理;
在 配置步驟 中 通過 腳本 定義 配置入參、配置響應 的返回內容;
在 結果校驗 中 通過 腳本 完全自定義校驗邏輯,校驗輸出內容。
Fizz
支持 javascript
和 groovy
兩種腳本語言,方便開發人員靈活的選擇自己熟悉的語言進行服務編排。
其中,
如果使用javascript
,可以 通過 common
對象獲取一系列工具函數,方便進行邏輯處理;
而在 groovy
中,所有的工具函數都掛載在 context
下,你可以很方便的使用它們。
#javascript
編寫JavaScript腳本時,需要按照以下固定格式進行編寫。 function name dyFunc
不可修改。
返回值只能是基本類型,如 string/number/boolean
,object/array
類型的必須通過JSON.stringify
序列化后返回。
Fizz 是通過調用 js引擎執行javascript腳本,然后捕獲執行結果,只能獲取基本的數據類型。
object/array類型捕獲前,會調用原型上的
toString
方法,得到的結果為[object type]
的字符串,并非預期的數據,所以必須通過JSON.stringify()
序列化為jsonString后再返回。
請勿在js 中使用document等api
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // do something... // return string/number/boolean/jsonString return JSON.stringify({}); }
#groovy
編寫groovy腳本時,支持返回groovy支持的任何數據類型。
import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject // do something... // return any result return result
在 編輯服務編排接口時,允許在 配置輸入 中,對輸入的數據進行自定義的腳本校驗,校驗 請求頭、請求體、query參數是否通過驗證。
返回的驗證結果,必須是一個 序列化后的 數組,且:
如果校驗通過,則返回一個空數組;
如果校驗不通過,將校驗不通過的錯誤信息,push到數組中后返回。
參考示例:
javascript
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 獲取聚合接口用戶輸入的數據 // 獲取請求頭 var token = common.getInputReqHeader(ctx, 'token'); // 獲取請求參數 var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校驗請求參數 if (!token) { // 將校驗不通過的錯誤信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 將 數組 validate 序列化后返回 // 空數組表示校驗通過,非空表示校驗不通過 return JSON.stringify(validate); }
groovy
// 獲取聚合接口用戶輸入的數據 // 獲取請求頭 String token = context.getInputReqHeader('token') // 獲取請求參數 String account = context.getInputReqAttr('params').get('account') List<String> validate = new LinkedList<>() // 校驗請求參數 if (token == null || token.trim().isEmpty()) { // 將校驗不通過的錯誤信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空數組表示校驗通過,非空表示校驗不通過 return validate
#輸出 完整response
在 編輯服務編排接口時,允許在 配置輸出 中,自定義輸出結果。
對于返回結果,建議以 { 狀態碼, 請求信息,請求結果 }
的數據結構進行返回,示例如下:
{ "msgCode": 0, // 狀態碼 "message": "success", // 請求信息 "data": { // 請求結果 "count": 1 } }
當腳本內部執行時,檢查到發生異常,需要終止請求,可在 響應的結果中, 添加_stopAndResponse: true
用于中斷,直接將當前結果返回到用戶端。
{ "msgCode": 1, // 狀態碼 "message": "request error", "_stopAndResponse": true // 終止請求并返回響應結果 }
配置輸出腳本示例:
// javascript腳本函數名不能修改 function dyFunc(paramsJsonStr) { var context = JSON.parse(paramsJsonStr)['context']; var data = common.getStepRespBody(context, 'step2', 'request1', 'data'); // do something // 自定義 返回結果,如果返回的Object里含有_stopAndResponse=true字段時將會終止請求并把腳本結果響應給客戶端(主要用于有異常情況要終止請求的場景) var result = { // 對于result 內的數據結構無其他特殊要求,msgCode/message/data字段僅做示例 // _stopAndResponse: true, msgCode: '0', message: '', data: data }; // 返回結果為Array或Object時要先轉為json字符串 return JSON.stringify(result); }
#單個字段 輸出腳本處理
在 編輯服務編排接口時,允許在 配置輸出 中,通過腳本處理,自定義單個字段的值。
在字段配置中,選擇 腳本后,即可通過腳本 配置 單個字段的值。
這里的腳本執行的結果只賦值給單個字段。
// javascript腳本函數名不能修改 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; }
與 上面的 配置輸入——腳本校驗 和__配置輸出__ 相同。
結果校驗指為最終返回給用戶端的數據進行校驗。
返回的驗證結果,必須是一個 序列化后的 數組,且:
如果校驗通過,則返回一個空數組;
如果校驗不通過,將校驗不通過的錯誤信息,push到數組中后返回。
參考示例:
javascript
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 獲取聚合接口用戶輸入的數據 // 獲取請求頭 var token = common.getInputReqHeader(ctx, 'token'); // 獲取請求參數 var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校驗請求參數 if (!token) { // 將校驗不通過的錯誤信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 將 數組 validate 序列化后返回 // 空數組表示校驗通過,非空表示校驗不通過 return JSON.stringify(validate); }
groovy
// 獲取聚合接口用戶輸入的數據 // 獲取請求頭 String token = context.getInputReqHeader('token') // 獲取請求參數 String account = context.getInputReqAttr('params').get('account') List<String> validate = new LinkedList<>() // 校驗請求參數 if (token == null || token.trim().isEmpty()) { // 將校驗不通過的錯誤信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空數組表示校驗通過,非空表示校驗不通過 return validate
context
javascript
腳本中的context
是僅作用域函數作用域中的,作為 function dyFunc(paramsJsonStr){}
的第一個入參傳入。
function dyFunc(paramsJsonStr) { // 傳入的 paramsJsonStr 僅是一個字符串,需要通過JSON.parse進行序列化后獲取`context` var ctx = JSON.parse(paramsJsonStr)['context']; // do something... }
context
數據結構描述:
interface context { debug: boolean; // 是否DEBUG模式 elapsedTimes: elapsedTime[]; // 各個操作的耗時 input: { // 客戶輸入和接口的返回結果 request: { // 請求 path: string; // 請求路徑 method: string; // 請求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 請求頭 body: { [field: string]: any; }; // 請求體 params: { [param: string]: any; }; // 響應體 }; response: { // 響應 headers: { [head: string]: any; }; // 響應頭 body: { [field: string]: any; }; // 響應體 聚合接口的響應 }; }; [stepName: string]: { // 步驟 [requestName: string]: { // 接口 request: { // // 請求相關參數 url: string; // 請求路徑 method: string; // 請求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 請求頭 body: { [body: string]: any; }; // 請求體 params: { [param: string]: any; }; // 響應體 }; response: { // 響應 根據轉換規則轉換后的接口響應 headers: { [head: string]: any; }; // 響應頭 body: { [field: string]: any; }; // 響應體 }; } }; result: string | number | boolean; // object/array 需要使用 JSON.stirngify 序列化 } interface elapsedTime { [acticeName: string]: number; // 操作名稱:耗時 }
為了方便在腳本中使用context
,我們提供了 javascript
和 groovy
兩種腳本的工具函數。
common.getInputReq(ctx)
:
獲取上下文客戶端中請求對象
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getInputReq(ctx); var path = req.path; // 請求路徑 var method = req.method; // 請求方法 var headers = req.headers; // 請求頭 var body = req.body; // 請求體 var params = req.params; // 請求參數 // do something... // return anything string return ''; }
ctx
: 上下文
common.getStepReq(ctx, stepName, requestName)
:
獲取上下文步驟中請求接口的請求對象
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getStepReq(ctx, 'step1', 'request1'); var url = req.url; // 請求路徑 var method = req.method; // 請求方法 var headers = req.headers; // 請求頭 var body = req.body; // 請求體 var params = req.params; // 請求參數 // do something... // return anything string return ''; }
ctx
: 上下文
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應的 request name
common.getStepResp(ctx, stepName, requestName)
獲取上下文步驟中請求接口的響應對象
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var stepResp = common.getStepResp(ctx, 'step1', 'request1'); // do something... // return anything string return ''; }
ctx
: 上下文
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應的 request name
common.getInputReqHeader(ctx, headerName)
獲取客戶端請求頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getInputReqHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
ctx
: 上下文
headerName
: 請求頭字段名 【選填】,不傳時返回所有請求頭
common.getInputReqParam(ctx, paramName)
獲取客戶端URL請求參數(query string)
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqParam(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
paramName URL參數名 【選填】,不傳時返回所有請求參數
common.getInputReqBody(ctx, field)
獲取客戶端請求體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
field
字段名 【選填】,不傳時返回整個請求體
common.getInputRespHeader(ctx, headerName)
獲取返回給客戶端的響應頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputRespHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
ctx
: 上下文
headerName
響應頭字段名 【選填】,不傳時返回所有響應頭
common.getInputRespBody(ctx, field)
獲取返回給客戶端的響應體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
field
字段名 【選填】,不傳時返回整個響應體
common.getStepReqHeader(ctx, stepName, requestName, headerName)
獲取步驟中調用的接口的請求頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepReqHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
請求頭字段名 【選填】,不傳時返回所有請求頭
common.getStepReqParam(ctx, stepName, requestName, paramName)
獲取步驟中調用的接口的URL參數
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqParam(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
paramName
URL參數名 【選填】,不傳時返回所有URL參數
common.getStepReqBody(ctx, stepName, requestName, field)
獲取步驟中調用的接口的請求體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個請求體
common.getStepRespHeader(ctx, stepName, requestName, headerName)
獲取步驟中調用的接口的響應頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepRespHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
響應頭字段名 【選填】,不傳時返回所有響應頭
common.getStepRespBody(ctx, stepName, requestName, field)
獲取步驟中調用的接口的響應頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepRespBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個響應頭
common.getStepResult(ctx, stepName, field)
獲取步驟結果
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var list = common.getStepResult(ctx, 'step1', 'list'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
field
字段名 【選填】,不傳時返回整個步驟結果對象
context.getInputReq()
獲取上下文客戶端中請求對象
Map<String, Object> req = context.getInputReq()
context.getStepReq(stepName, requestName)
:
獲取上下文步驟中請求接口的請求對象
Map<String, Object> req = context.getStepReq('step1', 'request1')
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應的 request name
context.getStepResp(stepName, requestName)
獲取上下文步驟中請求接口的響應對象
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應的 request name
context.getInputReqHeader(headerName)
獲取客戶端請求頭
headerName
: 請求頭字段名 【選填】,不傳時返回所有請求頭
context.getInputReqParam(paramName)
獲取客戶端URL請求參數(query string)
paramName URL參數名 【選填】,不傳時返回所有請求參數
context.getInputReqBody(field)
獲取客戶端請求體
field
字段名 【選填】,不傳時返回整個請求體
context.getInputRespHeader(headerName)
獲取返回給客戶端的響應頭
headerName
響應頭字段名 【選填】,不傳時返回所有響應頭
context.getInputRespBody(field)
獲取返回給客戶端的響應體
field
字段名 【選填】,不傳時返回整個響應體
context.getStepReqHeader(ctx, stepName, requestName, headerName)
獲取步驟中調用的接口的請求頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
請求頭字段名 【選填】,不傳時返回所有請求頭
context.getStepReqParam(stepName, requestName, paramName)
獲取步驟中調用的接口的URL參數
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
paramName
URL參數名 【選填】,不傳時返回所有URL參數
context.getStepReqBody(stepName, requestName, field)
獲取步驟中調用的接口的請求體
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個請求體
context.getStepRespHeader(stepName, requestName, headerName)
獲取步驟中調用的接口的響應頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
響應頭字段名 【選填】,不傳時返回所有響應頭
context.getStepRespBody(stepName, requestName, field)
獲取步驟中調用的接口的響應頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個響應頭
context.getStepResult(stepName, field)
獲取步驟結果
stepName
步驟名【必填】
field
字段名 【選填】,不傳時返回整個步驟結果對象
當要在腳本里中止請求時可以通過以下方式來實現
返回一個對象且這個對象包含一個_stopAndResponse等于true的屬性,Fizz會終止后續的操作并把這個對象返回給調用方。
通過腳本可以實現重定向,腳本返回一個對象且這個對象同時包含_stopAndResponse=true和_redirectUrl屬性,_redirectUrl的值為重定向的目標URL,Fizz會終止后續的操作并進行重定向。JavaScript腳本樣例如下:
支持調試模式,在測試接口和正式接口均可使用,修改后重新發布可實時生效,在調試模式下會打印請求日志及報文,主要用于排查線上問題
當腳本執行異常時context里會記錄異常信息
exceptionMessage 異常信息
exceptionStacks 異常堆棧信息
exceptionData 引起異常的腳本數據
// 上下文數據結構設計 // 上下文,用于保存客戶輸入輸出和每個步驟的輸入與輸出結果 var context = { // 是否DEBUG模式 debug:false, // exception info exceptionMessage: "", exceptionStacks: "", exceptionData: "", // such as script source code that cause exception // ... other fields }
在請求里加上returnContext=true可以返回context上下文,異常信息樣例:
導入導出主要用于在各個環境間同步接口配置,在開發環境配置好后導到測試環境中測試,測試完后導到生產環境進行發布
目前發布|下線申請有以上兩個入口。
批量發布:對發布單里的接口進行批量發布
批量回滾:對發布單里的接口進行批量回滾
發布:實時發布到網關
回滾:支持回滾到歷史任何一個版本,可在發布歷史里指定一個版本進行回滾
下線:從網關刪除接口,在后臺可以通過發布功能再次上線
申請發布、審核、發布和下線功能的權限可根據需要靈活分配給不同角色,如:開發人員只能申請發布,上級領導審核,運維或測試人員執行發布、回滾或下線。在開發、測試和預生產環境為了方便開發人員調試也可把申請發布、審核、發布和下線功能都分配給開發人員。
感謝各位的閱讀,以上就是“Fizz Gateway網關腳本功能的高級用法教程”的內容了,經過本文的學習后,相信大家對Fizz Gateway網關腳本功能的高級用法教程這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。