2013-03-14 67 views
3

這裏是我的腳本:G-WAN處理程序重寫解決方案

#include "gwan.h" // G-WAN exported functions 
#include <string.h> // strstr() 

int init(int argc, char *argv[]) 
{ 
    u32 *states = (u32*)get_env(argv, US_HANDLER_STATES); 
    *states = 1 << HDL_AFTER_READ; 
    return 0; 
} 

void clean(int argc, char *argv[]) 
{} 

int main(int argc, char *argv[]) 
{ 
    if((long)argv[0] == HDL_AFTER_READ) 
    { 
     xbuf_t *read_xbuf = (xbuf_t*)get_env(argv, READ_XBUF); 
     if(strstr(read_xbuf->ptr, "GET/HTTP/1.1")) 
     { 
      xbuf_repl(read_xbuf, "GET/HTTP/1.1", "GET /?index HTTP/1.1"); 
     } 
     else 
     { 
      if(strstr(read_xbuf->ptr, ".c HTTP/1.1")) 
      { 
       int *pHTTP_status = (int*)get_env(argv, HTTP_CODE); 
       if(pHTTP_status) 
        *pHTTP_status = 404; 
       return 255; 
      } 
      xbuf_repl(read_xbuf, "GET /", "GET /?"); 
     } 
    } 
    return(255); 
} 

你可能明白,我想重定向網頁的動態文件「的hello.c」。 我也將每個請求重定向到動態目錄(不必使用字符「?」),同時防止在URL中使用擴展名「.c」。

該腳本部分工作,但顯然會導致內存分配問題。 你有任何解決方案建議?

+0

此腳本不適用於流水線請求,因爲您沒有檢查該情況。另外,它忽略HTTP 1.0。請參閱下文,瞭解更簡單,更有效的解決方案。 – Gil 2013-03-14 07:14:25

+0

我同意你的意見。我的解決方案不是很好,但我不知道該如何解決我的問題......主要是以最好的方式將我的主頁(mydomain.com/)重定向到一個動態文件。 – 2013-03-15 14:31:56

回答

1

如果您擔心性能不要使用strstr。它會搜索整個請求進行匹配。

根據你的腳本,你期待所有的請求都是GET,所以strncmp更好用,因爲你只是比較前6個字符。

int main(int argc, char *argv[]) 
{ 
    xbuf_t *read_xbuf = (xbuf_t*)get_env(argv, READ_XBUF); 
    if(strncmp(read_xbuf->ptr, "GET/", 6) == 0) 
    { 
     xbuf_repl(read_xbuf, "/", " /?index "); 
    } 
    else 
    { 
     int pos = 5; // Start checking after '/' in "GET /" 
     while(pos < 20) // Only check first 15 characters 
     {    // Adjust depend on longest servlet name 
      if(read_xbuf->ptr[pos] == '.' && read_xbuf->ptr[pos+1] == 'c') // If request contains '.' return 404 
      { 
       int *pHTTP_status = (int*)get_env(argv, HTTP_CODE); 
       if(pHTTP_status) 
        *pHTTP_status = 404; 
       return 255; 
      } 
     } 
     xbuf_repl(read_xbuf, "GET /", "GET /?"); 
    } 
    return(255); 
} 

再次檢查「.c」。你只想檢查第一個N字符。

如果您擔心由於添加'?'引起的內存分配問題,到您需要設計servlet名稱的每個請求,以便就地替換可能發生。以下鏈接提供了有關如何實現就地更換以獲得更好性能的示例。

RESTful URIs in G-WAN

我沒有測試上面的代碼,以便它可能無法正常工作,但至少你會得到關於如何做到這一點的想法。此外,該腳本不處理管道請求。

+0

你的腳本實際上更快更清潔,但正如你所說,主要關注點仍然存在(管線不處理)!無論如何,你的網站是非常有趣的;) – 2013-03-17 03:28:23

0

首先,試圖避免*.c腳本擴展是無用的:在默認情況下,G-WAN接受像/?hello請求被自動重新映射到/?hello.c

其次,這不是特定於C,因爲G-WAN允許您定義至少編程語言(支持的16種腳本語言之一)將用作「默認」語言。

第三,如果你想避開'?',你還可以定義另一個字符。在你的請求。 G-WAN允許您在非保留字符中進行選擇,從而可以使用/'hello/_hello而不是/?hello.cpp(請參閱下面的所有選項)。

而且,這一切都可以在不調用處理程序爲每個請求(這樣就不會流失內存)來完成:

int init(int argc, char *argv[]) 
{ 
    // the QUERY_CHAR character can be chosen from the following set: 
    // - _ . ! ~ * ' () 
    // (see RFC 2396, section "2.3. Unreserved Characters") 
    // 
    u8 *query_char = (u8*)get_env(argv, QUERY_CHAR); 
    *query_char = '!'; // use "/!hello.c" instead of "/?hello.c" 

    // by default, DEFAULT_LANG = LG_C (ANSI C) 
    // LG_C, LG_CPP, LG_JAVA, etc. are defined in /gwan/include/gwan.h 
    // and in http://gwan.com/api#env 
    // 
    u8 *lang = (u8*)get_env(argv, DEFAULT_LANG); 
    *lang = LG_CPP; // use "/!hello" instead of "/!hello.cpp" 
    return 0; 
} 

// if, like above, init() does not define notification states with 
// get_env(argv, US_HANDLER_STATES), then the main() and clean() 
// handler calls defined below will never be invoked 
// (URL rewriting can't be done faster) 
// 
void clean(int argc, char *argv[]) { } 
int main (int argc, char *argv[]) { return 255; } 

所以,回到你的問題,你可以使用/'hello而不做任何改寫。

+0

我檢查是否存在'.c'字符,以防止我的訪問者知道我正在使用的編程語言(「mondomaine.com/?hello.c」將重定向到404頁面)。 關於'?'性格,我只是想讓它從我的訪問者的角度消失。 對我來說一個完美的地址是:「mondomaine.com/hello」而不是「mondomaine.com/?hello.c」。 – 2013-03-15 13:44:15

+0

然後,保留一個「垃圾」字符,並進行「就地」重寫。這比新的內存塊更快更安全。 – Gil 2013-05-14 13:50:08