CGI通用网关接口

CGI通用网关接口

Common Gatway Interface

原理
简介

CGI 是 Web服务器和程序动态生成数据之间的通用接口

在这里插入图片描述

服务器和CGI程序之间是通过标准输入输出来进行数据传递的,需要环境变量的协作才可以实现

基本流程:

  1. 通过浏览器将用户请求送到服务器
  2. 服务器接收用户请求并交给CGI程序处理
  3. CGI程序把处理结果传送给服务器
  4. 服务器把结果送回到浏览器

对于Windows系统而言,还可以通过profile文件进行数据传输(如ini文件)

每个CGI程序只能处理一个用户请求,在激活一个CGI程序进程时也创建了属于该进程的环境变量。

环境变量

对于CGI程序来说,它继承了系统的环境变量, CGI环境变量在CGI程序启动时初始化,在结束时销毁。

当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了关于HTTP服务器、客户端、CGI传输过程等相关内容。

与请求相关的环境变量

名称说明
REQUEST_METHOD服务器与CGI程序之间的信息传输方式
QUERY_STRING采用GET时所传输的信息
CONTENT_LENGTHSTDIO中有效信息长度
CONTENT_TYPE指示所传来的信息的MIME类型
CONTENT_FILE使用Windows HTTPd/WinCGI标准时,用来传送数据的文件名
PATH_INFO路径信息
PATH_TRANSLATEDCGI程序的完整路径名
SCRIPT_NAME所调用的CGI程序的名字

与服务器相关的环境变量

名称说明
GATEWAY_INTERFACE服务器所实现的CGI版本
SERVER_NAME服务器的IP或名字
SERVER_PORT主机的端口号
SERVER_SOFTWARE调用的CGI程序名称和版本号

与客户端相关的环境变量

名称说明
REMOTE_ADDR客户机的IP地址
REMOTE_HOST客户机的主机名
ACCEPT能接收的应答方式
ACCEPT_ENCODING支持的编码方式
ACCEPT_LANGUAGE可接受的语言
AUTORIZATION认证方式
FORM客户机地址
IF_MODIFIED_SINGCE当用get方式请求并且只有当文档比指定的日期更早时才返回数据
PRAGMA设定将来要用到的服务器代理
REFFERER链接到当前文档的文档的URL
USER_AGENT客户端浏览器的信息
  • CGI传送给Web服务器的信息可以用各种格式,通常是以HTML文本或者XML文本的形式

    1. 传输HTML,文本第一行输出的内容必须是"content-type:text/html\n\n"
    2. 传输XML,文本第一行输出的内容必须是"content-type:text/xml\n\n"
    3. 其他的一些格式:JIF(image/gif)JPEG(image/jpeg)AVI(video/avi)
    

两个重要环境变量

  • QUERY_STRING:在浏览器端以GET的方法输入的数据,数据的内容就是url问号后的内容

    char *data = getenv("QUERY_STRING");
    
  • CONTENT_LENGTH:在浏览器端以POST方法输入的数据的字节数,数据的内容通过标准输入获取

    //1. 数据的长度
    char *len = getenv("CONTENT_LENGTH");
    //2、根据长度 从标准输入设备 获取内容
    char data[128]="";
    fgets(data, atoi(len)+1, stdin);
    
POST方法

客户端来的用户数据将存放在CGI进程的标准输入中,同时将用户数据的长度赋予环境变量中的CONTENT_LENGTH

GET方法

客户端来的用户数据存放到到环境变量QUERY_STRING

