Perl CGI 프로그래밍
CGI란
NCSA는 현재 NCSA에서 관리하는 CGI를 다음과 같이 정의합니다.
CGI(Common Gateway Interface), 공통 게이트웨이 인터페이스입니다. 프로그램은 HTTP 서버와 같은 서버에서 실행되어 클라이언트 HTML 페이지와의 인터페이스를 제공합니다.
웹 탐색
CGI의 작동 방식을 더 잘 이해하기 위해 웹 페이지의 링크나 URL을 클릭하는 과정부터 시작할 수 있습니다.
1. 브라우저를 사용하여 URL에 접속하고 HTTP 웹 서버에 연결합니다.
2. 웹 서버는 요청 정보를 받은 후 URL을 구문 분석하여 해당 파일이 서버에 존재하는지 확인하고, 파일의 내용을 반환합니다. 그렇지 않으면 오류 메시지가 반환됩니다.
3. 브라우저는 서버로부터 정보를 받아 수신된 파일이나 오류 메시지를 표시합니다.
CGI 프로그램은 Python 스크립트, PERL 스크립트, SHELL 스크립트, C 또는 C++ 프로그램 등이 될 수 있습니다.
CGI 아키텍처 다이어그램
웹 서버 지원 및 구성
CGI 프로그래밍을 하기 전에 다음 사항을 확인하세요. 웹 서버는 CGI를 지원하며 CGI 처리기가 구성되어 있습니다.
Apache는 CGI 구성을 지원합니다.
CGI 디렉터리 설정:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
모든 HTTP 서버 실행 CGI 프로그램은 미리 구성된 디렉터리에 저장됩니다. 이 디렉토리를 CGI 디렉토리라고 하며 관례적으로 이름은 /var/www/cgi-bin입니다.
CGI 파일의 확장자는 .cgi이며 Perl도 .pl 확장자를 사용할 수 있습니다.
기본적으로 Linux 서버가 실행되도록 구성된 cgi-bin 디렉터리는 /var/www입니다.
CGI 스크립트를 실행하기 위해 다른 디렉터리를 지정하려면 다음과 같이 httpd.conf 구성 파일을 수정할 수 있습니다.
<Directory "/var/www/cgi-bin"> AllowOverride None Options +ExecCGI Order allow,deny Allow from all </Directory>
우리가 액세스할 수 있도록 AddHandler에 .pl 접미사를 추가하세요. .pl로 끝나는 Perl 스크립트 파일:
AddHandler cgi-script .cgi .pl .py
첫 번째 CGI 프로그램
아래에서 test.cgi 파일을 생성하고 코드는 다음과 같습니다.
#!/usr/bin/perl print "Content-type:text/html\r\n\r\n"; print '<html>'; print '<head>'; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print '</head>'; print '<body>'; print '<h2>Hello Word! </h2>'; print '<p>来自php中文网第一个 CGI 程序。</p>'; print '</body>'; print '</html>'; 1;
browser http://localhost/cgi-bin/test.cgi를 열면 출력은 다음과 같습니다:
스크립트 첫 번째 줄의 출력 내용은 "Content"입니다. -type: text/htmlrnrn" 브라우저에 전송되며 표시할 콘텐츠 유형이 "text/html"임을 브라우저에 알립니다.
HTTP 헤더
test.cgi 파일 내용의 "Content-type: text/html"은 HTTP 헤더의 일부로 브라우저에 전송되어 이를 알립니다. 브라우저 서버 파일의 콘텐츠 유형입니다.
HTTP 헤더의 형식은 다음과 같습니다.
HTTP 字段名: 字段内容
예:
Content-type:text/html\r\n\r\n
다음 표는 CGI 프로그램에서 HTTP 헤더에 일반적으로 사용되는 정보를 소개합니다.
头 | 描述 |
---|---|
Content-type: | 请求的与实体对应的MIME信息。例如: Content-type:text/html |
Expires: Date | 响应过期的日期和时间 |
Location: URL | 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 |
Last-modified: Date | 请求资源的最后修改时间 |
Content-length: N | 请求的内容长度 |
Set-Cookie: String | 设置Http Cookie |
CGI 환경 변수
모든 CGI 프로그램은 CGI 프로그램에서 중요한 역할을 하는 다음과 같은 환경 변수를 받습니다.
变量名 | 描述 |
---|---|
CONTENT_TYPE | 这个环境变量的值指示所传递来的信息的MIME类型。目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencoded,他表示数据来自于HTML表单。 |
CONTENT_LENGTH | 如果服务器与CGI程序信息的传递方式是POST,这个环境变量即使从标准输入STDIN中可以读到的有效数据的字节数。这个环境变量在读取所输入的数据时必须使用。 |
HTTP_COOKIE | 客户机内的 COOKIE 内容。 |
HTTP_USER_AGENT | 提供包含了版本数或其他专有数据的客户浏览器信息。 |
PATH_INFO | 这个环境变量的值表示紧接在CGI程序名之后的其他路径信息。它常常作为CGI程序的参数出现。 |
QUERY_STRING | 如果服务器与CGI程序信息的传递方式是GET,这个环境变量的值即使所传递的信息。这个信息经跟在CGI程序名的后面,两者中间用一个问号'?'分隔。 |
REMOTE_ADDR | 这个环境变量的值是发送请求的客户机的IP地址,例如上面的192.168.1.67。这个值总是存在的。而且它是Web客户机需要提供给Web服务器的唯一标识,可以在CGI程序中用它来区分不同的Web客户机。 |
REMOTE_HOST | 这个环境变量的值包含发送CGI请求的客户机的主机名。如果不支持你想查询,则无需定义此环境变量。 |
REQUEST_METHOD | 提供脚本被调用的方法。对于使用 HTTP/1.0 协议的脚本,仅 GET 和 POST 有意义。 |
SCRIPT_FILENAME | CGI脚本的完整路径 |
SCRIPT_NAME | CGI脚本的的名称 |
SERVER_NAME | 这是你的 WEB 服务器的主机名、别名或IP地址。 |
SERVER_SOFTWARE | 这个环境变量的值包含了调用CGI程序的HTTP服务器的名称和版本号。例如,上面的值为Apache/2.2.14(Unix) |
다음은 CGI 환경 변수를 출력하는 간단한 CGI 스크립트입니다.
#!/usr/bin/perl print "Content-type: text/html\n\n"; print '<meta charset="utf-8">'; print "<font size=+1>环境变量:</font>\n"; foreach (sort keys %ENV) { print "<b>$_</b>: $ENV{$_}<br>\n"; } 1;
파일 다운로드
Perl CGI를 통해 파일 다운로드를 구현하려면 다르게 설정해야 합니다. 헤더 정보는 아래와 같습니다.
#!/usr/bin/perl # HTTP Header print "Content-Type:application/octet-stream; name=\"FileName\"\r\n"; print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n"; # Actual File Content will go hear. open( FILE, "<FileName" ); while(read(FILE, $buffer, 100) ) { print("$buffer"); }
GET 메서드를 사용하여 데이터를 전송합니다
GET 메서드는 인코딩된 사용자 정보를 서버로 보냅니다. 데이터 정보는 URL에 포함됩니다. 요청된 페이지를 아래와 같이 "?"로 구분합니다.
http://www.test.com/cgi-bin/test.cgi?key1=value1&key2=value2GET 요청에 대한 기타 참고 사항:
GET 요청은 캐시될 수 있습니다
-
GET 요청은 브라우저 기록에 보관
GET 요청은 북마크에 추가할 수 있습니다
민감한 데이터를 처리할 때는 GET 요청을 사용하면 안 됩니다
GET 요청에는 길이 제한이 있습니다
GET 요청은 데이터 검색에만 사용해야 합니다
단순 URL 예: GET 메서드
다음은 GET 메서드를 사용하여 test.cgi 프로그램에 두 개의 매개변수를 보내는 간단한 URL입니다.
/cgi-bin/test.cgi?name=php中文网&url=http://www.php.cn
다음은 test.cgi 파일의 코드입니다. :
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取文本信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } $name = $FORM{name}; $url = $FORM{url}; print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2>$name网址:$url</h2>"; print "</body>"; print "</html>"; 1;
브라우저를 보면 다음과 같이 출력됩니다.
간단한 양식 예: GET 메소드
다음은 양식입니다. HTML을 통해 GET 메소드를 사용하여 두 개의 데이터를 서버로 보냅니다. 제출된 서버 스크립트도 test.cgi 파일입니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="get"> 站点名称: <input type="text" name="name"> <br /> 站点 URL: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html>
브라우저에서 실행 효과가 나타납니다.
POST 방식을 사용하여 데이터를 전송합니다
POST 방식을 사용하여 서버에 데이터를 전송하는 것이 더 안전하고 안정적입니다. 사용자 비밀번호와 같은 일부 민감한 정보는 POST를 사용하여 데이터를 전송해야 합니다.
다음은 브라우저에서 제출한 POST 양식 데이터도 처리할 수 있는 test.cgi입니다.
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取文本信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } $name = $FORM{name}; $url = $FORM{url}; print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2>$name网址:$url</h2>"; print "</body>"; print "</html>"; 1;
다음은 GET 메서드를 사용하여 두 개의 데이터를 HTML을 통해 전송하는 양식입니다. 서버, submit 서버 스크립트도 test.cgi 파일이고, test.html 코드는
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="post"> 站点名称: <input type="text" name="name"> <br /> 站点 URL: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html>
브라우저에서 실행 효과는 다음과 같다.
CGI를 통해 프로그램은 체크박스 데이터를 전달합니다
체크박스는 하나 이상의 옵션 데이터를 제출하는 데 사용됩니다. test.html 코드는 다음과 같습니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="POST" target="_blank"> <input type="checkbox" name="php" value="on" /> php中文网 <input type="checkbox" name="google" value="on" /> Google <input type="submit" value="选择站点" /> </form> </body> </html>
다음은 다음과 같습니다. test.cgi 파일의 코드는 다음과 같습니다.
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } if( $FORM{php} ){ $php_flag ="ON"; }else{ $php_flag ="OFF"; } if( $FORM{google} ){ $google_flag ="ON"; }else{ $google_flag ="OFF"; } print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2> php中文网选中状态 : $php_flag</h2>"; print "<h2> Google 选择状态 : $google_flag</h2>"; print "</body>"; print "</html>"; 1;
브라우저에서 실행 효과는 다음과 같습니다.
CGI 프로그램을 통해 라디오 데이터 전송
라디오는 서버에만 전송합니다. 데이터를 전달하면 test.html 코드는 다음과 같습니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="post" target="_blank"> <input type="radio" name="site" value="php" /> php中文网 <input type="radio" name="site" value="google" /> Google <input type="submit" value="提交" /> </form> </body> </html>
test.cgi 스크립트 코드는 다음과 같습니다.
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } $site = $FORM{site}; print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2> 选择的网站 $site</h2>"; print "</body>"; print "</html>"; 1;
브라우저에서 실행 효과는 다음과 같습니다.
CGI 프로그램을 통해 Textarea 데이터 전송
Textarea 전송 여러 줄의 데이터를 서버에 전송하는 경우 test.html 코드는 다음과 같습니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="post" target="_blank"> <textarea name="textcontent" cols="40" rows="4"> 在这里输入内容... </textarea> <input type="submit" value="提交" /> </form> </body> </html>
test.cgi 스크립트 코드는 다음과 같습니다.
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } $text_content = $FORM{textcontent}; print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2>输入的文本内容为:$text_content</h2>"; print "</body>"; print "</html>"; 1;
브라우저에서 실행 효과는 다음과 같습니다. :
CGI 프로그램을 통해 드롭다운 데이터 전송
HTML 드롭다운 상자 코드 다음과 같습니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/test.cgi" method="post" target="_blank"> <select name="dropdown"> <option value="php" selected>php中文网</option> <option value="google">Google</option> </select> <input type="submit" value="提交"/> </form> </body> </html>
test .cgi 스크립트 코드는 다음과 같습니다:
#!/usr/bin/perl local ($buffer, @pairs, $pair, $name, $value, %FORM); # 读取信息 $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else { $buffer = $ENV{'QUERY_STRING'}; } # 读取 name/value 对信息 @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%(..)/pack("C", hex())/eg; $FORM{$name} = $value; } $site = $FORM{dropdown}; print "Content-type:text/html\r\n\r\n"; print "<html>"; print "<head>"; print '<meta charset="utf-8">'; print '<title>php中文网(php.cn)</title>'; print "</head>"; print "<body>"; print "<h2>选择的网站是:$site</h2>"; print "</body>"; print "</html>"; 1;
브라우저에서 실행 효과는 다음과 같습니다.
CGI에서 쿠키 사용
http 프로토콜의 큰 단점 단지 사용자의 신원을 판단하지 않는다는 점은 프로그래머들에게 큰 불편을 안겨줍니다. 쿠키 기능의 등장으로 이러한 단점이 보완되었습니다.
쿠키는 고객이 스크립트에 접속할 때 고객의 브라우저를 통해 고객의 하드디스크에 기록되는 데이터를 쓰는 것입니다. , 신원 식별 기능을 달성하기 위해 다음 번에 고객이 스크립트에 액세스할 때 데이터 정보가 검색됩니다. 쿠키는 신원 확인에 자주 사용됩니다.
쿠키 구문
http 쿠키는 파일 전송보다 빠른 http 헤더를 통해 전송됩니다. 헤더의 set-cookie 구문은 다음과 같습니다.
Set-cookie:name=name;expires=date;path=path;domain=domain;secure
name=name: 쿠키 값을 설정해야 합니다(name은 ";" 및 ","을 사용할 수 없음). 다수 ";"을 사용하여 이름 값을 구분합니다(예: name1=name1;name2=name2;name3=name3).
expires=date: 쿠키 유효 기간, 형식:expires="Wdy,DD-Mon-YYYY HH:MM:SS"
path=path: path가 경로인 경우 쿠키가 여기에 위치합니다. 모든 파일과 하위 디렉터리에 유효합니다(예: path="/cgi-bin/"). path가 파일인 경우 쿠키는 이 파일에 유효합니다(예: path="/cgi-bin/cookie). cgi".
domain=domain: 쿠키에 유효한 도메인 이름(예: domain="www.php.cn"
<🎜) >secure: 이 플래그가 제공되면 쿠키는 SSL 프로토콜의 https 서버를 통해서만 전달될 수 있음을 의미합니다.
- 쿠키 수신은 환경 변수 HTTP_COOKIE를 설정하여 이루어집니다. CGI 프로그램은 이 변수를 검색하여 쿠키 정보를 얻을 수 있습니다.
쿠키 설정쿠키 설정은 매우 간단합니다. 쿠키는 http 헤더에 별도로 전송됩니다. 다음 예는 쿠키에 UserID, Password 및 만료를 설정합니다.
#!/usr/bin/perl print "Set-Cookie:UserID=XYZ;\n"; print "Set-Cookie:Password=XYZ123;\n"; print "Set-Cookie:Expires=Tuesday, 31-Dec-2017 23:12:40 GMT";\n"; print "Set-Cookie:Domain=www.php.cn;\n"; print "Set-Cookie:Path=/perl;\n"; print "Content-type:text/html\r\n\r\n"; ...........其他 HTML 内容Find Cookie쿠키 정보 검색 페이지는 매우 간단합니다. 쿠키 정보는 CGI 환경 변수인 HTTP_COOKIE에 저장되며 저장 형식은 다음과 같습니다.
#!/usr/bin/perl $rcvd_cookies = $ENV{'HTTP_COOKIE'}; @cookies = split /;/, $rcvd_cookies; foreach $cookie ( @cookies ){ ($key, $val) = split(/=/, $cookie); # splits on the first =. $key =~ s/^\s+//; $val =~ s/^\s+//; $key =~ s/\s+$//; $val =~ s/\s+$//; if( $key eq "UserID" ){ $user_id = $val; }elsif($key eq "Password"){ $password = $val; } } print "User ID = $user_id\n"; print "Password = $password\n";위 예제의 출력 결과는 다음과 같습니다.
User ID = XYZ Password = XYZ123
CGI 모듈Perl은 다음 두 가지 내장 CGI 모듈을 제공합니다. 일반적으로 사용되는 모듈:
- CGI 모듈
- Berkeley cgi-lib.pl