mirror of
https://github.com/lxsang/ant-http
synced 2025-04-17 16:16:45 +02:00
support of rule, useful for sub domain remapping
This commit is contained in:
parent
01c32d964e
commit
ff3c68ff64
157
http_server.c
157
http_server.c
@ -16,7 +16,7 @@ void accept_request(int client)
|
|||||||
size_t i, j;
|
size_t i, j;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
char *query_string = NULL;
|
//char *query_string = NULL;
|
||||||
|
|
||||||
numchars = get_line(client, buf, sizeof(buf));
|
numchars = get_line(client, buf, sizeof(buf));
|
||||||
i = 0; j = 0;
|
i = 0; j = 0;
|
||||||
@ -28,7 +28,7 @@ void accept_request(int client)
|
|||||||
method[i] = '\0';
|
method[i] = '\0';
|
||||||
if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
|
if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
|
||||||
{
|
{
|
||||||
printf("METHOD NOT FOUND %s\n", method);
|
LOG("METHOD NOT FOUND %s\n", method);
|
||||||
// unimplemented
|
// unimplemented
|
||||||
//while(get_line(client, buf, sizeof(buf)) > 0) printf("%s\n",buf );
|
//while(get_line(client, buf, sizeof(buf)) > 0) printf("%s\n",buf );
|
||||||
unimplemented(client);
|
unimplemented(client);
|
||||||
@ -47,41 +47,20 @@ void accept_request(int client)
|
|||||||
}
|
}
|
||||||
url[i] = '\0';
|
url[i] = '\0';
|
||||||
|
|
||||||
if (strcasecmp(method, "GET") == 0)
|
|
||||||
{
|
|
||||||
query_string = url;
|
|
||||||
while ((*query_string != '?') && (*query_string != '\0'))
|
|
||||||
query_string++;
|
|
||||||
if (*query_string == '?')
|
|
||||||
{
|
|
||||||
*query_string = '\0';
|
|
||||||
query_string++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the HOST header
|
|
||||||
line = read_line(client);
|
|
||||||
trim(line, '\n');
|
|
||||||
trim(line, '\r');
|
|
||||||
token = strsep(&line,":");
|
|
||||||
trim(token,' ');
|
|
||||||
trim(line,' ');
|
|
||||||
if(strcasecmp(token, "HOST"))
|
|
||||||
{
|
|
||||||
badrequest(client);
|
|
||||||
close(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform rule check in domain
|
|
||||||
|
|
||||||
|
char* oldurl = strdup(url);
|
||||||
|
char* tmp = strchr(oldurl,'?');
|
||||||
|
if(tmp)
|
||||||
|
*tmp = '\0';
|
||||||
|
|
||||||
|
dictionary rq = decode_request(client, method, url);
|
||||||
sprintf(path, server_config.htdocs);
|
sprintf(path, server_config.htdocs);
|
||||||
strcat(path, url);
|
strcat(path, url);
|
||||||
//if (path[strlen(path) - 1] == '/')
|
//if (path[strlen(path) - 1] == '/')
|
||||||
// strcat(path, "index.html");
|
// strcat(path, "index.html");
|
||||||
if (stat(path, &st) == -1) {
|
if (stat(path, &st) == -1) {
|
||||||
if(execute_plugin(client,url,method,query_string) < 0)
|
if(execute_plugin(client,oldurl,method,rq) < 0)
|
||||||
not_found(client);
|
not_found(client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -89,7 +68,7 @@ void accept_request(int client)
|
|||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
strcat(path, "/index.html");
|
strcat(path, "/index.html");
|
||||||
// check if the mime is supported
|
// check if the mime is supported
|
||||||
// if the minme is not supported
|
// if the mime is not supported
|
||||||
// find an handler plugin to process it
|
// find an handler plugin to process it
|
||||||
// if the plugin is not found, forbidden access to the file should be sent
|
// if the plugin is not found, forbidden access to the file should be sent
|
||||||
char* mime_type = mime(path);
|
char* mime_type = mime(path);
|
||||||
@ -97,21 +76,76 @@ void accept_request(int client)
|
|||||||
{
|
{
|
||||||
sprintf(buf,"/%s-api%s",ext(path),url);
|
sprintf(buf,"/%s-api%s",ext(path),url);
|
||||||
LOG("WARNING::::Access octetstream via handler %s\n", buf);
|
LOG("WARNING::::Access octetstream via handler %s\n", buf);
|
||||||
if(execute_plugin(client,buf,method,query_string) < 0)
|
if(execute_plugin(client,buf,method,rq) < 0)
|
||||||
cannot_execute(client);
|
cannot_execute(client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ctype(client,mime_type);
|
ctype(client,mime_type);
|
||||||
// if the mime is supported, send the file
|
// if the mime is supported, send the file
|
||||||
serve_file(client, path);
|
serve_file(client, path);
|
||||||
|
//response(client,"this is the file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(oldurl);
|
||||||
|
free(rq);
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rule_check(association it, const char* host, const char* _url, const char* _query, char* buf)
|
||||||
|
{
|
||||||
|
// first perfom rule check on host, if not success, perform on url
|
||||||
|
regmatch_t key_matches[10];
|
||||||
|
regmatch_t val_matches[2];
|
||||||
|
char* query = strdup(_query);
|
||||||
|
char* url = strdup(_url);
|
||||||
|
int ret;
|
||||||
|
char* target;
|
||||||
|
char* tmp, rep[10];
|
||||||
|
int idx = 0;
|
||||||
|
memset(rep,0,10);
|
||||||
|
// 1 group
|
||||||
|
if( !(ret = regex_match(it->key,host, 10, key_matches)) )
|
||||||
|
{
|
||||||
|
target = url;
|
||||||
|
ret = regex_match(it->key,url, 10, key_matches);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
target = host;
|
||||||
|
|
||||||
|
if(!ret) return;
|
||||||
|
tmp = (char*) it->value;
|
||||||
|
|
||||||
|
while((ret = regex_match( "{([a-zA-Z0-9]+)}",tmp, 2, val_matches)))
|
||||||
|
{
|
||||||
|
memcpy(buf + idx, tmp, val_matches[1].rm_so - 1);
|
||||||
|
idx += val_matches[1].rm_so - 1;
|
||||||
|
memcpy(rep, tmp + val_matches[1].rm_so, val_matches[1].rm_eo - val_matches[1].rm_so);
|
||||||
|
if(strcasecmp(rep,"url") == 0)
|
||||||
|
{
|
||||||
|
memcpy(buf+idx, url, strlen(url));
|
||||||
|
idx += strlen(url);
|
||||||
|
} else if(strcasecmp(rep,"query") == 0)
|
||||||
|
{
|
||||||
|
memcpy(buf+idx, query, strlen(query));
|
||||||
|
idx += strlen(query);
|
||||||
|
} else if(match_int(rep))
|
||||||
|
{
|
||||||
|
int i = atoi(rep);
|
||||||
|
memcpy(buf+idx, target + key_matches[i].rm_so, key_matches[i].rm_eo - key_matches[i].rm_so);
|
||||||
|
idx += key_matches[i].rm_eo - key_matches[i].rm_so;
|
||||||
|
} else { // just keep it
|
||||||
|
memcpy(buf+idx, tmp + val_matches[1].rm_so-1, val_matches[1].rm_eo + 2 - val_matches[1].rm_so);
|
||||||
|
idx+= val_matches[1].rm_eo + 2 - val_matches[1].rm_so;
|
||||||
|
}
|
||||||
|
tmp += val_matches[1].rm_eo + 1;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
// now modify the match 2 group
|
||||||
|
if(idx > 0) buf[idx] = '\0';
|
||||||
|
free(url);
|
||||||
|
free(query);
|
||||||
|
}
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* Put the entire contents of a file out on a socket. This function
|
/* Put the entire contents of a file out on a socket. This function
|
||||||
* is named after the UNIX "cat" command, because it might have been
|
* is named after the UNIX "cat" command, because it might have been
|
||||||
@ -242,11 +276,11 @@ void serve_file(int client, const char *filename)
|
|||||||
{
|
{
|
||||||
FILE *resource = NULL;
|
FILE *resource = NULL;
|
||||||
int numchars = 1;
|
int numchars = 1;
|
||||||
char buf[1024];
|
//char buf[1024];
|
||||||
|
|
||||||
buf[0] = 'A'; buf[1] = '\0';
|
//buf[0] = 'A'; buf[1] = '\0';
|
||||||
while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
|
//while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
|
||||||
numchars = get_line(client, buf, sizeof(buf));
|
// numchars = get_line(client, buf, sizeof(buf));
|
||||||
|
|
||||||
resource = fopen(filename, "rb");
|
resource = fopen(filename, "rb");
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
@ -339,6 +373,34 @@ char* post_url_decode(int client,int len)
|
|||||||
LOG("POST Query %s\n", query);
|
LOG("POST Query %s\n", query);
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
char* apply_rules(const char* host, char*url)
|
||||||
|
{
|
||||||
|
association it;
|
||||||
|
// rule check
|
||||||
|
char* query_string = url;
|
||||||
|
while ((*query_string != '?') && (*query_string != '\0'))
|
||||||
|
query_string++;
|
||||||
|
if (*query_string == '?')
|
||||||
|
{
|
||||||
|
*query_string = '\0';
|
||||||
|
query_string++;
|
||||||
|
}
|
||||||
|
//char* oldurl = strdup(url);
|
||||||
|
for_each_assoc(it, server_config.rules)
|
||||||
|
{
|
||||||
|
// 1 group
|
||||||
|
rule_check(it,host, url, query_string, url);
|
||||||
|
query_string = url;
|
||||||
|
while ((*query_string != '?') && (*query_string != '\0'))
|
||||||
|
query_string++;
|
||||||
|
if (*query_string == '?')
|
||||||
|
{
|
||||||
|
*query_string = '\0';
|
||||||
|
query_string++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strdup(query_string);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Decode the HTTP request
|
* Decode the HTTP request
|
||||||
* Get the cookie values
|
* Get the cookie values
|
||||||
@ -352,13 +414,14 @@ char* post_url_decode(int client,int len)
|
|||||||
* @param query query string in case of GET
|
* @param query query string in case of GET
|
||||||
* @return a dictionary of key- value
|
* @return a dictionary of key- value
|
||||||
*/
|
*/
|
||||||
dictionary decode_request(int client,const char* method,const char* query)
|
dictionary decode_request(int client,const char* method, char* url)
|
||||||
{
|
{
|
||||||
dictionary request = NULL;
|
dictionary request = NULL;
|
||||||
dictionary cookie = NULL;
|
dictionary cookie = NULL;
|
||||||
dictionary xheader = dict();
|
dictionary xheader = dict();
|
||||||
char* line;
|
char* line;
|
||||||
char * token;
|
char * token;
|
||||||
|
char* query = NULL;
|
||||||
if(strcmp(method,"GET") == 0)
|
if(strcmp(method,"GET") == 0)
|
||||||
{
|
{
|
||||||
// this for check if web socket is enabled
|
// this for check if web socket is enabled
|
||||||
@ -382,7 +445,11 @@ dictionary decode_request(int client,const char* method,const char* query)
|
|||||||
trim(line, ' ');
|
trim(line, ' ');
|
||||||
if(line != NULL && strcasecmp(line,"websocket") == 0)
|
if(line != NULL && strcasecmp(line,"websocket") == 0)
|
||||||
ws = 1;
|
ws = 1;
|
||||||
} else if(token != NULL && strcasecmp(token,"Sec-WebSocket-Key") == 0)
|
}else if(token != NULL && strcasecmp(token,"Host") == 0)
|
||||||
|
{
|
||||||
|
query = apply_rules(line, url);
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcasecmp(token,"Sec-WebSocket-Key") == 0)
|
||||||
{
|
{
|
||||||
// get the key from the client
|
// get the key from the client
|
||||||
trim(line, ' ');
|
trim(line, ' ');
|
||||||
@ -390,6 +457,7 @@ dictionary decode_request(int client,const char* method,const char* query)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
request = decode_url_request(query);
|
request = decode_url_request(query);
|
||||||
|
if(query) free(query);
|
||||||
if(ws && ws_key != NULL)
|
if(ws && ws_key != NULL)
|
||||||
{
|
{
|
||||||
ws_confirm_request(client, ws_key);
|
ws_confirm_request(client, ws_key);
|
||||||
@ -424,6 +492,9 @@ dictionary decode_request(int client,const char* method,const char* query)
|
|||||||
token = strsep(&line,":");
|
token = strsep(&line,":");
|
||||||
trim(token,' ');
|
trim(token,' ');
|
||||||
clen = atoi(token);
|
clen = atoi(token);
|
||||||
|
}else if(token != NULL && strcasecmp(token,"Host") == 0)
|
||||||
|
{
|
||||||
|
apply_rules(line, url);
|
||||||
}
|
}
|
||||||
else if(token != NULL &&strcasecmp(token,"Cookie") == 0)
|
else if(token != NULL &&strcasecmp(token,"Cookie") == 0)
|
||||||
{
|
{
|
||||||
@ -735,7 +806,7 @@ char* json_data_decode(int client,int len)
|
|||||||
* @return -1 if failure
|
* @return -1 if failure
|
||||||
* 1 if sucess
|
* 1 if sucess
|
||||||
*/
|
*/
|
||||||
int execute_plugin(int client, const char *path, const char *method, const char *query_string)
|
int execute_plugin(int client, const char *path, const char *method, dictionary dic)
|
||||||
{
|
{
|
||||||
char pname[255];
|
char pname[255];
|
||||||
char pfunc[255];
|
char pfunc[255];
|
||||||
@ -768,7 +839,7 @@ int execute_plugin(int client, const char *path, const char *method, const char
|
|||||||
LOG("Method:%s\n", method);
|
LOG("Method:%s\n", method);
|
||||||
LOG("Plugin name '%s'\n",pname);
|
LOG("Plugin name '%s'\n",pname);
|
||||||
LOG("Query path. '%s'\n", pfunc);
|
LOG("Query path. '%s'\n", pfunc);
|
||||||
LOG("query :%s\n", query_string);
|
//LOG("query :%s\n", query_string);
|
||||||
|
|
||||||
//load the plugin
|
//load the plugin
|
||||||
if((plugin = plugin_lookup(pname)) == NULL)
|
if((plugin = plugin_lookup(pname)) == NULL)
|
||||||
@ -781,9 +852,9 @@ int execute_plugin(int client, const char *path, const char *method, const char
|
|||||||
LOG("Problem when finding %s method from %s : %s \n", PLUGIN_HANDLER, pname,error);
|
LOG("Problem when finding %s method from %s : %s \n", PLUGIN_HANDLER, pname,error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dictionary dic = decode_request(client,method,query_string);
|
//dictionary dic = decode_request(client,method,query_string);
|
||||||
(*fn)(client,method,pfunc,dic);
|
(*fn)(client,method,pfunc,dic);
|
||||||
free(dic);
|
//free(dic);
|
||||||
free(rpath);
|
free(rpath);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -31,15 +31,16 @@ void serve_file(int, const char *);
|
|||||||
int startup(unsigned *);
|
int startup(unsigned *);
|
||||||
void unimplemented(int);
|
void unimplemented(int);
|
||||||
void badrequest(int);
|
void badrequest(int);
|
||||||
|
void rule_check(association, const char* , const char* , const char* , char*);
|
||||||
void ws_confirm_request(int, const char*);
|
void ws_confirm_request(int, const char*);
|
||||||
char* post_url_decode(int client,int len);
|
char* post_url_decode(int client,int len);
|
||||||
dictionary decode_url_request(const char* query);
|
dictionary decode_url_request(const char* query);
|
||||||
dictionary decode_request(int client,const char* method,const char* query);
|
dictionary decode_request(int client,const char* method, char* url);
|
||||||
dictionary decode_multi_part_request(int,const char*);
|
dictionary decode_multi_part_request(int,const char*);
|
||||||
dictionary decode_cookie(const char*);
|
dictionary decode_cookie(const char*);
|
||||||
char* json_data_decode(int,int);
|
char* json_data_decode(int,int);
|
||||||
|
|
||||||
int execute_plugin(int client, const char *path,
|
int execute_plugin(int client, const char *path,
|
||||||
const char *method, const char *query_string);
|
const char *method, dictionary rq);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
void set_status(int client,int code,const char* msg)
|
void set_status(int client,int code,const char* msg)
|
||||||
{
|
{
|
||||||
response(client, __s("HTTP/1.0 %d %s", code, msg));
|
response(client, __s("HTTP/1.1 %d %s", code, msg));
|
||||||
response(client, __s("Server: %s ", SERVER_NAME));
|
response(client, __s("Server: %s ", SERVER_NAME));
|
||||||
}
|
}
|
||||||
void redirect(int client,const char*path)
|
void redirect(int client,const char*path)
|
||||||
|
@ -193,11 +193,11 @@ int is_bin(const char* file)
|
|||||||
|
|
||||||
int match_int(const char* search)
|
int match_int(const char* search)
|
||||||
{
|
{
|
||||||
return regex_match("^[-+]?[0-9]+$",search);
|
return regex_match("^[-+]?[0-9]+$",search,0, NULL);
|
||||||
}
|
}
|
||||||
int match_float(const char* search)
|
int match_float(const char* search)
|
||||||
{
|
{
|
||||||
return regex_match("^[+-]?[0-9]*\\.[0-9]+$",search);
|
return regex_match("^[+-]?[0-9]*\\.[0-9]+$",search,0,NULL);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
regmatch_t matches[MAX_MATCHES];
|
regmatch_t matches[MAX_MATCHES];
|
||||||
@ -206,7 +206,7 @@ if (regexec(&exp, sz, MAX_MATCHES, matches, 0) == 0) {
|
|||||||
printf("group1: %s\n", buff);
|
printf("group1: %s\n", buff);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
int regex_match(const char* expr,const char* search)
|
int regex_match(const char* expr,const char* search, int msize, regmatch_t* matches)
|
||||||
{
|
{
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
int reti;
|
int reti;
|
||||||
@ -220,7 +220,7 @@ int regex_match(const char* expr,const char* search)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Execute regular expression */
|
/* Execute regular expression */
|
||||||
reti = regexec(®ex, search, 0, NULL, 0);
|
reti = regexec(®ex, search, msize, matches, 0);
|
||||||
if( !reti ){
|
if( !reti ){
|
||||||
//LOG("Match");
|
//LOG("Match");
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -84,7 +84,7 @@ char* mime(const char*);
|
|||||||
int is_bin(const char*);
|
int is_bin(const char*);
|
||||||
int match_int(const char*);
|
int match_int(const char*);
|
||||||
int match_float(const char*);
|
int match_float(const char*);
|
||||||
int regex_match(const char*,const char*);
|
int regex_match(const char*,const char*, int, regmatch_t*);
|
||||||
char *url_decode(const char *str);
|
char *url_decode(const char *str);
|
||||||
char *url_encode(const char *str);
|
char *url_encode(const char *str);
|
||||||
char from_hex(char ch);
|
char from_hex(char ch);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user