Here's my 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);
}
As you may understood, I'm trying to redirect the homepage to the dynamic file "hello.c". I'm also redirecting every request to the dynamic directory (without having to use the character "?") while preventing the use of the extension ".c" in the url.
This script works partly but obviously causes memory allocation issues. Would you have any solution to propose?
If you are worried about performance don't use strstr. It will search the whole request for a match.
Based on your script you are expecting all request to be GET so strncmp is better to use since you are only comparing the first 6 characters.
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);
}
Again checking for ".c". You only want to check the first N character.
If you are worried about memory allocation caused by adding '?' to every request you need to design your servlet name so in-place replace can happen. Here is a link that have samples on how to achieve in-place replace for better performance.
I haven't tested the code above so it might not work but at least you will get an idea on how to do it. Also the script doesn't handle pipe-lined request.
First, trying to avoid the *.c
script extension is useless: by default, G-WAN accepts requests like /?hello
which are automatically remapped into /?hello.c
.
Second, this is not specific to C as G-WAN lets you define wich programming language (among the 16 scripted languages supported) will be used as the "default" language.
Third, you can also define another character if you want to avoid the '?' in your requests. G-WAN lets you chose among the non-reserved characters, making it possible to use use /'hello
or /_hello
instead of /?hello.cpp
(see below all your options).
And, all this can be done without calling a handler for each request (so it will not churn memory):
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; }
So, to come back to your question, you could use /'hello
without doing any rewrite.
来源:https://stackoverflow.com/questions/15398849/g-wan-handler-rewriting-solution