G-WAN handler rewriting solution

徘徊边缘 提交于 2019-11-30 18:20:41

问题


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?


回答1:


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.

RESTful URIs in G-WAN

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.




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!