Solución de reescritura del manejador G-WAN
url-rewriting handler (2)
Aquí está mi script:
#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);
}
Como puede comprender, estoy intentando redirigir la página de inicio al archivo dinámico "hello.c". También estoy redireccionando cada solicitud al directorio dinámico (sin tener que usar el carácter "?") Mientras impido el uso de la extensión ".c" en la url.
Esta secuencia de comandos funciona en parte, pero obviamente causa problemas de asignación de memoria. ¿Tendría alguna solución para proponer?
En primer lugar, intentar evitar la extensión de script *.c
es inútil: de manera predeterminada, G-WAN acepta solicitudes como /?hello
que se /?hello.c
a /?hello.c
automáticamente en /?hello.c
.
En segundo lugar, esto no es específico de C, ya que G-WAN le permite definir qué lenguaje de programación (entre los 16 lenguajes con guiones admitidos) se usará como el idioma "predeterminado" .
En tercer lugar, también puede definir otro personaje si desea evitar el ''?'' en tus peticiones G-WAN le permite elegir entre los caracteres no reservados, lo que le permite usar use /''hello
o /_hello
lugar de /?hello.cpp
(consulte a continuación todas sus opciones).
Y, todo esto se puede hacer sin llamar a un controlador para cada solicitud (para que no se agote la memoria):
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; }
Entonces, para volver a su pregunta, podría usar /''hello
sin hacer ninguna reescritura.
Si te preocupa el rendimiento, no uses strstr. Buscará toda la solicitud de un partido.
En función de su secuencia de comandos, espera que todas las solicitudes sean GET, por lo que es mejor utilizar strncmp, ya que solo está comparando los primeros 6 caracteres.
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);
}
Nuevamente comprobando si tiene ".c". Solo quieres verificar el primer carácter N.
Si le preocupa la asignación de memoria causada al agregar ''?'' Para cada solicitud, debe diseñar su nombre de servlet para que pueda reemplazarse in situ. Aquí hay un enlace que contiene ejemplos sobre cómo lograr reemplazos in situ para un mejor rendimiento.
No he probado el código anterior, por lo que podría no funcionar, pero al menos tendrás una idea de cómo hacerlo. Además, el script no maneja solicitudes alineadas.