CGI程序的执行流程:

  • 查询与该CGI程序进程相应的环境变量:

    REQUEST_METHOD,如果是POST,就从环境变量中获取数据的长度len,然后到该进程相应的标准输入取出len长的数据。

    如果是GET,则用户数据就在环境变量的QUERY_STRING中

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int get_inputs(){ 
	int length;
 	char *method;
 	char *inputstring;
	method = getenv("REQUEST_METHOD"); //将返回结果赋予指针
	if(method == NULL)	return 1;       //找不到环境变量REQUEST_METHOD
 	if(!strcmp(method, "POST")) {  // POST方法
 		length = atoi(getenv("CONTENT_LENGTH")); //结果是字符,需要转换
 		if(length != 0)	{
        	inputstring = malloc(sizeof(char)*length + 1) //必须申请缓存,因为stdin是不带缓存的。
        	fread(inputstring, sizeof(char), length, stdin); //从标准输入读取一定数据
 		}
    }else if(!strcmp(method, "GET")){
 		Inputstring = getenv("QUERY_STRING");   
 		length = strlen(inputstring);
    }
}

先判断“REQUEST_METHOD”是否存在,程序会更健壮,否则在某些情况下可能会造成程序崩溃。

假若CGI程序不是由服务器调用的,环境变量集里就没有与CGI相关的环境变量(如REQUEST_METHOD,REMOTE_ADDR等)添加进来

CGI数据输出

在CGI程序中的标准输出stdout是经过重定义了的,没有在服务器上产生任何的输出内容,而是被重定向到客户浏览器

可以用打印来实现客户端新的HTML页面的生成。

CGI标题

CGI的格式输出内容必须组织成标题/内容的形式,CGI标准规定了CGI程序可以使用的三个HTTP标题。

标题必须占据第一行输出,而且必须随后带有一个空行

标题描述
Content-Type设定随后输出数据的MIME类型
Location设定输出为另外一个文档
Status指定HTTP状态码
Content-Type

向标准输出发送网页内容要遵循MIME格式

任意输出前面必须要有一个用于定义MIME类型的输出内容,随后必须跟一个空行。

printf("Content-Type:text/html\n\n");
printf("Welcome\n");

MIME类型以类型/子类型(type/subtype)的形式表示。

  • 其中type表示一下几种典型文件格式的一种:

​ text、audio、video、image、application、mutipart、message

  • Subtype则用来描述具体所用的数据格式。

    类型说明
    Application/mswordword文档
    Application/octet-stream一种通用二进制文件格式
    Application/zipzip压缩文件
    Application/pdfpdf文件
Location

使用location ,一个CGI可以使用当前用户转而访问同一服务器上的另外一个程序,甚至可以访问一个url

使用Location的格式为:Location:Filename/URL

printf("Location:/test.html\n\n");
//这与直接链接到test.html的效果是一样的。
printf("Location:http:*//www.baidu.com/\n\n");
//由于该URL并不指向当前服务器,用户浏览器并不会直接链接到指定的URL,而是给用户输出提示信息。
Demo

GET方式:计算a + b的值

url: http://ip:port/add?a=nn&b=nn

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
    char * method = NULL;
    char *query_string = NULL;
    printf("Content-Type:text/html\r\n\r\n");

    method = getenv("REQUEST_METHOD");
    if(method == NULL){
        printf("<html> <p> UNKNOWN METHOD</p></html>");
        return;
    }
    if(strcasecmp(method,"POST") == 0){
        printf("<html> <p> UNSUPPORTED METHOD</p></html>");
        return 0;
    }
    query_string = getenv("QUERY_STRING");
    if(query_string == NULL){
        printf("<html> <p> PARAMETER ERROR </p></html>");
        return 0;
    } 
    int a = 0;
    int b = 0;
    int i = 0;
    char * start = query_string+2;
    char * end = NULL;
    // format: a=xxx&b=xxx
    for(i = 0;i<strlen(query_string);i++){
        if(*(query_string+i) == '&'){
            end = query_string+i;
            break;
        }
    }
    *end = '\0';
    a = atoi(start);
    start = end +3;
    b = atoi(start);
    printf("<html> <p> %d + %d = %d  </p></html>",a,b,a+b);
    return 0;
}

显示效果如下:

在这里插入图片描述

参考
  1. http://t.csdn.cn/44wV4

  2. http://t.csdn.cn/tkgPJ

  3. http://t.csdn.cn/JqlKj

  4. http://t.csdn.cn/afcOz

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴风雨中的白杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值