Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4462881
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: 嵌入式

2011-03-25 09:06:13

6.解析和处理HTTP请求

     上面通过socket接口获得文件描述符conn_fd之后,我们将conn_fd传入到 handle_req函数中来处理HTTP请求。

  1. .....
  2. #define MAXLINE 150
  3. .....
  4. extern char **environ; /* defined by libc */

  5. void handle_req(int fd);
  6. int parse_uri(char *uri, char *filename, char *cgiargs);
  7. void serve_static(int fd, char *filename, int filesize);
  8. void get_filetype(char *filename, char *filetype);
  9. void exec_cgi(int fd, char *method, int content_length, char *filename, char *cgiargs);
  10. void error_msg(int fd, char *cause, char *errnum,
  11.          char *shortmsg, char *longmsg);


  12. ##############
  13. ### 处理HTTP请求/响应

  14. void handle_req(int fd)
  15. {
  16.     char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
  17.     char filename[MAXLINE], cgiargs[MAXLINE];

  18. ###################
  19. ### 转换文件描述符到文件指针
  20. ### FILE *fdopen(int fd,const char *mode)
  21.     FILE *f = fdopen(fd, "r");
  22.     if (!f) {
  23.         perror("Unable to open input fd");
  24.         close(fd);
  25.         return;
  26.     }
#####################
### 设置文件缓冲区
### void setbuf(FILE *stream,char *buf)
### 参数 stream 为流文件指针,buf为政府串数组的指针
### 该函数没有返回值
### 函数中参数如果为NULL,0,则默认该文件的读为无缓冲操作,此时每一次操作都是对该文件的操作。

  1.     setbuf(f, 0);

#####################
### 获取 HTTP命令行
### char *fgets(char *str,int num,FILE *stream)  从流文件中读出一行数据
### 通过fgets函数读取第一行,或者如果第一行很长的话,只读取MAXLINE-1大小的字符串


  1.     if (!fgets(buf, MAXLINE, f)) {
  2.         perror("Error reading buffer");
  3.         fclose(f);
  4.         return;
  5.     }
#####################
### int sscanf(const char *str,const char *foramt[...]) 格式化字符串取值
### 按照 format 格式解析
###将buf按照 %s,%s,%s,解析到 metnho ,uri,version,三者之间用空格分隔

  1.     sscanf(buf, "%s %s %s", method, uri, version);
  2. #ifdef DEBUG
  3.     printf("method: %s, uri: %s, version: %s \n", method, uri, version);
  4. #endif
#####################
### 通过strcasecmp 来检查 method 是否为 GET 或者 POST
### 这是 miniwebserver 支持的两种方法,如果是其他的方法,我们通过 error_msg 函数给客户端一个简单的错误信息
### 告知 miniwebserver 还不支持这个方法

  1.     if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) {
  2.         error_msg(fd, method, "501", "Not Implemented",
  3.                 "MiniWebServer does not support this method yet!");
  4.         return;
  5.     }
######################
### 继续读取问阿金指针f中的内容,按照HTTP协议规范,接下来是 0 行或者多行的请求报头
### 我们的miniwebserver 仅仅关心 “content-length:” 字符串之后所紧跟的数值,这是在使用 POST方法时的一个重要数值,后文酱油详细介绍

  1.     char buf_header[MAXLINE];
  2.     int content_length = 0;
  3.     while (fgets(buf_header, 150, f) && (strlen(buf_header) > 2)) {
  4.         if (strncasecmp(buf_header, "Content-length:", 15) == 0) {
  5.             content_length = atoi(buf_header + 15);
  6.         }
  7.     }
  8. #ifdef DEBUG
  9.     printf("content length: %d \n", content_length);
  10. #endif
  11.    
  12. #############################
  13. ### 接受完HTTP请求之后,我们便来检查所要求的具体内容
  14. ### parse_uri 得到HTTP请求的具体uri,文件名filename,以及CGI参数cgiargs
  15. ### if中,检查filename是否存在,没有的调用 error_msg函数通知客户端浏览器
  16.   
  17.     int is_cgi = parse_uri(uri, filename, cgiargs);
  18.     struct stat sbuf;
  19.     if (stat(filename, &sbuf) < 0) {
  20.         error_msg(fd, filename, "404", "Not found",
  21.          "Couldn't find this file");
  22.      return;
  23.     }

########################
### 分别对要求的静态网页和CGI程序进行处理,检查权限后分别转到相应的函数
  1.     if (is_cgi) { /* Serve CGI request */
  2.      if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {
  3.      error_msg(fd, filename, "403", "Forbidden",
  4.              "You have no permission to run the CGI program");
  5.      return;
  6.      }
  7.      exec_cgi(fd, method, content_length, filename, cgiargs);  #####
  8.     }
  9.     else { /* Serve static content */
  10.      if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
  11.      error_msg(fd, filename, "403", "Forbidden",
  12.              "You have no permission to read the file");
  13.      return;
  14.      }
  15.      serve_static(fd, filename, sbuf.st_size);                #####
  16.     }
  17. }



阅读(1320) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~