CGI通用网关接口

简介: 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_LENGTH STDIO中有效信息长度
CONTENT_TYPE 指示所传来的信息的MIME类型
CONTENT_FILE 使用Windows HTTPd/WinCGI标准时,用来传送数据的文件名
PATH_INFO 路径信息
PATH_TRANSLATED CGI程序的完整路径名
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/msword word文档
Application/octet-stream 一种通用二进制文件格式
Application/zip zip压缩文件
Application/pdf pdf文件
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
相关文章
|
1月前
|
DataWorks 安全 API
在DataWorks中创建的接口如果要使用API网关进行鉴权
【4月更文挑战第3天】在DataWorks中创建的接口如果要使用API网关进行鉴权
31 2
|
7月前
|
负载均衡 应用服务中间件 API
微服务技术系列教程(25) - SpringCloud- 接口网关服务Zuul
微服务技术系列教程(25) - SpringCloud- 接口网关服务Zuul
78 0
|
9月前
|
Java API Nacos
巧用网关白名单实现接口免鉴权
分享技术,用心生活 场景描述:一般系统中提供的接口都是经过统一配置鉴权的,比如不登录不能访问。但是,一些接口是需要开放给客户用的,我称作open API。那么这时候你不能要求客户先登录你的接口再去调用吧。那么,这时候就可以通过网关白名单来实现免鉴权
巧用网关白名单实现接口免鉴权
|
8月前
|
存储 安全 PHP
【100天精通Python】Day48:Python Web开发_WSGI网络服务器网关接口与使用
【100天精通Python】Day48:Python Web开发_WSGI网络服务器网关接口与使用
76 0
|
7月前
|
域名解析 监控 安全
接口开放太麻烦?试试阿里云API网关吧
我在[多方合作时,系统间的交互是怎么做的?](https://www.cnblogs.com/wlovet/p/17466812.html)这篇文章中写过一些多方合作时接口的调用规则和例子,然而,接口开放所涉及的安全、权限、监控、流量控制等问题,可不是简简单单就可以解决的,这一般需要专业的开放平台来支撑。但为了开放几个接口就要做一个开放平台,实在是不合算。为此阿里云为了解决这类需求推出了一款强大的工具——API网关。本文将介绍阿里云API网关的特点和优势,以及如何使用API网关来简化接口开放的过程。
251 0
接口开放太麻烦?试试阿里云API网关吧
|
1月前
|
网络虚拟化 网络架构
配置基于接口划分VLAN示例(汇聚层设备作为网关)
划分VLAN的方式有:基于接口、基于MAC地址、基于IP子网、基于协议、基于策略(MAC地址、IP地址、接口)。其中基于接口划分VLAN,是最简单,最常见的划分方式。 基于接口划分VLAN指的是根据交换机的接口来划分VLAN。网络管理员预先给交换机的每个接口配置不同的PVID,当一个数据帧进入交换机时,如果没有带VLAN标签,该数据帧就会被打上接口指定PVID的Tag,然后数据帧将在指定PVID中传输。 在典型的分层组网中,当接入交换机是二层交换机时,可以使用汇聚交换机作为用户的网关。另外使用汇聚交换机作为用户的网关还可以简化接入交换机的配置,使用户通过一个出接口访问外部网络,便于维护和管
|
11月前
|
JavaScript 安全 小程序
Spring Cloud实战 | 第十一篇:Spring Cloud Gateway网关实现对RESTful接口权限和按钮权限细粒度控制
Spring Cloud实战 | 第十一篇:Spring Cloud Gateway网关实现对RESTful接口权限和按钮权限细粒度控制
Spring Cloud实战 | 第十一篇:Spring Cloud Gateway网关实现对RESTful接口权限和按钮权限细粒度控制
|
存储 SpringCloudAlibaba API
SpringCloud Alibaba二十五 | 网关Restful接口拦截
SpringCloud Alibaba二十五 | 网关Restful接口拦截
196 0
|
canal 监控 安全
谷粒学院——Day17【数据同步工具、SpringCloud【GateWay网关】、权限管理功能(接口)】
谷粒学院——Day17【数据同步工具、SpringCloud【GateWay网关】、权限管理功能(接口)】
284 0
谷粒学院——Day17【数据同步工具、SpringCloud【GateWay网关】、权限管理功能(接口)】
|
消息中间件 移动开发 负载均衡