support of rule, useful for sub domain remapping

This commit is contained in:
Xuan Sang LE 2018-02-04 19:46:47 +01:00
parent 01c32d964e
commit ff3c68ff64
5 changed files with 123 additions and 51 deletions

View File

@ -16,7 +16,7 @@ void accept_request(int client)
size_t i, j;
struct stat st;
char *query_string = NULL;
//char *query_string = NULL;
numchars = get_line(client, buf, sizeof(buf));
i = 0; j = 0;
@ -28,7 +28,7 @@ void accept_request(int client)
method[i] = '\0';
if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
{
printf("METHOD NOT FOUND %s\n", method);
LOG("METHOD NOT FOUND %s\n", method);
// unimplemented
//while(get_line(client, buf, sizeof(buf)) > 0) printf("%s\n",buf );
unimplemented(client);
@ -47,41 +47,20 @@ void accept_request(int client)
}
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);
strcat(path, url);
//if (path[strlen(path) - 1] == '/')
// strcat(path, "index.html");
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);
}
else
@ -89,7 +68,7 @@ void accept_request(int client)
if (S_ISDIR(st.st_mode))
strcat(path, "/index.html");
// 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
// if the plugin is not found, forbidden access to the file should be sent
char* mime_type = mime(path);
@ -97,21 +76,76 @@ void accept_request(int client)
{
sprintf(buf,"/%s-api%s",ext(path),url);
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);
}
else
{
ctype(client,mime_type);
// if the mime is supported, send the file
// if the mime is supported, send the file
serve_file(client, path);
//response(client,"this is the file");
}
}
free(oldurl);
free(rq);
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
* 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;
int numchars = 1;
char buf[1024];
//char buf[1024];
buf[0] = 'A'; buf[1] = '\0';
while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
numchars = get_line(client, buf, sizeof(buf));
//buf[0] = 'A'; buf[1] = '\0';
//while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
// numchars = get_line(client, buf, sizeof(buf));
resource = fopen(filename, "rb");
if (resource == NULL)
@ -339,6 +373,34 @@ char* post_url_decode(int client,int len)
LOG("POST Query %s\n", 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
* Get the cookie values
@ -352,13 +414,14 @@ char* post_url_decode(int client,int len)
* @param query query string in case of GET
* @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 cookie = NULL;
dictionary xheader = dict();
char* line;
char * token;
char* query = NULL;
if(strcmp(method,"GET") == 0)
{
// 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, ' ');
if(line != NULL && strcasecmp(line,"websocket") == 0)
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
trim(line, ' ');
@ -390,6 +457,7 @@ dictionary decode_request(int client,const char* method,const char* query)
}
}
request = decode_url_request(query);
if(query) free(query);
if(ws && ws_key != NULL)
{
ws_confirm_request(client, ws_key);
@ -424,6 +492,9 @@ dictionary decode_request(int client,const char* method,const char* query)
token = strsep(&line,":");
trim(token,' ');
clen = atoi(token);
}else if(token != NULL && strcasecmp(token,"Host") == 0)
{
apply_rules(line, url);
}
else if(token != NULL &&strcasecmp(token,"Cookie") == 0)
{
@ -735,7 +806,7 @@ char* json_data_decode(int client,int len)
* @return -1 if failure
* 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 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("Plugin name '%s'\n",pname);
LOG("Query path. '%s'\n", pfunc);
LOG("query :%s\n", query_string);
//LOG("query :%s\n", query_string);
//load the plugin
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);
return -1;
}
dictionary dic = decode_request(client,method,query_string);
//dictionary dic = decode_request(client,method,query_string);
(*fn)(client,method,pfunc,dic);
free(dic);
//free(dic);
free(rpath);
return 1;
}

View File

@ -31,15 +31,16 @@ void serve_file(int, const char *);
int startup(unsigned *);
void unimplemented(int);
void badrequest(int);
void rule_check(association, const char* , const char* , const char* , char*);
void ws_confirm_request(int, const char*);
char* post_url_decode(int client,int len);
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_cookie(const char*);
char* json_data_decode(int,int);
int execute_plugin(int client, const char *path,
const char *method, const char *query_string);
const char *method, dictionary rq);
#endif

View File

@ -3,7 +3,7 @@
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));
}
void redirect(int client,const char*path)

View File

@ -193,11 +193,11 @@ int is_bin(const char* file)
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)
{
return regex_match("^[+-]?[0-9]*\\.[0-9]+$",search);
return regex_match("^[+-]?[0-9]*\\.[0-9]+$",search,0,NULL);
}
/*
regmatch_t matches[MAX_MATCHES];
@ -206,7 +206,7 @@ if (regexec(&exp, sz, MAX_MATCHES, matches, 0) == 0) {
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;
int reti;
@ -220,7 +220,7 @@ int regex_match(const char* expr,const char* search)
}
/* Execute regular expression */
reti = regexec(&regex, search, 0, NULL, 0);
reti = regexec(&regex, search, msize, matches, 0);
if( !reti ){
//LOG("Match");
ret = 1;

View File

@ -84,7 +84,7 @@ char* mime(const char*);
int is_bin(const char*);
int match_int(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_encode(const char *str);
char from_hex(char ch);