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

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: 嵌入式

2011-03-25 16:53:27

10.处理POST方法的 CGI 请求

    在WEB环境中,浏览器与服务器之间的数据交互,很多是通过 HTML 中form 表单完成的。form提供了两种数据传输的方式---GET 和POST。虽然他们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的影响。二者主要的区别如下:

    1.GET是用来从服务器上获得数据,而POST是用来向服务器上传递数据。
    2.GET将表单的数据按照variable=value的形式,添加到action所指向的 URL后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;POST是将表单中的数据放在form的数据体中,按照变量和值相应的方式,传递到action所指向的URL。
    3.GET是不安全的。因为自傲传输过程,数据会被放在请求的URL中,而如今现有的很多服务器、代理服务器或者用户代理都会请求URL记录到日志文件中,然后放在某个地方,这样就可能有一些隐私被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部信息将会一同显示在用户面前。POST的所有操作对用户来都是不可见得。
    4.GET传输的数据量小,这主要是因为受URL长度限制;而POST可以传输大量的数据,所以在上次文件只能使用POST.
    5.GET限制Form表单的数据集的必须为ASCII字符;POST支持整个ISO10646字符集。
    6.GET是 form的默认方法。

   我们利用上面提到的 post.html 文件来比较它与 get.html 产生的结果的不同之处。
post.html
  1. <html>
  2. <head><title>test of "POST"</title></head>
  3. <body>
  4. <h1>Test POST Form</h1>
  5. <form method="POST" action="/cgi-bin/test_post">
  6. <h2>Input your test strings:</h2>
  7. ID:<input type=text name=id><br>
  8. Name:<input type=text name=name><br>
  9. <input type=submit value="Test the Form">
  10. </form>
  11. </body>
  12. </html>


   为了便于对比 post.html 与 get.html 几乎一摸一样,主要不同之处在粗体字部分,我们把method设为了“POST”。同样我们在 ID和Name栏中分别输入“111”和“scrum”,此时浏览器发送给服务器的HTTP请求行中,uri对应的数据不再是“/cgi-bin/test_get?id=111&name=scrum”,而是变成了“/cgi-bin/test-post”,如上面所述,参数的内容不再是通过HTTP请求行来传递,而是通过表单的数据内容来传递。

    根据 CGI的规范,对于POST方法,我们在WEB服务器中需要根据表单所提交的数据的长度content_length,将其重定向为CGI程序的标准输入 stdin,这样CGI程序就可以通过stdin来得到客户端所提交的数据。
 
    我们通过UNIX的管道机制 PIPE 来实现这种重定向的要求。对POST方法的具体逻辑处理如下:
  

  1. void exec_cgi(int fd, char *method, int content_length, char *filename, char *cgiargs)
  2. {
  3. char buf[MAXLINE], *emptylist[] = { NULL };

  4. /* Return first part of HTTP response */
  5. sprintf(buf, "HTTP/1.1 200 OK\r\n");
  6. write(fd, buf, strlen(buf));
  7. sprintf(buf, "Server: Mini Web Server\r\n");
  8. write(fd, buf, strlen(buf));

  9. if (fork() == 0) { /* child */
  10. /*handle POST method*/
  11. if (strcasecmp(method, "POST") == 0) {
  12. int pfd[2];
  13. int rc = pipe(pfd);
  14. if (rc < 0) {
  15. perror("pipe in POST failed");
  16. exit(1);
  17. }
  18. int post_pid = fork();
  19. if (post_pid == 0) {
  20. close(pfd[0]);
  21. int n = 0, bytes_read = 0;
  22. /*only read length of "content_length"*/
  23. while (n < content_length) {
  24. bytes_read = read(fd, buf, sizeof(buf)-1);
  25. printf("content read: %s \n", buf);
  26. if (bytes_read > 0) {
  27. write(pfd[1], buf, bytes_read);
  28. n += bytes_read;
  29. }
  30. }
  31. exit(0);
  32. }

  33. close(pfd[1]);
  34. /*redirect to STDIN*/
  35. dup2(pfd[0],STDIN_FILENO);
  36. }

  37. /* set CGI vars, only support "QUERY_STRING" and "CONTENT_LENGTH" */
  38. setenv("QUERY_STRING", cgiargs, 1);
  39. sprintf(buf, "%d", content_length);
  40. setenv("CONTENT_LENGTH", buf);
  41. dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */
  42. execve(filename, emptylist, environ); /* Run CGI program */
  43. }
  44. wait(NULL); /* Parent waits for and reaps child */
  45. }





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