CGI接口介绍
1.CGI定義:
CGI(CommonGateway Interface)是HTTP服務(wù)器與你的或其它機(jī)器上的程序進(jìn)行“交談”的一種工具,其程序須運(yùn)行在網(wǎng)絡(luò)服務(wù)器上。CGI程序在服務(wù)器端執(zhí)行,并可以和Web服務(wù)器在同一主機(jī)上。常用的CGI語言有Perl、shell、Python,在windows上也可以用C、C++或Java等進(jìn)行編寫。
2.CGI功能:
絕大多數(shù)的CGI程序被用來解釋處理來自表單的輸入信息,并在服務(wù)器產(chǎn)生相應(yīng)的處理,或?qū)⑾鄳?yīng)的信息反饋給瀏覽器。CGI程序使網(wǎng)頁具有交互功能。
3.CGI運(yùn)行環(huán)境:
CGI程序在UNIX操作系統(tǒng)上CERN或NCSA格式的服務(wù)器上運(yùn)行。 在其它操作系統(tǒng)(如:windows NT及windows95等)的服務(wù)器上 也廣泛地使用CGI程序,同時(shí)它也適用于各種類型機(jī)器。
4.CGI處理步驟:
⑴通過Internet把用戶請(qǐng)求送到服務(wù)器。
⑵服務(wù)器接收用戶請(qǐng)求并交給CGI程序處理。
⑶CGI程序把處理結(jié)果傳送給服務(wù)器。
⑷服務(wù)器把結(jié)果送回到用戶。
5.CGI服務(wù)器配置:
在許多服務(wù)器cgi-bin是僅能夠放置CGI腳本的目錄。
在Windows平臺(tái)上將C或C++寫好的程序的Debug或Release版本的.exe程序拷貝到cgi-bin的目錄下(如上圖所示),將.exe改為.cgi也可同樣運(yùn)行,如下2個(gè)圖。
cgi-bin目錄是存放CGI腳本的地方。這些腳本使WWW服務(wù)器和瀏覽器能運(yùn)行外部程序,而無需啟動(dòng)另一個(gè)程序。它是運(yùn)行在Web服務(wù)器上的一個(gè)程序,并由來自于瀏覽者的輸入觸發(fā)。
CGI程序不是放在服務(wù)器上就能順利運(yùn)行,如果要想使其在服務(wù)器上順利的運(yùn)行并準(zhǔn)確的處理用戶的請(qǐng)求,則須對(duì)所使用的服務(wù)器進(jìn)行必要的設(shè)置。
配置:根據(jù)所使用的服務(wù)器類型以及它的設(shè)置把CGI程序放在某一特定的目錄中或使其帶有特定的擴(kuò)展名。
CGI腳本是怎樣工作的?
CGI腳本由服務(wù)器調(diào)用, 基于瀏覽器的數(shù)據(jù)輸入. 其工作原理如下:
1. 一個(gè)URL指向一個(gè)CGI腳本. 一個(gè)CGI腳本的URL能如普通的URL一樣出現(xiàn),區(qū)別于.htm/.html靜態(tài)URL,CGI的URL是動(dòng)態(tài)URL。如http://xxxx.com/cgiurl
2. 服務(wù)器CGI接收瀏覽器的請(qǐng)求, 按照那個(gè)URL指向?qū)?yīng)的腳本文件(注意文件的位置和擴(kuò)展名),執(zhí)行CGI腳本.
3. CGI腳本執(zhí)行基于輸入數(shù)據(jù)的操作,包括查詢數(shù)據(jù)庫、計(jì)算數(shù)值或調(diào)用系統(tǒng)中其他程序.
4. CGI腳本產(chǎn)生某種Web服務(wù)器能理解的輸出結(jié)果.
5. 服務(wù)器接收來自腳本的輸出并且把它傳回瀏覽器,讓用戶了解處理結(jié)果。
CGI的輸入/輸出方法:CGI程序通過標(biāo)準(zhǔn)輸入(STDIN)和標(biāo)準(zhǔn)輸出(STDOUT)來進(jìn)行輸入輸出,STDIN和STDOUT是兩個(gè)預(yù)先定義好的文件指針。你可以利用文件讀寫函數(shù)來對(duì)其進(jìn)行操縱。
此外CGI程序還通過環(huán)境變量來得到輸入,只不過環(huán)境變量中提供的是一些常用的信息,并且通常不包括用戶在WEB頁面中輸入的信息(除使用下面講的GET方法時(shí),通過檢查環(huán)境變量QUERY_STRING來得到輸入數(shù)據(jù)),而STDIN通常用來傳遞用戶輸入的信息。
在輸入時(shí)所使用的POST/GET方法:在WEB頁面向CGI發(fā)送數(shù)據(jù)時(shí)通常采用兩種方法:GET/POST,GET方法將數(shù)據(jù)附加在URL后發(fā)送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通過檢查環(huán)境變量QUERY_STRING來得到輸入數(shù)據(jù)。
GET和POST方法的區(qū)別
GET方法,它將數(shù)據(jù)打包放置在環(huán)境變量QUERY_STRING中作為URL整體的一部分傳遞給服務(wù)器。而他的限制是:1) 參數(shù)的內(nèi)容作為URL信息,用戶可以看到;2) 有大小的限制。
POST方法,通過環(huán)境變量和標(biāo)準(zhǔn)輸入傳遞數(shù)據(jù)給CGI程序,因此POST方法可較方便地傳遞較多的數(shù)據(jù)給CGI程序。
CGI接口標(biāo)準(zhǔn)包括標(biāo)準(zhǔn)輸入、環(huán)境變量、標(biāo)準(zhǔn)輸出三部分。
標(biāo)準(zhǔn)輸入
CGI程序像其他可執(zhí)行程序一樣,可通過標(biāo)準(zhǔn)輸入(stdin)從Web服務(wù)器得到輸入信息,如Form中的數(shù)據(jù),這就是所謂的向CGI程序傳遞數(shù)據(jù)的POST方法。這意味著在操作系統(tǒng)命令行狀態(tài)可執(zhí)行CGI程序,對(duì)CGI程序進(jìn)行調(diào)試。POST方法是常用的方法。
環(huán)境變量
操作系統(tǒng)提供了許多環(huán)境變量,它們定義了程序的執(zhí)行環(huán)境,應(yīng)用程序可以存取它們。Web服務(wù)器和CGI接口又另外設(shè)置了自己的一些環(huán)境變量,用來向CGI程序傳遞一些重要的參數(shù)。CGI的GET方法還通過環(huán)境變量QUERY-STRING向CGI程序傳遞Form中的數(shù)據(jù)。
標(biāo)準(zhǔn)輸出
CGI程序通過標(biāo)準(zhǔn)輸出(stdout)將輸出信息傳送給Web服務(wù)器。傳送給Web服務(wù)器的信息可以用各種格式,通常是以純文本或者HTML文本的形式,這樣我們就可以在命令行狀態(tài)調(diào)試CGI程序,并且得到它們的輸出。
環(huán)境變量
環(huán)境變量是文本串(名字/值對(duì)),可以被OSShell或其他程序設(shè)置 ,也可以被其他程序訪問。它們是Web服務(wù)器傳遞數(shù)據(jù)給CGI程序的簡單手段,之所以稱為環(huán)境變量是因?yàn)樗鼈兪侨肿兞?任何程序都可以存取它們。下面是CGI程序設(shè)計(jì)中常常要用到的一些環(huán)境變量。
對(duì)于CGI程序來說,它繼承了系統(tǒng)的環(huán)境變量。CGI環(huán)境變量在CGI程序啟動(dòng)時(shí)初始化,在結(jié)束時(shí)銷毀。
當(dāng)一個(gè)CGI程序不是被HTTP服務(wù)器調(diào)用時(shí),它的環(huán)境變量幾乎是系統(tǒng)環(huán)境變量的復(fù)制。
當(dāng)這個(gè)CGI程序被HTTP服務(wù)器調(diào)用時(shí),它的環(huán)境變量就會(huì)多了以下關(guān)于HTTP服務(wù)器、客戶端、CGI傳輸過程等項(xiàng)目。
環(huán)境變量是一個(gè)保存用戶信息的內(nèi)存區(qū)。當(dāng)客戶端的用戶通過瀏覽器發(fā)出CGI請(qǐng)求時(shí),服務(wù)器就尋找本地的相應(yīng)CGI程序并執(zhí)行它。在執(zhí)行CGI程序的同時(shí),服務(wù)器把該用戶的信息保存到環(huán)境變量里。接下來,CGI程序的執(zhí)行流程是這樣的:查詢與該CGI程序進(jìn)程相應(yīng)的環(huán)境變量:第一步是request_method,如果是POST,就從環(huán)境變量的len,然后到該進(jìn)程相應(yīng)的標(biāo)準(zhǔn)輸入取出len長的數(shù)據(jù)。如果是GET,則用戶數(shù)據(jù)就在環(huán)境變量的QUERY_STRING里。
環(huán)境變量 意義
SERVER_NAME
CGI腳本運(yùn)行時(shí)的主機(jī)名和IP地址
SERVER_SOFTWARE
你的服務(wù)器的類型如: CERN/3.0 或 NCSA/1.3.
GATEWAY_INTERFACE
運(yùn)行的CGI版本. 對(duì)于UNIX服務(wù)器, 這是CGI/1.1.
SERVER_PROTOCOL
服務(wù)器運(yùn)行的HTTP協(xié)議. 這里當(dāng)是HTTP/1.0.
SERVER_PORT
服務(wù)器運(yùn)行的TCP口,通常Web服務(wù)器是80.
REQUEST_METHOD
POST 或 GET, 取決于你的表單是怎樣遞交的.
HTTP_ACCEPT
瀏覽器能直接接收的Content-types, 可以有HTTP Accept header定義.
HTTP_USER_AGENT
遞交表單的瀏覽器的名稱、版本 和其他平臺(tái)性的附加信息。
HTTP_REFERER
遞交表單的文本的 URL,不是所有的瀏覽器都發(fā)出這個(gè)信息,不要依賴它
PATH_INFO
附加的路徑信息, 由瀏覽器通過GET方法發(fā)出.
PATH_TRANSLATED
在PATH_INFO中系統(tǒng)規(guī)定的路徑信息.
SCRIPT_NAME
指向這個(gè)CGI腳本的路徑, 是在URL中顯示的(如, /cgi-bin/thescript).
QUERY_STRING
腳本參數(shù)或者表單輸入項(xiàng)(如果是用GET遞交). QUERY_STRING包含URL中問號(hào)后面的參數(shù).
REMOTE_HOST
遞交腳本的主機(jī)名,這個(gè)值不能被設(shè)置.
REMOTE_ADDR
遞交腳本的主機(jī)IP地址.
REMOTE_USER
遞交腳本的用戶名. 如果服務(wù)器的authentication被激活,這個(gè)值可以設(shè)置。
REMOTE_IDENT
如果Web服務(wù)器是在ident (一種確認(rèn)用戶連接你的協(xié)議)運(yùn)行, 遞交表單的系統(tǒng)也在運(yùn)行ident, 這個(gè)變量就含有ident返回值.
CONTENT_TYPE
如果表單是用POST遞交, 這個(gè)值將是 application/x-www-form-urlencoded. 在上載文件的表單中, content-type 是個(gè) multipart/form-data.
CONTENT_LENGTH
對(duì)于用POST遞交的表單,標(biāo)準(zhǔn)輸入口的字節(jié)數(shù).
說明: 1. CONTENT_TYPE:如application/x-www-form-urlencoded,表示數(shù)據(jù)來自HTML表單,并且經(jīng)過了URL編碼
2. REQUEST_METHOD:它的值一般包括兩種:POST和GET,但我們寫CGI程序時(shí),最后還要考慮其他的情況。
如果采用POST方法,那么客戶端來的用戶數(shù)據(jù)將存放在CGI進(jìn)程的標(biāo)準(zhǔn)輸入中,同時(shí)將用戶數(shù)據(jù)的長度賦予環(huán)境變量中的CONTENT_LENGTH。客戶端用POST方式發(fā)送數(shù)據(jù)有一個(gè)相應(yīng)的MIME類型(通用Internet郵件擴(kuò)充服務(wù):Multi-purpose Internet Mail Extensions)。目前,MIME類型一般是:application/x-wwww-form-urlencoded,該類型表示數(shù)據(jù)來自HTML表單。該類型記錄在環(huán)境變量CONTENT_TYPE中,CGI程序應(yīng)該檢查該變量的值。
如果采用GET方法,CGI程序無法直接從服務(wù)器的標(biāo)準(zhǔn)輸入中獲取數(shù)據(jù),因?yàn)榉?wù)器把它從標(biāo)準(zhǔn)輸入接收到得數(shù)據(jù)編碼到環(huán)境變量QUERY_STRING(或PATH_INFO)。
GET與POST的區(qū)別:采用GET方法提交HTML表單數(shù)據(jù)的時(shí)候,客戶機(jī)將把這些數(shù)據(jù)附加到由ACTION標(biāo)記命名的URL的末尾,用一個(gè)包括把經(jīng)過URL編碼后的信息與CGI程序的名字分開:http://www.mycorp.com/hello.html?name=hgq$id=1,QUERY_STRING的值為name=hgq&id=1
從服務(wù)器獲取數(shù)據(jù)的例子(C語言實(shí)現(xiàn)代碼):
#include <stdio.h> #include <stdlib.h> #include <string.h>int get_inputs() { int length; char *method; char *inputstring;method = getenv(“REQUEST_METHOD”); //將返回結(jié)果賦予指針 if(method == NULL)return 1; //找不到環(huán)境變量REQUEST_METHOD if(!strcmp(method, ”POST”)) // POST方法 {length = atoi(getenv(“CONTENT_LENGTH”)); //結(jié)果是字符,需要轉(zhuǎn)換if(length != 0){inputstring = malloc(sizeof(char)*length + 1) //必須申請(qǐng)緩存,因?yàn)閟tdin是不帶緩存的。fread(inputstring, sizeof(char), length, stdin); //從標(biāo)準(zhǔn)輸入讀取一定數(shù)據(jù) } } else if(!strcmp(method, “GET”)) {Inputstring = getenv(“QUERY_STRING”); length = strlen(inputstring); } if(length == 0) return 0; }獲取環(huán)境變量的時(shí)候,如果先判斷“REQUEST_METHOD”是否存在,程序會(huì)更健壯,否則在某些情況下可能會(huì)造成程序崩潰。因?yàn)榧偃鬋GI程序不是由服務(wù)器調(diào)用的,那么環(huán)境變量集里就沒有與CGI相關(guān)的環(huán)境變量(如REQUEST_METHOD,REMOTE_ADDR等)添加進(jìn)來,也就是說“getenv(“REQUEST_METHOD”)”將返回NULL!
CGI數(shù)據(jù)輸出
CGI程序如何將信息處理結(jié)果返回給客戶端?這實(shí)際上是CGI格式化輸出。
這個(gè) “腳本輸出” 意思是指你的腳本發(fā)回服務(wù)器的數(shù)據(jù). 在UNIX系統(tǒng)中, 輸出是發(fā)向標(biāo)準(zhǔn)輸出, 服務(wù)器從那兒檢測(cè)它. 在其他系統(tǒng)和服務(wù)器, 你的腳本輸出也許不一樣了.
在CGI程序中的標(biāo)準(zhǔn)輸出stdout是經(jīng)過重定義了的,它并沒有在服務(wù)器上產(chǎn)生任何的輸出內(nèi)容,而是被重定向到客戶瀏覽器,這與它是由C,還是Perl或Python實(shí)現(xiàn)無關(guān)。
所以,我們可以用打印來實(shí)現(xiàn)客戶端新的HTML頁面的生成。比如,C的printf是向該進(jìn)程的標(biāo)準(zhǔn)輸出發(fā)送數(shù)據(jù),Perl和Python用print向該進(jìn)程的標(biāo)準(zhǔn)輸出發(fā)送數(shù)據(jù)。
輸出頭部信息,頭部是實(shí)際不是文本的一部分,是服務(wù)器與瀏覽器之間的信息協(xié)議,你實(shí)際看不到。 在CGI程序輸出時(shí)必須先輸出一個(gè)CGI標(biāo)題,標(biāo)題共有以下三類: Content-type, Location, 和Status. Content-type 是最普遍的。
Location: 標(biāo)題,指明輸出另一個(gè)文檔的URL,例如 fprintf(stdout,”Location:http://www.vchelp.net/\n\n”);
Content-Type: 標(biāo)題,指明發(fā)送的數(shù)據(jù)的MIME類型,例如 fprintf(stdout,”Content-Type:text/html\n\n”);
Status: 標(biāo)題,指明HTTP狀態(tài)碼,例如 fprintf(stdout,”Status:200\n\n”);
有關(guān)content-type解釋可以見有關(guān)HTML的說明, 發(fā)出text/html特定編碼如下:
Content-type, Location, 和Status.后面都要跟一個(gè)空行
例如:#!/bin/sh
echo “Content-type: text/html”
echo #空行
echo “”
URL編碼
不管是POST還是GET方式,客戶端瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù)都不是原始的用戶數(shù)據(jù),而是經(jīng)過URL編碼的。此時(shí),CGI的環(huán)境變量Content_type將被設(shè)置,如Content_type = application/x-www-form-urlencode就表示服務(wù)器收到的是經(jīng)過URL編碼的包含有HTML表單變量數(shù)據(jù)。
編碼的基本規(guī)則是:
變量之間用“&”分開;
變量與其對(duì)應(yīng)值用“=”連接;
空格用“+”代替;
保留的控制字符則用“%”連接對(duì)應(yīng)的16進(jìn)制ASCII碼代替;
某些具有特殊意義的字符也用“%”接對(duì)應(yīng)的16進(jìn)制ASCII碼代替;
空格是非法字符;
任意不可打印的ASCII控制字符均為非法字符。
所以,CGI程序從標(biāo)準(zhǔn)輸入或環(huán)境變量中獲取客戶端數(shù)據(jù)后,還需要進(jìn)行解碼。解碼的過程就是URL編碼的逆變:根據(jù)“&”和“=”分離HTML表單變量,以及特殊字符的替換。
總結(jié)
- 上一篇: Kubernetes v1.19版本来了
- 下一篇: STM8S系列基于IAR开发单通道ADC