<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 練習47:一個快速的URL路由 > 原文:[Exercise 47: A Fast URL Router](http://c.learncodethehardway.org/book/ex47.html) > 譯者:[飛龍](https://github.com/wizardforcel) 我現在打算向你展示使用`TSTree`來創建服務器中的快速URL路由。它適用于應用中的簡單的URL匹配,而不是在許多Web應用框架中的更復雜(一些情況下也不必要)的路由發現功能。 我打算編程一個小型命令行工具和路由交互,他叫做`urlor`,讀取簡單的路由文件,之后提示用戶輸入要檢索的URL。 ```c #include <lcthw/tstree.h> #include <lcthw/bstrlib.h> TSTree *add_route_data(TSTree *routes, bstring line) { struct bstrList *data = bsplit(line, ' '); check(data->qty == 2, "Line '%s' does not have 2 columns", bdata(line)); routes = TSTree_insert(routes, bdata(data->entry[0]), blength(data->entry[0]), bstrcpy(data->entry[1])); bstrListDestroy(data); return routes; error: return NULL; } TSTree *load_routes(const char *file) { TSTree *routes = NULL; bstring line = NULL; FILE *routes_map = NULL; routes_map = fopen(file, "r"); check(routes_map != NULL, "Failed to open routes: %s", file); while((line = bgets((bNgetc)fgetc, routes_map, '\n')) != NULL) { check(btrimws(line) == BSTR_OK, "Failed to trim line."); routes = add_route_data(routes, line); check(routes != NULL, "Failed to add route."); bdestroy(line); } fclose(routes_map); return routes; error: if(routes_map) fclose(routes_map); if(line) bdestroy(line); return NULL; } bstring match_url(TSTree *routes, bstring url) { bstring route = TSTree_search(routes, bdata(url), blength(url)); if(route == NULL) { printf("No exact match found, trying prefix.\n"); route = TSTree_search_prefix(routes, bdata(url), blength(url)); } return route; } bstring read_line(const char *prompt) { printf("%s", prompt); bstring result = bgets((bNgetc)fgetc, stdin, '\n'); check_debug(result != NULL, "stdin closed."); check(btrimws(result) == BSTR_OK, "Failed to trim."); return result; error: return NULL; } void bdestroy_cb(void *value, void *ignored) { (void)ignored; bdestroy((bstring)value); } void destroy_routes(TSTree *routes) { TSTree_traverse(routes, bdestroy_cb, NULL); TSTree_destroy(routes); } int main(int argc, char *argv[]) { bstring url = NULL; bstring route = NULL; check(argc == 2, "USAGE: urlor <urlfile>"); TSTree *routes = load_routes(argv[1]); check(routes != NULL, "Your route file has an error."); while(1) { url = read_line("URL> "); check_debug(url != NULL, "goodbye."); route = match_url(routes, url); if(route) { printf("MATCH: %s == %s\n", bdata(url), bdata(route)); } else { printf("FAIL: %s\n", bdata(url)); } bdestroy(url); } destroy_routes(routes); return 0; error: destroy_routes(routes); return 1; } ``` 之后我創建了一個簡單的文件,含有一些用于交互的偽造的路由: ``` / MainApp /hello Hello /hello/ Hello /signup Signup /logout Logout /album/ Album ``` ## 你會看到什么 一旦你使`urlor`工作,并且創建了路由文件,你可以嘗試這樣: ```sh $ ./bin/urlor urls.txt URL> / MATCH: / == MainApp URL> /hello MATCH: /hello == Hello URL> /hello/zed No exact match found, trying prefix. MATCH: /hello/zed == Hello URL> /album No exact match found, trying prefix. MATCH: /album == Album URL> /album/12345 No exact match found, trying prefix. MATCH: /album/12345 == Album URL> asdfasfdasfd No exact match found, trying prefix. FAIL: asdfasfdasfd URL> /asdfasdfasf No exact match found, trying prefix. MATCH: /asdfasdfasf == MainApp URL> $ ``` 你可以看到路由系統首先嘗試精確匹配,之后如果找不到的話則會嘗試前綴匹配。這主要是嘗試這二者的不同。根據你的URL的語義,你可能想要之中精確匹配,始終前綴匹配,或者執行二者并選出“最好”的那個。 ## 如何改進 URL非常古怪。因為人們想讓它們神奇地處理它們的web應用所具有的,所有瘋狂的事情,即使不是很合邏輯。在這個對如何將`TSTree`用作路由的簡單演示中,它具有一些人們不想要的缺陷。比如,它會把`/al`匹配到`Album`,它是人們通常不想要的。它們想要`/album/*`匹配到`Album`以及`/al`匹配到404錯誤。 這并不難以實現,因為你可以修改前綴算法來以你想要的任何方式匹配。如果你修改了匹配算法,來尋找所有匹配的前綴,之后選出“最好”的那個,你就可以輕易做到它。這種情況下,`/al`回匹配`MainApp`或者`Album`。獲得這些結果之后,就可以執行一些邏輯來決定哪個“最好”。 另一件你能在真正的路由系統里做的事情,就是使用`TSTree`來尋找所有可能的匹配,但是這些匹配是需要檢查的一些模式串。在許多web應用中,有一個正則表達式的列表,用于和每個請求的URL進行匹配。匹配所有這些正則表達式非常花時間,所以你可以使用`TSTree`來通過它們的前綴尋找所有可能的結果。于是你就可以縮小模式串的范圍,更快速地做嘗試。 使用這種方式,你的URL會精確匹配,因為你實際上運行了正則表達式,它們匹配起來更快,因為你通過可能的前綴來查找它們。 這種算法也可用于所有需要用戶可視化的靈活路由機制。域名、IP地址、包注冊器和目錄,文件或者URL。 ## 附加題 + 創建一個實際的引擎,使用`Handler`結構儲存應用,而不是僅僅儲存應用的字符串。這個結構儲存它所綁定的URL,名稱和任何需要構建實際路由系統的東西。 + 將URL映射到`.so`文件而不是任意的名字,并且使用`dlopen`系統動態加載處理器,并執行它們所包含的回調。將這些回調放進你的`Handler`結構體中,之后你就用C編寫了動態回調處理器系統的全部。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看