xmlweb基于狀態(tài)機(jī)理論設(shè)計(jì)的 Web 服務(wù)器
xmlweb 是一個(gè)基于狀態(tài)機(jī)理論設(shè)計(jì)的 web 服務(wù)器,使用它可以設(shè)計(jì)出高可讀性、高可維護(hù)性的 web 服務(wù)應(yīng)用。你可以使用它作為 express 或者 koa 的一個(gè)替代。
形式地看,一個(gè)狀態(tài)機(jī)包含了狀態(tài)集、字母表、轉(zhuǎn)移函數(shù)、起始狀態(tài)和接受狀態(tài)集。在 xmlweb 中將狀態(tài)集處理為組件的節(jié)點(diǎn)集,字母表對(duì)應(yīng)數(shù)據(jù)流,轉(zhuǎn)移函數(shù)由具體的組件節(jié)點(diǎn)根據(jù)數(shù)據(jù)流中的數(shù)據(jù)決定下一節(jié)點(diǎn)走向,起始狀態(tài)為 HTTP 節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn),接受狀態(tài)集為那些能夠響應(yīng)請(qǐng)求的節(jié)點(diǎn)。下面舉個(gè)簡(jiǎn)單的示例:
<i:HTTP xmlns:i="http://xmlweb">
<i:Router url="/index.html"/>
<Hello id='hello'/>
</i:HTTP>
在這個(gè)示例可以看成包含兩個(gè)狀態(tài)節(jié)點(diǎn)的狀態(tài)機(jī),這兩個(gè)節(jié)點(diǎn)分別是 Router 和 Hello。數(shù)據(jù)流由 HTTP 生成,里面包含一個(gè)關(guān)鍵的路徑數(shù)據(jù)。當(dāng)數(shù)據(jù)流經(jīng) Router 節(jié)點(diǎn)時(shí),Router 根據(jù)數(shù)據(jù)流中路徑是否為 /index.html 來(lái)絕對(duì)下一節(jié)點(diǎn)的走向,如果路徑是 /index.html,那么數(shù)據(jù)流就往 Hello 節(jié)點(diǎn)流動(dòng),否則導(dǎo)致停機(jī),也就是返回一個(gè)內(nèi)置 404 頁(yè)面。此示例中的 Hello 節(jié)點(diǎn)即是一個(gè)接受狀態(tài)。
上面的示例非常簡(jiǎn)單,但是如果使用狀態(tài)機(jī)的嵌套特性,你就可以構(gòu)建非常強(qiáng)大的 web 服務(wù)應(yīng)用,更多內(nèi)容可以查看文檔。
靜態(tài)服務(wù)器
下面是一個(gè)簡(jiǎn)單的靜態(tài)服務(wù)器,HTTP 節(jié)點(diǎn)是一個(gè)頂層狀態(tài)機(jī)組件節(jié)點(diǎn),默認(rèn)偵聽(tīng) 8080 端口,可以通過(guò)設(shè)置靜態(tài)參數(shù) listen 來(lái)變更。Static 節(jié)點(diǎn)是一個(gè)內(nèi)置的靜態(tài)服務(wù)組件節(jié)點(diǎn),已實(shí)現(xiàn)了緩存、壓縮以及斷點(diǎn)續(xù)傳等作為一個(gè) HTTP 靜態(tài)服務(wù)器應(yīng)該有的基本功能。
let xmlweb = require("xmlweb");
xmlweb("xp", function (xp, $_, t) {
$_().imports({
Index: {
xml:`<i:HTTP xmlns:i="http://xmlweb">
<i:Static root="static"/>
</i:HTTP>`
}
});
}).startup("http://xp/Index");
節(jié)點(diǎn)與數(shù)據(jù)流
狀態(tài)機(jī)節(jié)點(diǎn)可以是任何偵聽(tīng)了 enter 事件的組件對(duì)象。上面的 HTTP 節(jié)點(diǎn)與 Static 節(jié)點(diǎn)都是內(nèi)置的狀態(tài)機(jī)節(jié)點(diǎn)。為了方便起見(jiàn),你可以把節(jié)點(diǎn)看作中間件。下面是一個(gè)自定義的狀態(tài)機(jī)節(jié)點(diǎn):
Hello: {
fun: function (sys, items, opts) {
this.on("enter", (e, d) => {
d.res.setHeader("Content-Type", "text/html");
d.res.end("hello, world");
});
}
}
注意 enter 事件的偵聽(tīng)器有一參數(shù) d,它代表狀態(tài)機(jī)中數(shù)據(jù)流,數(shù)據(jù)流會(huì)在節(jié)點(diǎn)中流動(dòng)、變化。
狀態(tài)機(jī)
狀態(tài)機(jī) Flow 是 xmlweb 內(nèi)置的狀態(tài)機(jī)節(jié)點(diǎn),它可以作為 HTTP 節(jié)點(diǎn)的子級(jí)或者 Flow 節(jié)點(diǎn)的子級(jí)使用,下面是一個(gè)子狀態(tài)機(jī)節(jié)點(diǎn)的示例:
<i:Flow xmlns:i="http://xmlweb">
<Hello id='hello'/>
</i:Flow>
路由
路由組件節(jié)點(diǎn) Router 也是 xmlweb 內(nèi)置的組件節(jié)點(diǎn),它可根據(jù)請(qǐng)求類(lèi)型與 URL 模式串引導(dǎo)狀態(tài)機(jī)數(shù)據(jù)流的走向。它通常作為狀態(tài)機(jī)節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)使用。
<i:HTTP xmlns:i='//xmlweb'>
<i:Router url='/index.html'/>
<Hello id='hello'/>
</i:HTTP>
URL 重寫(xiě)與重定向
Rewrite 組件節(jié)點(diǎn)可將一個(gè)進(jìn)入的 URL 重新寫(xiě)成另一個(gè) URL,下面是一個(gè)簡(jiǎn)單的示例:
<i:HTTP xmlns:i='//xmlweb'>
<i:Rewrite from='/' to='/index.html'/>
<Hello id='hello'/>
</i:HTTP>
Redirect 組件節(jié)點(diǎn)用于 URL 的重定向,該組件節(jié)點(diǎn)默認(rèn)使用狀態(tài)碼為 302 的重定向:
<i:HTTP xmlns:i='//xmlweb'>
<i:Redirect to='http://xmlplus.cn'/>
</i:HTTP>
Session
xmlweb 提供一個(gè)內(nèi)置的 Session 組件以提供會(huì)話(huà)的創(chuàng)建、存儲(chǔ)以及移除。
<i:HTTP xmlns:i='//xmlweb'>
<i:Session id='session'/>
<Response id='response'/>
</i:HTTP>
xmlweb 內(nèi)置了一個(gè) session 的存儲(chǔ)驅(qū)動(dòng)組件 Storage,它位于命名空間 `//xmlweb/session` 中。組件 Storage 將數(shù)據(jù)以文本形式存放。你可以使用一個(gè)實(shí)現(xiàn)規(guī)定接口的同名組件來(lái)覆蓋默認(rèn)的內(nèi)置組件。
