Решение переписывания обработчиков 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". Я также перенаправляю каждый запрос в динамический каталог (без необходимости использовать символ "?"), В то же время предотвращая использование расширения ".c" в URL.
Этот скрипт работает частично, но, очевидно, вызывает проблемы с выделением памяти. Есть ли у вас какое-либо решение предложить?
2 ответа
Если вы беспокоитесь о производительности, не используйте 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
Если вы беспокоитесь о распределении памяти, вызванном добавлением '?' Для каждого запроса вам нужно разработать имя вашего сервлета, чтобы могла произойти замена на месте. Вот ссылка, в которой есть примеры того, как добиться замены на месте для повышения производительности.
Я не тестировал приведенный выше код, поэтому он может не работать, но по крайней мере вы получите представление о том, как это сделать. Кроме того, скрипт не обрабатывает конвейерный запрос.
Во-первых, пытаясь избежать *.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
без переписывания.