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