void process(int fd, fd_set *pMaster, struct sockaddr_in *clientaddr){ printf("accept request, fd is %d, pid is %d\n", fd, getpid()); int status = 200; char buf[1024]; u_int numchars; char method[255]; char url[1024]; size_t i, j; int client=fd; numchars = getLine(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return; } i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; Request request; request.client=client; request.reqStr=url; request.method=method; /*server(client,url,method);*/ server(request); close(client); http_request req; strncpy(req.filename, url, sizeof req.filename); log_access(status, clientaddr, &req); }
//parse the first line into the array //and store url method version into the header int parse_resquest(char* buff,http_header* pheader) { int i,j; i = j = 0; //read the method into the array while(!ISspace(buff[i]) && i<(sizeof(pheader->method) -1) ) { pheader->method[j] = buff[i]; i++,j++; } pheader->method[i] = '\0'; //if the method not the "GET",return the unimplemented if( strcmp(pheader->method,"GET") != 0) { // debug_info printf("this method unimplemented !"); //unimplemented method //unimplemented(cli_fd); //return -1 (method is unimplemented) return -1; } //skip all the space while(ISspace(buff[j]) && j<sizeof(buff)) j++; //read the url into the array i = 0 ; while(!ISspace(buff[j]) && i<sizeof(pheader->url)) { pheader->url[i] = buff[j]; i++,j++; } pheader->url[i] = '\0'; //read the version into the array while(ISspace(buff[j]) && j<sizeof(buff)) j++; i = 0; while(!ISspace(buff[j]) && i<sizeof(pheader->version) ) { pheader->version[i] = buff[j]; i++,j++; } pheader->version[j] = '\0'; return 0; }
//Parse the request int http_getrequest(char* buf, int size, char* src_buf) { int i = 0; int j = 0; while (ISspace(src_buf[j])) j++; while (!ISspace(src_buf[i+j]) && (i < size-1)) { buf[i] = src_buf[i+j]; i++; } buf[i] = '\0'; return i+j; }
/** * Read event for EPOLLIN on the httpd protocol module. * * @param dcb The descriptor control block * @return */ static int httpd_read_event(DCB* dcb) { //SESSION *session = dcb->session; //ROUTER_OBJECT *router = session->service->router; //ROUTER *router_instance = session->service->router_instance; //void *rsession = session->router_session; int numchars = 1; char buf[HTTPD_REQUESTLINE_MAXLEN-1] = ""; char *query_string = NULL; char method[HTTPD_METHOD_MAXLEN-1] = ""; char url[HTTPD_SMALL_BUFFER] = ""; int cgi = 0; size_t i, j; int headers_read = 0; HTTPD_session *client_data = NULL; client_data = dcb->data; /** * get the request line * METHOD URL HTTP_VER\r\n */ numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; strcpy(client_data->method, method); /* check allowed http methods */ if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { //httpd_unimplemented(dcb->fd); return 0; } if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) { j++; } while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; /** * Get the query string if availble */ if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } /** * Get the request headers */ while ((numchars > 0) && strcmp("\n", buf)) { char *value = NULL; char *end = NULL; numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); if ( (value = strchr(buf, ':'))) { *value = '\0'; value++; end = &value[strlen(value) -1]; *end = '\0'; if (strncasecmp(buf, "Hostname", 6) == 0) { strcpy(client_data->hostname, value); } if (strncasecmp(buf, "useragent", 9) == 0) { strcpy(client_data->useragent, value); } } } if (numchars) { headers_read = 1; memcpy(&client_data->headers_received, &headers_read, sizeof(int)); } /** * Now begins the server reply */ /* send all the basic headers and close with \r\n */ httpd_send_headers(dcb, 1); /** * ToDO: launch proper content handling based on the requested URI, later REST interface * */ dcb_printf(dcb, "Welcome to HTTPD Gateway (c) %s\n\n", version_str); if (strcmp(url, "/show") == 0) { if (strlen(query_string)) { if (strcmp(query_string, "dcb") == 0) dprintAllDCBs(dcb); if (strcmp(query_string, "session") == 0) dprintAllSessions(dcb); } } /* force the client connecton close */ dcb->func.close(dcb); return 0; }
void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return; } if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } //sprintf(path, "htdocs%s", url); sprintf(path, ".%s", url); if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); if (stat(path, &st) == -1) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { if ((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; cgi = 0;//must not cgi if (!cgi) serve_file(client, path); else execute_cgi(client, path, method, query_string); } close(client); }
void* accept_request(void* client1) //accept_request解析header里面的第一行获得request method(get/post)和请求路径,映射到htdoc文件夹下的路径, //其中当对应的文件可执行的时候,就调用execute_cgi函数 { int client = (intptr_t)client1; char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); // 仅仅支持GET和POST方法,否则抛出未支持的方法 return NULL; } if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } sprintf(path, "htdocs%s", url); if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); if (stat(path, &st) == -1) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { if ((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; if (!cgi) serve_file(client, path); else execute_cgi(client, path, method, query_string); } close(client); return NULL; }
void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf));//把client里的\r都换成\n i = 0; j = 0; //找出method是get还是post,只支持这两种方法 while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; //函数说明 strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异。 //返回值 若参数s1和s2字符串相等则返回0。s1大于s2则返回大于0 的值,s1 小于s2 则返回小于0的值。 if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client);//返回给浏览器表明收到的 HTTP 请求所用的 method 不被支持。 return; } if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; //找出URL while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } sprintf(path, "htdocs%s", url); if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); if (stat(path, &st) == -1) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { if ((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; if (!cgi) serve_file(client, path); else execute_cgi(client, path, method, query_string); } close(client); }
void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI program */ char *query_string = NULL; /*得到请求的第一行*/ numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; /*把客户端的请求方法存到 method 数组*/ while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; /*如果既不是 GET 又不是 POST 则无法处理 */ if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return; } /* POST 的时候开启 cgi */ if (strcasecmp(method, "POST") == 0) cgi = 1; /*读取 url 地址*/ i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { /*存下 url */ url[i] = buf[j]; i++; j++; } url[i] = '\0'; /*处理 GET 方法*/ if (strcasecmp(method, "GET") == 0) { /* 待处理请求为 url */ query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; /* GET 方法特点,? 后面为参数*/ if (*query_string == '?') { /*开启 cgi */ cgi = 1; *query_string = '\0'; query_string++; } } /*格式化 url 到 path 数组,html 文件都在 htdocs 中*/ sprintf(path, "htdocs%s", url); /*默认情况为 index.html */ if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); /*根据路径找到对应文件 */ if (stat(path, &st) == -1) { /*把所有 headers 的信息都丢弃*/ while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); /*回应客户端找不到*/ not_found(client); } else { /*如果是个目录,则默认使用该目录下 index.html 文件*/ if ((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; /*不是 cgi,直接把服务器文件返回,否则执行 cgi */ if (!cgi) serve_file(client, path); else execute_cgi(client, path, method, query_string); } /*断开与客户端的连接(HTTP 特点:无连接)*/ close(client); }
void accept_request(void *arg) { int client = *((int*)arg); char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; //读http 请求的第一行数据(request line),把请求方法存进 method 中 numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; //如果请求的方法不是 GET 或 POST 任意一个的话就直接发送 response 告诉客户端没实现该方法 if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return; } //如果是 POST 方法就将 cgi 标志变量置一(true) if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; //跳过所有的空白字符(空格) while (ISspace(buf[j]) && (j < sizeof(buf))) j++; //然后把 URL 读出来放到 url 数组中 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; //如果这个请求是一个 GET 方法的话 if (strcasecmp(method, "GET") == 0) { //用一个指针指向 url query_string = url; //去遍历这个 url,跳过字符 ?前面的所有字符,如果遍历完毕也没找到字符 ?则退出循环 while ((*query_string != '?') && (*query_string != '\0')) query_string++; //退出循环后检查当前的字符是 ?还是字符串(url)的结尾 if (*query_string == '?') { //如果是 ? 的话,证明这个请求需要调用 cgi,将 cgi 标志变量置一(true) cgi = 1; //从字符 ? 处把字符串 url 给分隔会两份 *query_string = '\0'; //使指针指向字符 ?后面的那个字符 query_string++; } } //将前面分隔两份的前面那份字符串,拼接在字符串htdocs的后面之后就输出存储到数组 path 中。相当于现在 path 中存储着一个字符串 sprintf(path, "htdocs%s", url); //如果 path 数组中的这个字符串的最后一个字符是以字符 / 结尾的话,就拼接上一个"index.html"的字符串。首页的意思 if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); //在系统上去查询该文件是否存在 if (stat(path, &st) == -1) { //如果不存在,那把这次 http 的请求后续的内容(head 和 body)全部读完并忽略 while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); //然后返回一个找不到文件的 response 给客户端 not_found(client); } else { LOG_INFO("accept request 1"); //文件存在,那去跟常量S_IFMT相与,相与之后的值可以用来判断该文件是什么类型的 //S_IFMT参读《TLPI》P281,与下面的三个常量一样是包含在<sys/stat.h> if ((st.st_mode & S_IFMT) == S_IFDIR) //如果这个文件是个目录,那就需要再在 path 后面拼接一个"/index.html"的字符串 strcat(path, "/index.html"); //S_IXUSR, S_IXGRP, S_IXOTH三者可以参读《TLPI》P295 if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) //如果这个文件是一个可执行文件,不论是属于用户/组/其他这三者类型的,就将 cgi 标志变量置一 cgi = 1; if (!cgi) //如果不需要 cgi 机制的话, serve_file(client, path); else //如果需要则调用 execute_cgi(client, path, method, query_string); } LOG_INFO("accept request end"); close(client); }
/** * Read event for EPOLLIN on the httpd protocol module. * * @param dcb The descriptor control block * @return */ static int httpd_read_event(DCB* dcb) { SESSION *session = dcb->session; ROUTER_OBJECT *router = session->service->router; ROUTER *router_instance = session->service->router_instance; void *rsession = session->router_session; int numchars = 1; char buf[HTTPD_REQUESTLINE_MAXLEN-1] = ""; char *query_string = NULL; char method[HTTPD_METHOD_MAXLEN-1] = ""; char url[HTTPD_SMALL_BUFFER] = ""; size_t i, j; int headers_read = 0; HTTPD_session *client_data = NULL; GWBUF *uri; client_data = dcb->data; /** * get the request line * METHOD URL HTTP_VER\r\n */ numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; strcpy(client_data->method, method); /* check allowed http methods */ if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { //httpd_unimplemented(dcb->fd); return 0; } i = 0; while ( (j < sizeof(buf)) && ISspace(buf[j])) { j++; } while ((j < sizeof(buf) - 1) && !ISspace(buf[j]) && (i < sizeof(url) - 1)) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; /** * Get the query string if availble */ 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 request headers */ while ((numchars > 0) && strcmp("\n", buf)) { char *value = NULL; char *end = NULL; numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); if ((value = strchr(buf, ':'))) { *value = '\0'; value++; end = &value[strlen(value) -1]; *end = '\0'; if (strncasecmp(buf, "Hostname", 6) == 0) { strcpy(client_data->hostname, value); } if (strncasecmp(buf, "useragent", 9) == 0) { strcpy(client_data->useragent, value); } } } if (numchars) { headers_read = 1; memcpy(&client_data->headers_received, &headers_read, sizeof(int)); } /** * Now begins the server reply */ /* send all the basic headers and close with \r\n */ httpd_send_headers(dcb, 1); #if 0 /** * ToDO: launch proper content handling based on the requested URI, later REST interface * */ if (strcmp(url, "/show") == 0) { if (query_string && strlen(query_string)) { if (strcmp(query_string, "dcb") == 0) { dprintAllDCBs(dcb); } if (strcmp(query_string, "session") == 0) { dprintAllSessions(dcb); } } } if (strcmp(url, "/services") == 0) { RESULTSET *set, *seviceGetList(); if ((set = serviceGetList()) != NULL) { resultset_stream_json(set, dcb); resultset_free(set); } } #endif if ((uri = gwbuf_alloc(strlen(url) + 1)) != NULL) { strcpy((char *)GWBUF_DATA(uri), url); gwbuf_set_type(uri, GWBUF_TYPE_HTTP); SESSION_ROUTE_QUERY(session, uri); } /* force the client connecton close */ dcb_close(dcb); return 0; }
void* accept_request(void* arg) { int client=(int)arg; char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0;/* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; //解析method:GET OR POST? while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return NULL; } //如果method为POST,则开启CGI; if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; //获取method对应的url,例如:url=/color.cgi?color=red; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; //如果method为GET,判断url中是否有CGI; if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } sprintf(path, "htdocs%s", url); if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); if (stat(path, &st) == -1) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { if ((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); //如果path指定的文件为可执行文件,则CGI置位; if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; if (!cgi) serve_file(client, path); else execute_cgi(client, path, method, query_string); } close(client); return NULL; }
/* ******************************** * @描述:处理客户端HTTP请求 * @输入:[in] client: 客户端地址 * @输出: 无 * ********************************/ void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; // unsigned int struct stat st; // 保存文件信息 int cgi = 0; // 当服务端认为它是一个CGI时变成1 char *query_string = NULL; /* 得到请求的第一行 */ numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; /* 把客户端的请求方法存到method数组,遇到空格则停止 */ while(!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; /* 既不是GET也不是POST的情况,忽略大小写进行比较 */ if(strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); return; } /* POST的情况,开启CGI */ if(strcasecmp(method, "POST") == 0) cgi = 1; /* 读取URL地址 */ i = 0; while(ISspace(buf[j]) && (j < sizeof(buf)))// 过滤掉空格 j++; while(!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; // 存下URL i++; j++; } url[i] = '\0'; /* 处理GET方法 */ if(strcasecmp(method, "GET") == 0) { query_string = url; /* 找到URL中的? */ while((*query_string != '?') && (*query_string != '\0')) query_string++; /* GET方法特点,?后面为参数 */ if(*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; //query_string指向'?'后面 } } /* 格式化URL到path数组,html文件在htdocs目录中 */ sprintf(path, "htdocs%s", url); /* 默认情况为index.html */ if(path[strlen(path) - 1] == '/')// path中最后一个字符 strcat(path, "index.html"); /* 根据路径找到对应文件 */ if(stat(path, &st) == -1) // 通过文件名path获取文件信息,并保存到st中,-1表示失败 { /* 读取并丢弃header */ while((numchars > 0) && strcmp("\n", buf))// strcmp 相等返回0 numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { /* 如果是目录,则默认使用该目录下的index.html 文件*/ if((st.st_mode & S_IFMT) == S_IFDIR) strcat(path, "/index.html"); if((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) cgi = 1; if(!cgi) // cgi == 0 serve_file(client, path); else // cgi == 1 execute_cgi(client, path, method, query_string); } /* 断开与客户端的连接 */ close(client); }
void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; //int cgi = 0; /* becomes true if server decides this is a CGI program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); close(client); return; } /* if (strcasecmp(method, "POST") == 0) cgi = 1; */ i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { // cgi = 1; *query_string = '\0'; query_string++; } } /* serve_gpio_request(client, NULL); */ logMessage (LOG_DEBUG,"HTTPD processing %s %s\n",url, query_string); if ( strcmp(url, "/gpio") == 0 || strcmp(url, "/gpio/") == 0) { serve_gpio_request(client, query_string); } else if ( strcmp(url, "/led") == 0 || strcmp(url, "/led/") == 0) { serve_led_request(client, query_string); } else if ( strcmp(url, "/mh") == 0 || strcmp(url, "/mh/") == 0) { serve_meteohub_request(client, query_string); } else { if ( _gpioconfig_.docroot != 0 ) sprintf(path, "%s/%s", _gpioconfig_.docroot, url); else sprintf(path, "htdocs%s", url); if (path[strlen(path) - 1] == '/') strcat(path, "index.html"); if (stat(path, &st) == -1) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { if ((st.st_mode & S_IFMT) == S_IFDIR) { while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } else { serve_file(client, path); } /* put cgi in here in the future */ } } close(client); }
// 处理客户端请求,服务器核心控制逻辑 void accept_request(int client) { char buf[1024]; int numchars; char method[255]; char url[255]; char path[512]; size_t i, j; struct stat st; int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); // 读取请求行 i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } // 循环截取出请求方法 method[i] = '\0'; if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) // 只接收GET和POST请求 { unimplemented(client); // 响应未实现页面 return; } if (strcasecmp(method, "POST") == 0) // POST请求 cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) // 刚才截取method后j定位到后面的一个空格处,现在一直向后移动j直到指向非空白字符 j++; while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } // 循环截取出请求的url资源 url[i] = '\0'; if (strcasecmp(method, "GET") == 0) // GET请求 { query_string = url; // 查询字符串在url中的?号后面 while ((*query_string != '?') && (*query_string != '\0')) // 一直移动到?号处 query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; // ?号置为\0,url就切出来了 query_string++; // 查询字符串从?后面一个字符开始 } } sprintf(path, "htdocs%s", url); // htdocs/url/ htdocs/res.html if (path[strlen(path) - 1] == '/') // 最后一个字符是‘/’,默认访问该目录下的 index.html 页面 strcat(path, "index.html"); if (stat(path, &st) == -1) { // 获取文件详细信息失败 while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ // 读取剩下的请求头 numchars = get_line(client, buf, sizeof(buf)); not_found(client); // 404 } else { if ((st.st_mode & S_IFMT) == S_IFDIR) // 是一个目录,默认访问该目录下的 index.html 页面 strcat(path, "/index.html"); if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) // 这个资源有执行权限 包括 所有者 同组 其他人 cgi = 1; if (!cgi) serve_file(client, path); // 请求的是个页面,返回这页面 else execute_cgi(client, path, method, query_string); // cgi程序,可以执行这个程序,处理过程交给cgi程序 } close(client); // 关闭client socket }