C G I (Common Gateway Interface) 제 1장 Introduction to the CGI 제 2장 Input to the CGI 제 3장 Output from the CGI 제 4장 Form and the CGI 제 5장 SSI(Server Side Include)
학습 목표 CGI의 개념을 이해한다. 관련된 환경 변수와 그 사용법을 이해한다. CGI에 자료 전달 방식(GET과 POST)과 encoding하는 규칙을 이해한다. CGI에 전달된 자료를 decoding하는 방법을 이해한다. CGI 프로그램에서 html 형식의 자료를 출력하는 방법을 이해한다. Form tag의 사용법을 익힌다. C언어로 CGI 프로그램을 구현하는 방법을 배우고 프로그래밍한다. CGI 프로그램 언어 C/C++, Java, Fortran, PERL, TCL, Any Unix shell, Visual Basic AppleScript If you have a version of the NCSA HTTPd server distribution, you will see a directory called /cgi-bin. This is the special directory mentioned above where all of your CGI programs currently reside. CGI의 Major Applications Form User로부터 정보를 입력 받는데 사용될 수 있다. Back-and-forth Interaction Gateway Client가 직접 읽을 수 없는 정보(예, DBMS의 Data)를 획득하고 처리하여 Client에게 제공하는 프로그램. Virtual Documents CGI의 Heart라고 칭해진다. User의 정보요청에 따라 실시간으로 정보를 제공한다. 정적으로 저장되어 있는 File이 아니라, 데이타의 Stream을 넘겨준다.
제 1장 Introduction to the CGI CGI(Common Gateway Interface)의 정의 웹의 하이퍼미디어 시스템과 외부 응용 프로그램이 서로 연계되기 위한 인코딩, 디코딩 방법과 데이터 교환 방법을 표준화 CGI 프로그램은 client의 요청에 따라 Web Server( HTTP Server)를 통하여 실행되며 C/C++, Java, Perl, Unix Shell 등으로 작성 가능 Submit (Form) Call CGI Program CGI 프로그램 언어 C/C++, Java, Fortran, PERL, TCL, Any Unix shell, Visual Basic AppleScript If you have a version of the NCSA HTTPd server distribution, you will see a directory called /cgi-bin. This is the special directory mentioned above where all of your CGI programs currently reside. CGI의 Major Applications Form User로부터 정보를 입력 받는데 사용될 수 있다. Back-and-forth Interaction Gateway Client가 직접 읽을 수 없는 정보(예, DBMS의 Data)를 획득하고 처리하여 Client에게 제공하는 프로그램. Virtual Documents CGI의 Heart라고 칭해진다. User의 정보요청에 따라 실시간으로 정보를 제공한다. 정적으로 저장되어 있는 File이 아니라, 데이타의 Stream을 넘겨준다. Form Client (Web Browser) CGI Program’s Response CGI Program’s Response Server Application (CGI)
CGI 작동 순서 1 6 Web Browser (Netscape,Explorer) Web Server (HTTPD) 2 5 3 Program DBMS 4
CGI 응용 예 Search engine Imagemap Guest book Order form 정보검색을 위한 Query 처리 Imagemap Guest book Order form On-line 주문 Clock, counter, web statistics Bi-lingual dictionary 한-영, 영-한, 일-영, 영-일 사전 등 Intranet application CGI 실행을 위해서는 Server Configuration Parameter의 조정이 필요하다. NCSA HTTP Server의 경우 httpd.conf ServerRoot /usr/local/etc/httpd srm.conf ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/ ScriptAlias /my-cgi-bin/ /usr/local/etc/httpd/my-cgi-bin/ AddType application/x-httpd-cgi .pl .sh .cgi CERN HTTP Server의 경우 Exec /cgi-bin/ /usr/local/etc/httpd/cgi-bin Guest book (방명록) Intranet : Any network which provides similar services within an organisation to those provided by the Internet outside it but which is not necessarily connected to the Internet. The commonest example is the use by a company of one or more World-Wide Web servers on an internal TCP/IP network for distribution of information within the company. Since about 1995, intranets have become a major growth area in corporate computing due to the availability of cheap or free commercial browser and web server software which allows them to provide a simple, uniform hypertext interface to many kinds of information and application programs. Some companies give limited access to their intranets to other companies or the general public. This is known as an "extranet". Extranet : <World-Wide Web> The extension of a company's intranet out onto the Internet, e.g. to allow selected customers, suppliers and mobile workers to access the company's private data and applications via the World-Wide Web. This is in contrast to, and usually in addition to, the company's public web site which is accessible to everyone. The difference can be somewhat blurred but generally an extranet implies real-time access through a firewall of some kind. Such facilities require very careful attention to security but are becoming an increasingly important means of delivering services and communicating efficiently.
제 2장 Input to the CGI CGI 프로그램이 얻을 수 있는 데이터의 종류 1) Server와 user에 관한 정보 웹 서버에서 설정하는 환경변수(environment variable)를 참조하여 얻을 수 있다. 2) User가 입력한 form data GET 방법 : URL 뒤에 추가된 자료로 전달된다. POST 방법 : 표준입력 데이터 stream(stdin)으로 전달된다. 3) Path name 정보 환경변수를 참조하여 얻을 수 있다. 환경 변수 : 운영체제에서 child process에게 정보를 전달하는 데 사용하는 특별한 이름을 가진 메모리 영역 CGI에서 사용하는 환경변수는 일부는 CGI 표준 변수이고 나머지는 검색기, 서버, 사이트 등 여러가지 이유로 인해 설정된 변수들이다. - 예제로 배우는 CGI p.22
서버에 관한 환경변수 SERVER_NAME SERVER_PORT SERVER_SOFTWARE SERVER_PROTOCOL Server의 Host Name(sungkyul.edu) SERVER_PORT HTTP 요청을 받은 서버의 port 번호 (표준 HTTP port 번호 : 80) SERVER_SOFTWARE Server Software의 이름과 버전 정보(Apache/0.6.4b) SERVER_PROTOCOL 서버의 프로토콜의 이름과 버전(HTTP/1.0) GATEWAY_INTERFACE Server가 사용하는 CGI의 Revision에 대한 정보(CGI/1.1)
사용자에 관한 환경변수 REMOTE_HOST REMOTE_ADDR HTTP_REFERER HTTP_FROM CGI 수행을 요청한 client program이 있는 컴퓨터의 인터넷 주소 REMOTE_ADDR CGI 수행을 요청한 client program이 위치한 컴퓨터의 IP 주소 HTTP_REFERER CGI 수행을 요청하기 전의 클라이언트가 가리키던 문서의 URL HTTP_FROM CGI실행을 요청한 사용자의 e-mail address HTTP_USER_AGENT Client program의 이름과 버전 HTTP_ACCEPT Client program(Web Browser)가 받아 들일 수 있는 MIME Type List HTTP_ACCEPT 문자열의 형식은 type/subtype 형식이다. Netscape 검색기를 Mozilla라고 부른다. REMOTE_HOST : 문자열로 표시 REMOTE_ADDR : 4개의 숫자와 점으로 표현 REMOTE_USER Authentificated User Name REMOTE_IDENT CGI수행을 요청한 User의 ID HTTP-FROM : 많은 browser가 이를 지원하지 않음
요청에 따라 달라지는 환경변수 DOCUMENT_ROOT PATH_INFO PATH_TRANSLATED SCRIPT_NAME Web document가 제공되는 서버의 directory PATH_INFO CGI 프로그램에 넘겨지는 (추가의) path 정보 PATH_TRANSLATED PATH_INFO를 변환한 path 정보 SCRIPT_NAME 현재 실행되고 있는 CGI 프로그램의 path와 이름 DOCUMENT_ROOT : Server redirection할 때 이 디렉토리에서 문서 제공 Extra Path Info Another simple method of sending data to a script is through the PATH_INFO environment variable. Similar to the query string, path info is whatever comes after the script name in the url. You need to start the path info with a slash (/) to let the web server know where the script name ends. Try the Web Form Analyser again, this time with path info instead of a query string. http://www.speakeasy.org/~cgires/perl_form.cgi/howdy.doo You'll see now that "/howdy.doo" is listed as the value of the PATH_INFO environment variable. You can supply both path info and a query string in the url as in the following link: http://www.speakeasy.org/~cgires/perl_form.cgi/howdy.doo?Fine,thanks though you must suppply the path info first and the query string second. Otherwise the query string will gobble up the path info. Try it by reversing the two and typing this example into your browser. Path info need not be a path to any particular file or directory, though this was its original intent and is still the most common use. For example, many hit counter scripts are installed for system-wide use. If one script serves many users, the script must be told which page is to be counted. Path info will often be the (file system or url) path to the particular file that contains the current count. Path info has the same disadvantages as the query string. It is not automatically url encoded, it is subject the the same path length limitations, and it is reported in the server logs.
요청에 따라 달라지는 환경변수 …. REQUEST_METHOD QUERY_STRING CONTENT_LENGTH 데이터가 전달되는 방법(POST or GET) 지정 QUERY_STRING GET 방법에서 사용되며 URL에서 ? 다음에 저장되는 정보 (http://www.bearnet.com/cgi-bin/test.cgi?quick.brown.fox) CONTENT_LENGTH POST 방법에서 사용되며 표준입력 데이터 stream(stdin)으로 입력되어 CGI 프로그램에 넘겨진 데이타의 크기(byte 단위) CONTENT_TYPE POST 방법으로 전달된 데이터에 대해 type/subtype 형식의 MIME content-type AUTH_TYPE User validation을 위해 사용된 authentification method PATH_INFO The extra path information, as given by the client. In other words, scripts can be accessed by their virtual pathname, followed by extra information at the end of this path. The extra information is sent as PATH_INFO. This information should be decoded by the server if it comes from a URL before it is passed to the CGI script. 서버에 전달하는 URL에 포함, 스크립트 뒤에, 그리고 질의 스트링 앞에 이 데이터를 둔다. Http://www.xyz.com/scripts/search.cgi/docs/november?value=abc path_info = docs/November PATH_TRANSLATED The server provides a translated version of PATH_INFO, which takes the path and does any virtual-to-physical mapping to it. 파일의 실제 경로 /users/webserver/maarketing/november Using CGI p. 100 REMOTE_USER Authentificated User Name REMOTE_IDENT CGI수행을 요청한 User의 ID
환경 변수를 출력하는 C Program #include <stdio.h> #include <stdlib.h> void main(void) { char *safenv(const char *a); printf("Content-type:text/html\n\n"); printf("<HTML>\n"); printf("<HEAD><TITLE> Hello from the server </TITLE></HEAD>\n"); printf("<BODY>\n"); printf("Server Name : %s<BR>\n",safenv("SERVER_NAME")); printf("Port No : %s<BR>\n",safenv("SERVER_PORT")); printf("Server Software : %s<BR>\n", safenv("SERVER_SOFTWARE")); printf("Server Protocol : %s<BR>\n", safenv("SERVER_PROTOCOL")); printf("CGI Revision : %s<BR>\n", safenv("GATEWAY_INTERFACE")); printf("Remote Host : %s<BR>\n", safenv("REMOTE_HOST")); printf("Remote Addr : %s<BR>\n", safenv("REMOTE_ADDR")); printf("Referer : %s<BR>\n",safenv("HTTP_REFERER")); printf("User : %s<BR>\n",safenv("HTTP_FROM"));
환경 변수를 출력하는 C Program …. printf("HTTP User Agent : %s<BR>\n",safenv("HTTP_USER_AGENT")); printf("Accept Type : %s<BR>\n", safenv("HTTP_ACCEPT")); printf("Document Root : %s<BR>\n", safenv("DOCUMENT_ROOT")); printf("Path Info : %s<BR>\n", safenv("PATH_INFO")); printf("Path Translated : %s<BR>\n", safenv("PATH_TRANSLATED")); printf("Script Name : %s<BR>\n", safenv("SCRIPT_NAME")); printf("Request Method : %s<BR>\n", safenv("REQUEST_METHOD")); printf("Query String : %s<BR>\n",safenv("QUERY_STRING")); printf("Content Length : %s<BR>\n",safenv("CONTENT_LENGTH")); printf("Content Type : %s<BR>\n" ,safenv("CONTENT_TYPE")); printf("Authorization Method : %s<BR>\n",safenv("AUTH_TYPE")); printf("</BODY></HTML>\n"); } char *safenv(const char *a) { char *empty ="<empty>"; if (getenv(a)==NULL) return empty; else return getenv(a); } <stdlib.h> : utility 함수를 포함하는 header file char *getenv(const char *name) : name에 해당하는 환경 변수 문자열을 return - C 프로그래밍 완성 p.483 환경 변수 : 운영체제에서 child process에게 정보를 전달하는 데 사용하는 특별한 이름을 가진 메모리 영역 <empty>는 특별한 의미가 없으며 단지 지원되지 않는 tag이므로 web browser가 표시하지 않는다.
환경 변수 알아 보기 예 <HTML> <HEAD><TITLE>Environment Variable</TITLE> </HEAD> <BODY> <H1>Environment Variable</H1><HR> <FORM Action="http://www.sungkyul.edu/~ywkeum/cgi/envar.cgi" Method="POST"> <FONT SIZE=5> Let's see what kinds of environment variables are available. <BR><BR> <Input Type="submit" Value="submit"> <Input Type="reset" Value="clear"> </FONT> </FORM> <HR> </BODY> </HTML> envar-h.cgis는 환경 변수를 보여 주는 CGI program
환경 변수 리스트 Server Name : hana Port No : 80 Server Software : NCSA/1.4.2 Server Protocol : HTTP/1.0 CGI Revision : CGI/1.1 Remote Host : 203.230.16.120 Remote Addr : 203.230.16.120 Referer : file:///D|/MYDOCU~1/LECTURE/HTML/HTML/CGI/ENVAR~1.HTM User : HTTP User Agent : Mozilla/4.01 [en] (Win95; I) Accept Type : image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* Document Root : /usr/local/etc/httpd/htdocs
환경 변수 리스트 …. Path Info : /a/b Path Translated : /usr/local/etc/httpd/htdocs/a/b Script Name : /home-cgi/envar.cgi Request Method : POST Query String : Content Length : 0 Content Type : application/x-www-form-urlencoded Authorization Method :
CGI 프로그램 실습 문제 앞에 나온 C program을 작성한다. 프로그램 소스를 자신의 학교 계정의 folder에 올려 놓는다. ftp 사용(http://www.shareware.co.kr/에서 알ftp 다운받아 설치) public_html 밑에 cgi folder 생성 cgi 폴더에 C 프로그램 소스를 올린다. C 프로그램 소스를 컴파일한다. telnet으로 학교 시스템 lonon한다. cgi 폴더로 이동(cd 명령 사용) 컴파일 방법 /usr/local/bin/gcc -o envar.cgi envar.c envar.c : 소스 프로그램, envar.cgi : 목적 프로그램 Html 파일을 만든다. Form 태그 사용하여 envar.cgi가 수행되도록 한다. Html 파일은 PC에 있어도 상관 없다.
Query string GET 방법을 사용할 때 데이터가 전달되는 방식이다. URL뒤에 추가된 데이터 예) http://some.machine/cgi-bin/name.pl?fortune 첫번째 ? 뒤의 모든 데이터를 query string이라 한다. CGI 프로그램은 QUERY_STRING이라는 환경변수를 참조하여 query string을 얻을 수 있다.
Query string 연습 문제 여러 Search engine에서 다음과 같은 단어로 웹 페이지를 찾아 보고 여기에 대응되는 query string을 적어 보시오. CGI and JavaScript
Rules of encoding Form에서 입력하는 내용은 한 개의 문자열로 합하여져서 CGI 프로그램에 전달된다. 규칙 Name/Value pair : &로 구별된다. Name에 Value 할당 : =을 사용한다. Name1=Value1&Name2=Value2&…. Space : ‘+’로 변환된다. (URL을 적는 규칙은 space를 허용하지 않는다.) Special Characters : %two-digit hex equivalent to ASCII code 예 Name1에 First, Name2에 Second? That’s right. 일 때 => Name1=First&Name2=Second%3F+That%26s+right%21 Browsers will bundle this data into a single string using these rules of url-encoding: all the submitted form data will be concatenated into a single string of ampersand (&) separated name=value pairs, one pair for each form tag. Like this: form_tag_name_1=value_1&form_tag_name_2=value_2&... any spaces occurring in a name or value will be replaced by a plus (+) sign. This is because url's cannot have spaces in them and under METHOD=GET, the form data is supplied in the query string in the url. other punctuation characters (for example, equal signs and ampersands) occurring in names or values will be replaced with a percent sign (%) followed by the two-digit hexadecimal equivalent of the punctuation character in the Ascii character set. (Hexadecimal is base 16.) Otherwise, it would be hard to distinguish these characters inside a form variable from those between the form variables in the first rule above.
실습 문제 : encoding의 예 아래와 같은 form을 작성하여 이 form에서 입력된 자료가 자신의 email로 전달되게 하고 email을 열어 자료를 확인하시오. Data1은 영문으로, Data2는 한글로 자료 입력하여 보시오. Browsers will bundle this data into a single string using these rules of url-encoding: all the submitted form data will be concatenated into a single string of ampersand (&) separated name=value pairs, one pair for each form tag. Like this: form_tag_name_1=value_1&form_tag_name_2=value_2&... any spaces occurring in a name or value will be replaced by a plus (+) sign. This is because url's cannot have spaces in them and under METHOD=GET, the form data is supplied in the query string in the url. other punctuation characters (for example, equal signs and ampersands) occurring in names or values will be replaced with a percent sign (%) followed by the two-digit hexadecimal equivalent of the punctuation character in the Ascii character set. (Hexadecimal is base 16.) Otherwise, it would be hard to distinguish these characters inside a form variable from those between the form variables in the first rule above.
연습 문제 : encoding의 예(html 소스) <BODY> <H1> Two text fields </H1> <HR> <FORM Action="mailto:ywkeum@sungkyul.edu" Method="POST"> Data 1 <Input Type="text" Name="name1" Size=40> <BR> Data 2 <Input Type="text" Name="name2" Size=40> <BR><BR> <Input Type="submit" Value="Submit"> <Input Type="reset" Value="clear"> </FORM> </BODY> Browsers will bundle this data into a single string using these rules of url-encoding: all the submitted form data will be concatenated into a single string of ampersand (&) separated name=value pairs, one pair for each form tag. Like this: form_tag_name_1=value_1&form_tag_name_2=value_2&... any spaces occurring in a name or value will be replaced by a plus (+) sign. This is because url's cannot have spaces in them and under METHOD=GET, the form data is supplied in the query string in the url. other punctuation characters (for example, equal signs and ampersands) occurring in names or values will be replaced with a percent sign (%) followed by the two-digit hexadecimal equivalent of the punctuation character in the Ascii character set. (Hexadecimal is base 16.) Otherwise, it would be hard to distinguish these characters inside a form variable from those between the form variables in the first rule above.
제 3장 Output from the CGI CGI Program의 Output Simple document를 출력할 수 있다. Plain text HTML document 그림 또는 그 외의 이진 데이터(영상, 소리, 등등)를 출력할 수 있다. Client에게 HTTP status code를 보낼 수 있다. Server에게 특정 document를 client에게 보내도록 지시할 수 있다. Client로 하여금 Virtual Document의 Caching 여부를 지시할 수도 있다.
HTTP Header Content-Type Content-Length Location Expires/Pragma Status Output Stream의 MIME Content Type Content-Length Output Stream의 크기 (byte 단위) Location Used to specify to the server that the script is returning a reference to a document rather than an actual document. 예) printf(“Location: /thanks.html\n\n”); Expires/Pragma Headers to instruct the client not to cache the document. Status Request의 status 정보 7.2.1.2. Location : Server redirection을 위해 사용 : DOCUMENT_ROOT에 있는 기존의 서버 문서 return This is used to specify to the server that the script is returning a reference to a document rather than an actual document. Location = "Location" ":" ( fragment-URI | rel-URL-abs-path ) NL fragment-URI = URI [ # fragmentid ] URI = scheme ":" *qchar fragmentid = *qchar rel-URL-abs-path = "/" [ hpath ] [ "?" query-string ] hpath = fpsegment *( "/" psegment ) fpsegment = 1*hchar psegment = *hchar hchar = alpha | digit | safe | extra | ":" | "@" | "& | "=" The Location value is either an absolute URI with optional fragment, as defined in RFC 1630 [1], or an absolute path within the server's URI space (i.e., omitting the scheme and network-related fields) and optional query-string. If an absolute URI is returned by the script, then the server MUST generate a '302 redirect' HTTP response message unless the script has supplied an explicit Status response header field. Scripts returning an absolute URI MAY choose to provide a message-body. Servers MUST make any appropriate modifications to the script's output to ensure the response to the user-agent complies with the response protocol version. If the Location value is a path, then the server MUST generate the response that it would have produced in response to a request containing the URL scheme "://" SERVER_NAME ":" SERVER_PORT rel-URL-abs-path Note: If the request was accompanied by a message-body (such as for a POST request), and the script redirects the request with a Location field, the message-body may not be available to the resource that is the target of the redirect. 3.6 The "Expires" and "Pragma" Headers Most browsers cache (or store internally) the documents you access. This is a very positive feature that saves a lot of resources; the browser doesn't have to retrieve the document every time you look at it. However, it can be a slight problem when you are dealing with virtual documents created by CGI programs. Once the browser accesses a virtual document produced by a CGI program, it will cache it. The next time you try to access the same document, the browser will not make a request to the server, but will reload the document from its cache. To see the effects of caching, try running the following program: #!/usr/local/bin/perl chop ($current_date = `/bin/date`); $script_name = $ENV{'SCRIPT_NAME'}; print "Content-type: text/html", "\n\n"; print "<HTML>", "\n"; print "<HEAD><TITLE>Effects of Browser Caching</TITLE></HEAD>", "\n"; print "<BODY><H1>", $current_date, "</H1>", "\n"; print "<P>", qq|<A HREF="$script_name">Click here to run again!</A>|, "\n"; print "</BODY></HTML>", "\n"; exit (0); This program displays the current time, as well as a hypertext link to itself. If you click on the link to run the program again, the date and time that is displayed should change, but it does not, because the browser is retrieving the cached document. You need to explicitly tell the browser to reload the document if you want to run the CGI program again. Fortunately, there is a solution to this problem. If you don't want a virtual document to be cached, you can use the Expires and/or Pragma headers to instruct the client not to cache the document. print "Content-type: text/html", "\n"; print "Pragma: no-cache", "\n\n"; . or print "Expires: Wednesday, 27-Dec-95 05:29:10 GMT", "\n\n"; However, some browsers don't handle these headers correctly, so don't rely on them. Pragma 현문서의 Caching 여부를 지정(On/Off)
HTTP Header 작성 요령 1) Header Line 정보를 적는 정해진 순서는 없다. 2) Header Block과 Body Block은 blank line으로 구별된다. Content-type: text/html <HTML> <HEAD><TITLE>Virtual HTML Document</TITLE> </HEAD> <BODY> ... </BODY> </HTML> Blank line
Content-type & Content-length CGI로 하여금 web Browser가 처리 가능한 data를 넘겨주도록 할 수 있다. Web browser가 처리 가능한 data의 형태는 환경변수 HTTP_ACCEPT에 저장되어 있다. CGI는 환경변수 HTTP_ACCEPT에 맞추어 Content-type을 넘겨준다. Content-Length HTML 문서가 아닌 GIF, JPEG Image, Audio Clip을 전송할 수도 있다. 이 때에는 반드시 Content-length를 명시해 주어야 한다. Content-type: image/gif Content-length: 12000
Status Codes Client의 정보 request 처리결과 상태정보 (status/reason string) 200 OK 204 No Content 301 Document Moved Permanently 401 Unauthorized 403 Forbidden 404 Not Found 500 Internal Server Error 501 Not Implemented (참고 site) ftp://ftp.isi.edu/in-notes/rfc2616.txt The format is nnn xxxxx, where nnn is the 3-digit status code, and xxxxx is the reason string, such as "Forbidden". 10.2.5 204 No Content The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant. 10.3.2 301 Moved Permanently The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise. The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). 10.4.2 401 Unauthorized The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43]. 10.4.4 403 Forbidden The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 Not Found) can be used instead. 10.4.5 404 Not Found The server has not found anything matching the Request-URI. No Indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable. 10.5.1 500 Internal Server Error The server encountered an unexpected condition which prevented it from fulfilling the request. 10.5.2 501 Not Implemented The server does not support the functionality required to fulfill the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource.
An example of an output from CGI 예 #include <stdio.h> #include <stdlib.h> void main() { printf("Content-type: text/html\n\n"); printf("<HTML>\n"); printf("<HEAD><TITLE> HTML Document from CGI </TITLE></HEAD>\n"); printf("<BODY>\n"); printf("<H1> Welcome </H1>\n"); printf(“This is the output from a CGI program<BR>\n"); printf("</BODY></HTML> \n"); }
연습 문제 프로그램에서 html 문서를 생성하여 웹 브라우저에 출력하는 CGI 프로그램을 작성하고 호출하여 보시오. Location을 사용하여 서버에 있는 html 문서를 출력하는 CGI 프로그램을 작성하고 호출하시오. 환경 변수를 출력하는 프로그램을 작성하고 호출하시오. The format is nnn xxxxx, where nnn is the 3-digit status code, and xxxxx is the reason string, such as "Forbidden". 10.2.5 204 No Content The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant. 10.3.2 301 Moved Permanently The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise. The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). 10.4.2 401 Unauthorized The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43]. 10.4.4 403 Forbidden The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 Not Found) can be used instead. 10.4.5 404 Not Found The server has not found anything matching the Request-URI. No Indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable. 10.5.1 500 Internal Server Error The server encountered an unexpected condition which prevented it from fulfilling the request. 10.5.2 501 Not Implemented The server does not support the functionality required to fulfill the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource.
제 4장 Forms and the CGI Form의 사용 목적 Form 사용의 이점 Form 사용의 문제점 Data collection Interactive communication Form 사용의 이점 Platform independent user interface 다양한 gateway(database, information server)에 대한 front end Form 사용의 문제점 text 형 이외의 데이터 형에 대한 지원이 안 된다. int, data, float, url 등의 데이터 형을 구별하여 지정하지 못한다. User input을 client side에서 검증하지 못한다. JavaScript와 CGI를 함께 사용하면 synergy 효과가 있음
Form을 이용하여 Data를 처리하는 과정 User Requests a form User fills out the form Sends the form to client Forward to CGI application User submits form Output Received Output to Server Output to client Client (Web Browser) Server Application (CGI)
FORM tag Form을 구성하기 위해서는 <FORM> </FORM> tag를 사용한다. 형식 : <FORM ACTION=“...” METHOD=“...” NAME=“…”> ACTION : CGI program의 위치와 CGI program명을 지정한다. ACTION을 지정하지 않으면 document의 URL을 사용 예) ACTION=“../cgi-bin/cgi-01.pl” METHOD : POST 또는 GET을 지정한다. POST를 사용하는 것을 권장함 값을 적지 않으면 GET이 default 값으로 사용됨. 예) METHOD=“POST” NAME : FORM의 이름을 지정 예) NAME=“myForm”
FORM tag 내의 다른 tag들 <FORM ...> <INPUT …> …. </INPUT> <SELECT ...> <OPTION>…. </SELECT> <TEXTAREA …> …. </TEXTAREA> </FORM>
INPUT tag <FORM> tag 내에서 <INPUT> tag로 입력 필드 지정 <INPUT> tag의 TYPE attribute에 입력 필드 종류 지정 Text field : Text, Password, Hidden Button Submit : form을 서버에 전송 Reset : form을 초기 상태로 만듬 Check Box & Radio Button Other attributes(TYPE 외에) Name : 입력 필드의 이름 지정 Value : 입력 필드의 값 또는 button의 label 지정 Checked : 선택 항목 중 어떤 항목을 기본으로 선택 Size : 입력 필드의 크기 지정 Maxlength : 실제 입력할 수 있는 최대 문자수 지정 Password field : 글자가 나타나지 않고 ***가 나타남 Before we move on, there is still another type of text field. It is called a "hidden" field and allows you to store information in the form. The client will not display the field. For example: <INPUT TYPE="hidden" NAME="publisher" VALUE="ORA"> Hidden fields are most useful for transferring information from one CGI application to another. See Chapter 8, Multiple Form Interaction, for an example of using hidden fields.
SELECT tag <FORM> tag 내에서 Pull down menu, Scrolled menu 지정할 때 사용 Attributes Name attribute : 이름을 지정 Size attribute : 항목 수를 지정 Multiple : 다중 선택을 가능하게 한다. OPTION tag SELECT tag 내에서 선택 사항을 지정 Attributes SELECTED : 기본으로 선택된 항목을 지정 VALUE : 서버에 전송되는 데이터 값 정의
Textarea tag 여러 줄의 text를 입력 할 때 사용 <FORM> tag 내에 정의 Attributes Name : 이름을 지정 Rows : 세로의 길이를 나타냄 Cols : 가로의 길이를 나타냄
(1) Single Text Field <HTML> <HEAD><TITLE>Single Text Field</TITLE> </HEAD> <BODY> <H1> Single Text Field </H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> Name <Input Type=“text” Name=“name” Size=10> <BR> <Input Type=“submit” Value=“Submit Query”> <Input Type=“reset” Value=“clear”> </FORM> </BODY></HTML>
환경변수와 입력을 출력하는 C program #include <stdio.h> #include <stdlib.h> // #include <string.h> void main() { int icl, nobj; char *qs; /*POST 방법으로 전달하는 자료를 넣는 장소 */ char *safenv(const char *a); printf("Content-type: text/html\n\n"); printf("<HTML>\n"); printf("<HEAD><TITLE> Form Input Test </TITLE></HEAD>\n"); printf("<BODY>\n"); printf("<HR noshade>\n"); printf("<H1 ALIGN=CENTER> <FONT COLOR=BLUE> Your Encoded Input Is </FONT></H1>\n"); printf("<HR noshade><FONT SIZE=5>\n");
환경변수와 입력을 출력하는 C program …. printf("<UL>\n"); printf("Request Method : %s<BR>\n", safenv("REQUEST_METHOD")); printf("Query String with GET : %s<BR>\n", safenv("QUERY_STRING"));//GET printf("Content Length : %s<BR>\n", safenv("CONTENT_LENGTH")); icl=atoi(safenv("CONTENT_LENGTH")); /* atoi : 문자열을 정수로 변환 */ if (icl !=0) { qs = malloc(icl+1); // icl=0이 아니면 POST 방법 // malloc : (icl+1) bytes의 메모리 할당 if ((nobj = fread(qs, icl, 1, stdin)) != 1 ) { printf("cannot read the input stream (%d)!\n",nobj); exit(1);} /* fread : stdin에서 자료를 1개 object에서 icl bytes를 읽어 qs에 넣는다. */ int atoi(const char *s) : 문자열 s를 정수로 변환 size_t fread(void *_ptr, size_t _size, size_t nobj, FILE *__stream); fread reads from stream into the array ptr at most nobj objects of size _size. fread returns the number of objects read; this may be less than the number requested. feof and ferror must be used to determine status.
환경변수와 입력을 출력하는 C program …. printf("Input with POST : \n"); printf("%s", qs); } // POST 방법으로 읽은 자료 출력 printf("</UL><FONT>\n"); printf("</BODY></HTML>\n"); } char *safenv(const char *a) { char *empty ="<empty>"; if (getenv(a)==NULL) return empty; else return getenv(a); } int atoi(const char *s) : 문자열 s를 정수로 변환 size_t fread(void *_ptr, size_t _size, size_t nobj, FILE *__stream); fread reads from stream into the array ptr at most nobj objects of size _size. fread returns the number of objects read; this may be less than the number requested. feof and ferror must be used to determine status.
환경 변수와 입력 자료 (예) 입력 : Hongkil Dong GET의 경우 POST의 경우 Query String with GET : name=Hongkil+Dong Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 17 Input with POST : name= Hongkil+Dong Simple Text Input Box에 입력한 후, Submit Button을 누르면...(2) (예) 입력 : 정대영 GET의 경우 Query String with GET : name=%C1%A4%B4%EB%BF%B5 CONTENT LENGTH : INPUT WAS : POST의 경우 Query String with GET : CONTENT LENGTH : 23 INPUT WAS : name=%C1%A4%B4%EB%BF%B5 Simple Text Input Box에 입력한 후, Submit Button을 누르면...(3) (아무것도 입력하지 않은 경우) Query String with GET : name= CONTENT LENGTH : 5 INPUT WAS : name=
POST v.s. GET의 URL 비교 GET 방법 사용 시 URL http://www.sungkyul.ac.kr/home-cgi/listform.cgi? name=Hongkil+Dong POST 방법 사용 시 URL http://www.sungkyul.ac.kr/home-cgi/listform.cgi
(2) Multiple Text Fields <HTML> <HEAD><TITLE> Multiple Text Fields </TITLE></HEAD> <BODY> <H1> Multiple Text Fields </H1> <HR> <FORM Action= “home-cgi/listform.cgi” Method=“POST”> 학번 <Input Type=“text” Name=“studentid” Size=20> <BR> 성명 <Input Type=“text” Name=“name” Size=20> <Input Type=“submit” Value=“Submit Query”> <Input Type=“reset” Value=“clear”> </FORM> </BODY></HTML>
환경 변수와 입력 자료 (예) 학번 : 88406-023 성명 : Hongkil Dong GET의 경우 POST의 경우 (예) 학번 : 88406-023 성명 : Hongkil Dong GET의 경우 Query String with GET : studentid=88406-023&name= Hongkil+Dong Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 37 Input with POST : studentid=88406-023&name= Hongkil+Dong (학번 : 88406-023) (성명은 넣지 않은 경우) GET의 경우 Query String with GET : studentid=88406-023&name= CONTENT LENGTH : INPUT WAS : POST의 경우 Query String with GET : CONTENT LENGTH : 25 INPUT WAS : studentid=88406-023&name=
POST v.s. GET의 URL 비교 GET 방법 사용시 URL http://www.sungkyul.ac.kr/ home-cgi/listform.cgi ?studentid=88406-406&name= Hongkil+Dong POST 방법 사용시 URL http:// www.sungkyul.ac.kr/ home-cgi/listform.cgi
(3) CHECK BOX <HTML> <HEAD><TITLE>Check Box</TITLE> </HEAD> <BODY> <H1>Check Box</H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> Which toppings would you like? <BR> <Input Type=“checkbox” Name=“Pepperoni ”> Pepperoni <Input Type=“checkbox” Name=“Sausage”> Sausage <Input Type=“checkbox” Name=“Ham”> Ham <Input Type=“checkbox” Name=“Pineapple”> Pineapple <BR> <Input Type=“submit” Value=“submit”> <Input Type=“reset” Value=“clear”> </FORM> <HR> </BODY> </HTML> Multiple choices are possible.
환경 변수와 입력 자료 (예) Sausage와 Ham을 Check한 경우 GET의 경우 POST의 경우 Query String with GET : sausage=on&ham=on Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 18 Input with POST : sausage=on&ham=on
(4) Radio Button <HTML> <HEAD><TITLE> Radio Button </TITLE></HEAD> <BODY> <H1> Radio Button </H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> 당신이 가장 좋아하는 가수는? <BR> <Input Type=“radio” Name=“singer” Value=“ujh”> 엄정화 <Input Type=“radio” Name=“singer” Value=“khj”> 김현정 <Input Type=“radio” Name=“singer” Value=“sch”> 소찬휘 <Input Type=“radio” Name=“singer” Value=“lsr”> 이소라 <BR> <Input Type=“submit” Name=“submit”> <Input Type=“reset” Name=“clear”> </FORM> <HR></BODY> </HTML>
환경 변수와 입력 자료 (예) 엄정화를 선택한 경우 GET의 경우 POST의 경우 Query String with GET : singer=ujh Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 10 Input with POST : singer=ujh
(5) Scrolled Lists <HTML> <HEAD><TITLE> Scrolled Lists </TITLE></HEAD> <BODY> <H1> Scrolled Lists </H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> 좋아하는 프로 야구단은? <BR> <Select Name=“baseball” Size=1> <Option Selected> OB Bears <Option> LG Twins <Option> Haitai Tigers <Option> Samsung Lions </Select> <Input Type=“submit” Name=“submit”> <Input Type=“reset” Name=“clear”> </FORM> <HR> </BODY> </HTML>
환경 변수와 입력 자료 (예) OB Bears를 선택한 경우 GET의 경우 POST의 경우 Query String with GET : baseball=OB+BEARS Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 17 Input with POST : baseball=OB+BEARS
(6) Scrolled Lists (Multiple) <HTML> <HEAD><TITLE>Scrolled Lists (Multiple) </TITLE></HEAD> <BODY> <H1> Scrolled Lists (Multiple) </H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> 좋아하는 맥주는? <BR> <Select Name=“beer” Size=3 Multiple> <Option> OB Cafri <Option> OB Lite <Option> OB Lager <Option> Budweiser <Option> 하이트 </Select> <Input Type=“submit” Name=“submit”> <Input Type=“reset” Name=“clear”> </FORM> <HR> </BODY> </HTML>
환경 변수와 입력 자료 (예) OB Cafri와 OB Larger를 선택한 경우 GET의 경우 POST의 경우 Query String with GET : beer=OB+CAFRI&beer=OB+Lager Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 27 Input with POST : beer=OB+CAFRI&beer=OB+Lager
(7) Text Area <HTML> <HEAD><TITLE> Text Area </TITLE> </HEAD> <BODY> <H1> Text Area </H1> <HR> <FORM Action=“home-cgi/listform.cgi” Method=“POST”> 하고 싶은 말 다 적으세요. <BR> <TextArea Rows=3 Cols=40 Name=“comments”> </TextArea> <BR> <Input Type=“submit” Value=“submit”> <Input Type=“reset” Value=“clear”> </FORM> <HR> </BODY> </HTML>
환경 변수와 입력 자료 (예) Glad to meet you ! Let’s go to paint the town red. GET의 경우 Query String with GET : comments=Glad+to+meet+you+%21%0D%0ALet%27s+paint+the+town+red.%0D%0A Content Length : Input with POST : POST의 경우 Query String with GET : Content Length : 68 comments=Glad+to+meet+you+%21%0D%0ALet%27s+paint+the+town+red.%0D%0A %21%0D%0A => ! CR LF
Lab : 환경 변수와 입력 자료 알아 보기 임의의 입력 폼을 2개 이상 작성하여 각각에 대하여 다음과 같이 2개의 form 태그를 작성하여 submit하여 CGI 프로그램에 전달되는 값을 확인한다. 1. GET <FORM Action= “http://www.sungkyul.edu/~ywkeum/cgi/listform.cgi" Method="GET"> 2. POST <FORM Action= "http://www.sungkyul.edu/~ywkeum/cgi/listform.cgi" Method="POST"> %21%0D%0A => ! CR LF
Decoding Process의 절차 1. Request protocol이 무엇인지 확인한다. REQUEST_METHOD가 POST인지 GET인지... 2. Protocol이 GET이면 Query를 QUERY_STRING에서 읽어 들이고, PATH_INFO를 참조한다. 3. Protocol이 POST이면 Request의 길이를 CONTENT_LENGTH에서 읽어 들인 후 Request를 표준입력 Data Stream에서 읽어 들인다. 4. 입력 자료를 &단위로 잘라 내고 해석한다. name=value&name=value... 5. Hexadecimal 및 + character를 해석한다. 6. Name은 1번째, value는 2번째 요소로 된 table을 만든다.
Lab : 입력 자료의 디코딩 이전에 작성한 입력 폼에 수행되는 CGI 프로그램을 아래와 같이 변경하여 입력 자료가 디코딩 되어 출력되는 것을 확인하시오. 기존의 출력 자료와 비교하시오. <FORM Action= “http: www.sungkyul.edu/~ywkeum/cgi/ /cgiqc.cgi" Method=“POST"> %21%0D%0A => ! CR LF
Sample C program for decoding 자료 선언 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { // 자료를 decoding한 곳의 주소를 표시 char *param; // name 에 속한 자료의 주소 char *val; // name에 대한 값의 주소 } ITEM; void main() { char *qc,*buffer,hex[3]; // qc : form에서 입력된 자료를 보관 int ql,i,j,k,l,h; long handle=0; ITEM *itemp;
Sample C program for decoding POST 또는 GET 처리 if (!strcmp("POST", getenv("REQUEST_METHOD"))) { ql = atoi(getenv("CONTENT_LENGTH")); // 자료 길이 qc = malloc(ql+1); // 자료를 넣을 공간 확보 buffer = malloc(ql+1); // 변환된(decoding)된 자료 넣을 공간 fread(qc, ql, 1, stdin); // qc에 자료를 읽어 넣음 qc[ql] = 0; } else { qc = getenv("QUERY_STRING"); // GET 으로 전달된 자료 qc에 넣음 ql = strlen(qc); buffer = malloc(ql+1); for (i=0,l=0; i<ql; i++) if (qc[i]=='&') l++; /* l+1 is the number of names */
Sample C program for decoding 자료에 값에 따른 decoding itemp = (ITEM *)malloc(sizeof(ITEM)*(l+1)); k = 0; itemp[k].param = &buffer[0]; for (i=0,j=0; i<ql; i++,j++) { switch (qc[i]) { case '&': buffer[j] = 0; itemp[++k].param = &buffer[j+1]; break; case '=': itemp[k].val = &buffer[j+1]; case '+': buffer[j] = ' ';
Sample C program for decoding 자료에 값에 따른 decoding …. case '%': hex[0] = qc[++i]; hex[1] = qc[++i]; hex[2] = 0; // end of string sscanf(hex, "%x", &h); // hex[0]와 hex[1]을 16진수로 읽어 h에 넣음 buffer[j] = (char)h; // 문자로 변환 break; default: buffer[j] = qc[i]; } buffer[j] = 0;
Sample C program for decoding 출력하기 printf("Content-type:text/html\n\n"); printf("<html>\n"); printf("<head></head>\n"); printf("<body>\n"); printf("Request Method: %s<br>\n", getenv("REQUEST_METHOD")); for (i=0; i<=l; i++) printf("%s: %s<br>\n", itemp[i].param, itemp[i].val); printf("</body>\n"); printf("</html>\n"); }
제 5장 SSI(Server Side Include) HTML 문서 내에 명령어와 옵션을 준다. 형식 : <!--#command options=“value” ……. --> 서버는 이 문서를 parsing하여 주어진 명령어 해독 서버가 그 결과를 문서 중간에 삽입하여 클라이언트에게 보낸다. 적용 분야 날자나 현재 시각 표시 파일의 최종 갱신 시각이나 파일 크기 표시 별도의 파일 포함 명령의 결과를 받는다.
SSI command : #config SSI를 사용하는 다른 명령의 출력 형식을 정한다. errmsg=“….” SSI 실행 중 error 발생한 경우 출력하는 메시지 전달 <!--#config errmsg=“SSI 실패”--> timefmt=“….” 날자나 파일의 최종 갱신 시각 표시할 때의 포맷을 지정 <!--#config timefmt=“%m월%d일”--> sizefmt=“….” 파일 크기의 포맷을 지정 <!--#config sizefmt=“bytes”-->
SSI command : #include 다른 파일을 포함 시킬 때 사용한다. file=“….” 현재 디렉토리를 기준으로 한 상대적인 경로 <!--#include file=“sections/main.html”--> virtual=“….” 서버에 있는 파일을 URL로 기술 <!--#include virtual=“/~yskim/main.html”--> Text file, HTML file, parsed HTML file 등을 include 할 수 있음 동일한 파일이 여러 곳에 사용될 경우 한 파일만 고치면 되므로 유용하게 사용할 수 있다.
SSI command : #echo 서버 측에 정의되어 있는 변수를 var 옵션을 사용하여 표시한다. 변수의 종류 DOCUMENT_NAME : 파일명 DATE_LOCAL : 서버의 시간 DATE_GMT : 그리니치 표준 시간 LAST_MODIFIED : 파일의 최종 수정된 날자 오늘은 <!--#echo var=“DATE_LOCAL”-->입니다. => 오늘은 Monday, 12 Oct 98 19:50:00 입니다. <!--#config timefmt=%m월%d일”--> => 오늘은 10월 12일 입니다. Text file, HTML file, parsed HTML file 등을 include 할 수 있음 동일한 파일이 여러 곳에 사용될 경우 한 파일만 고치면 되므로 유용하게 사용할 수 있다.
SSI command : #flastmod, #fsize 이 문서의 최종 갱신 시간은 <!--#config timefmt=%m%d %H:%M”--> <!--#flastmod file=“main.html”-->입니다. => 이 문서의 최종 갱신 시간은 10/12 18:25 입니다. Text file, HTML file, parsed HTML file 등을 include 할 수 있음 동일한 파일이 여러 곳에 사용될 경우 한 파일만 고치면 되므로 유용하게 사용할 수 있다.
SSI command : #exec 쉘 명령(cmd option)이나 CGI(cgi option)를 실행시킬 때 사용한다. <!--#exec cmd=“/usr/bin/finger niles@selah.net”--> 현재 시각은 <!--#exec cmd=“date”--> 입니다. This page has been accessed <!--#exec cgi="/cgi-bin/counter.pl"--> times. In this example, we use the UNIX finger command to retrieve some information about the user. SSI allows us to pass command-line arguments to the external programs. If you plan to use environment variables as part of an argument, you have to precede them with a dollar sign. The reason for this is that the server spawns a shell to execute the command, and that's how you would access the environment variables if you were programming in a shell. Here is what the output will look like, assuming REMOTE_USER and REMOTE_HOST are "shishir" and "bu.edu", respectively: An important thing to note is that a CGI program called by an SSI directive cannot output anything other than text because this data is embedded within an HTML or plain document that invoked the directive. As a result, it doesn't matter whether you output a content type of text/plain or text/html, as the browser will interpret the data within the scope of the calling document. Needless to say, your CGI program cannot output graphic images or other binary data.
참고 문헌 O'Reilley CGI Programming on the World Wide http://www-iutsoph.unice.fr/infocom/WEB/cgi/index.htm CGI: Common Gateway Interface http://www.w3.org/CGI/ The WWW Common Gateway Interface Version 1.1 http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html Hypertext Transfer Protocol -- HTTP/1.1 ftp://ftp.isi.edu/in-notes/rfc2616.txt