static void * accept_request(void *arg) { int sock = (int)arg; char buf[_SIZE_]; char method[_SIZE_/10]; char url[_SIZE_]; char path[_SIZE_]; memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(method)); memset(buf, '\0', sizeof(url)); memset(buf, '\0', sizeof(path)); int cgi = 0; int ret = -1; char *query_string = NULL; // 数据参数 int len = sizeof(buf) / sizeof(buf[0]); #ifdef _DEBUG_ do { // http 请求 报文 按行存储 ret = get_line(sock, buf, len); printf("%s", buf); fflush(stdout); } while (ret > 0 && strcmp(buf, "\n") != 0); #endif ret = get_line(sock, buf, len); // 获取请求行 printf("line: %s\n", buf); if (ret < 0) { echo_errno(sock); return (void*)1; } // GET / HTTP/1.0 int i = 0; // method index int j = 0; // buf index // 请求行 包括 【方法(GET/POST)】【url】【HTTP/1.0(1.1)】 // 获取方法 GET/POST while ((i < sizeof(method) - 1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { method[i] = buf[j]; ++i; ++j; } method[i] = '\0'; // strcasecmp 忽略大小写的比较 if (strcasecmp(method, "GET") != 0 && strcasecmp(method, "POST") != 0) { echo_errno(sock); return (void*)2; } // 跳过空格 while (j < sizeof(buf) && isspace(buf[j])) { j++; } i = 0; // 获取url url是除了域名 端口号之后的 /。。。 while ((i < sizeof(url) - 1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { url[i++] = buf[j++]; } url[i] = '\0'; //GET 所传递的参数 在URL中, 从server的QUERY_STRING 中获取 //POST 所传递的参数 在 数据包中 从server环境变量中CONTENT_LENGTH 环境变量中获取参数 数据的长度 if (strcasecmp(method, "POST") == 0) { cgi = 1; } if (strcasecmp(method, "GET") == 0) { query_string = url; // 路径和数据参数 以?分隔 如 http:// baidu.com /s ? k = v while (*query_string != '\0' && *query_string != '?') { ++query_string; } if(*query_string == '?') // GET 带参数 需要进一步处理参数 { cgi = 1; *query_string++ = '\0'; } } // 没指定具体网页 加默认网页 和 根文件夹(安全考虑) sprintf(path, "httpdoc%s", url); if (path[strlen(path) - 1] == '/') { strcat(path, "index.html"); } // method , query_string, cgi, path struct stat st; if (stat(path, &st) < 0) // 测文件在不在 { echo_errno(sock); return (void*)3; } else { if (S_ISDIR(st.st_mode))// 测是不是 文件夹 { strcat(path, "/index.html"); } else if( (st.st_mode & S_IXUSR) ||\ (st.st_mode & S_IXGRP) ||\ (st.st_mode & S_IXOTH)) // 查看cgi执行权限 { cgi = 1; } else {} if (cgi) { exec_cgi(sock, method, path, query_string); } else { clear_header(sock); // echo_www(sock, path, st.st_size); } } }
void* accept_request(void* arg) { pthread_detach(pthread_self()); int sock = (int)arg; char buf[_SIZE_]; char method[_SIZE_]; char url[_SIZE_]; char path[_SIZE_]; memset(buf, '\0', sizeof(buf)); memset(method, '\0', sizeof(method)); memset(url, '\0', sizeof(url)); memset(path, '\0', sizeof(path)); int cgi = 0; int ret = -1; char* query_string = NULL; #ifdef _DEBUG_ do{ ret = get_line(sock, buf, sizeof(buf)); printf("%s", buf); fflush(stdout); } while((ret > 0) && (strcmp(buf, "\n") != 0)); #endif ret = get_line(sock, buf, sizeof(buf)); if(ret < 0) { echo_errno(sock); return (void *)1; } //GET /HTTP/1.1 int i = 0; // method index int j = 0; // buf index while( (i < sizeof(method)-1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { method[i] = buf[j]; i++, j++; } method[i] = '\0'; while( isspace(buf[j]) ) { j++; } if(strcasecmp(method, "GET") != 0 && strcasecmp(method, "POST") != 0) { echo_errno(sock); return (void*)2; } if(strcasecmp(method, "POST") == 0) { cgi = 1; } i = 0; // url index while( (i<sizeof(url)-1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { url[i] = buf[j]; i++, j++; } if(strcasecmp(method, "GET") == 0) { query_string = url; while(*query_string != '\0' && *query_string != '?' ) { query_string++; } if(*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } // / /aa/bb/cc sprintf(path, "htdoc%s", url); // htdoc/ if(path[strlen(path) - 1] == '/') { strcat(path, "index.html"); } printf("method: %s\n", method); printf("path: %s\n", path); printf("query_string: %s\n", query_string); struct stat st; if(stat(path, &st) < 0) { echo_errno(sock); return (void*)3; } else { if(S_ISDIR(st.st_mode)) { strcpy(path, "htdoc/index.html"); } else if( (st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) { cgi = 1; } else {} if(cgi) { exec_cgi(sock, path, method, query_string); } else { clear_header(sock); echo_html(sock, path, st.st_size); } } close(sock); return (void*)0; }