Direktørers mobiltelefoner. CGI script filtypenavn

Introduktion.

I denne artikel vil jeg tale om CGI-grænsefladen generelt, dens implementering til Windows og brugen af ​​assemblersprog i særdeleshed ved skrivning af CGI-programmer. Det er uden for rammerne af denne artikel Fuld beskrivelse CGI, da der simpelthen er et hav af materiale om dette emne på internettet, og jeg kan simpelthen ikke se meningen med at genfortælle det hele her.

TeoriCGI.

CGI – (Common Gateway Interface) – Common Gateway Interface. Som du måske kan gætte, fungerer denne grænseflade som en gateway mellem serveren (her mener jeg serverprogrammet) og et eller andet eksternt program skrevet til det operativsystem, som netop denne server kører på. Således er CGI ansvarlig for præcis, hvordan data vil blive overført fra serverprogrammet til CGI-programmet og tilbage. Interfacet pålægger ingen begrænsninger for, hvad CGI-programmet skal skrives i; det kan enten være en almindelig eksekverbar fil eller en hvilken som helst anden fil - det vigtigste er, at serveren kan køre det (i Windows-miljøet kan det f.eks. kan være en fil med filtypenavnet knyttet til ethvert program).

Fra det øjeblik du ringede (for eksempel klikkede på en formularknap, som et CGI-programkald er knyttet til) CGI-programmet, indtil du modtager resultatet i dit browservindue, sker følgende:

En webklient (såsom en browser) opretter en forbindelse til den server, der er angivet i URL'en;

Webklienten sender en anmodning til serveren, denne anmodning foretages normalt ved hjælp af to metoder GET eller POST;

Data fra klientanmodningen (f.eks. formularfeltværdier) sendes af serveren ved hjælp af en CGI-grænseflade til det CGI-program, der er angivet i URL'en;

CGI-programmet behandler klientdataene modtaget fra serveren og genererer på baggrund af denne behandling et svar til klienten, som det transmitterer via det samme CGI-interface til serveren, og det transmitterer det igen direkte til klienten;

Serveren lukker forbindelsen med klienten.

Standard CGI-specifikationen forudsætter, at serveren kan kommunikere med programmet på følgende måder:

Miljøvariabler – de kan indstilles af serveren, når programmet starter;

Standard input stream (STDIN) - med sin hjælp kan serveren overføre data til programmet;

Standard output stream (STDOUT) – programmet kan skrive sit output ind i det, som sendes til serveren;

Kommandolinje – i den kan serveren videregive nogle parametre til programmet.

Standard input/output streams er meget praktiske og udbredt på UNIX-systemer, hvilket ikke kan siges om Windows, så der er en CGI-specifikation udviklet specifikt til Windows-systemer, kaldet "Windows CGI". Men selvfølgelig kan standard input/output streams også bruges i Windows CGI programmering. Her vil jeg ikke berøre "Windows CGI"-standarden, og der er mindst to grunde til dette - den første og vigtigste er, at i øjeblikket ikke alle http-servere til Windows understøtter denne specifikation (især min favorit Apache 1.3.19). Du kan se den anden grund ved at indtaste en hvilken som helst søgemaskine linje "Windows CGI". Jeg vil kun bemærke generelle detaljer vedrørende denne grænseflade - alle data fra serveren til klienten overføres ved hjælp af det sædvanlige Windows *. ini fil, hvis navn sendes til programmet på kommandolinjen. I dette tilfælde er alle data i filen allerede omhyggeligt opdelt i sektioner af serveren, og alt du skal gøre er at bruge "GetPrivateProfile*"-funktionerne til at udtrække dem derfra. Svaret sendes til serveren igen via en fil, hvis navn er angivet i den tilsvarende post i ini-filen.

Hvilke data kan overføres af klienten til CGI-programmet? - næsten alle. Generelt sendes programmet værdierne af formularfelterne, som klienten udfylder, men det kan også være en slags binær data, for eksempel en fil med et billede eller musik. Data kan overføres til serveren ved to forskellige metoder - GET-metoden og POST-metoden. Når vi opretter en formular, der skal udfyldes på vores side, angiver vi eksplicit, hvilken af ​​de givne metoder, vi ønsker at sende de data, som brugeren har indtastet, dette gøres i formularens hovedtag noget som dette:

få action="/cgi-bin/navn_script">

Når der sendes data ved hjælp af GET-metoden, læser browseren dataene fra formularen og placerer dem efter script-URL'en efterfulgt af et spørgsmålstegn; hvis der er flere væsentlige felter i formularen, sendes de alle gennem "&" tegnet, feltnavnet og dets værdi skrives i URL'en gennem "=" tegnet " For eksempel en anmodning genereret af en browser fra en formular, når du klikker på en knap, hvortil scriptet "/cgi-bin/test.exe" er knyttet, idet det tages i betragtning, at det første felt i formularen hedder "dit_navn" , den anden – “din_alder”, kan se sådan ud:

GET /cgi-bin/test.exe?dit_navn=Pupkin&your_age=90 HTTP/1.0

At bruge GET metoden har flere svagheder – den første og vigtigste er pga Dataene transmitteres i URL'en, så har den en grænse for mængden af ​​disse transmitterede data. Den anden svaghed følger igen af ​​URL'en - dette er fortrolighed, med en sådan overførsel forbliver dataene absolut åbne. Så det er godt, hvis vi har 2-3 små felter i formularen ... spørgsmålet opstår, hvad skal man gøre, hvis der er flere data? Svaret er at bruge POST-metoden!

Ved brug af metoden POST data overføres til serveren som en datablok og ikke i en URL, hvilket i nogen grad frigør vores hænder til at øge lydstyrken overførte oplysninger, for ovenstående POST-formeksempel vil blokeringen, der sendes til serveren, være sådan her:

POST /cgi-bin/test.exe HTTP/1.0

Accepter: tekst/almindelig

Accepter: tekst/html

Acceptere: */*

Indholdstype: application/x-www-form-urlencoded

Indholdslængde: 36

your_name=Pupkin&your_age=90

Som nævnt ovenfor, efter at have modtaget dataene, skal serveren transformere dem og transmittere dem CGI-program. I standard CGI-specifikationen placeres klientinput for en GET-anmodning af serveren i programmets miljøvariabel "QUERY_STRING". På POST anmodning Dataene placeres på applikationens standard inputstrøm, hvorfra de kan læses af den. Derudover sætter serveren med en sådan anmodning yderligere to miljøvariabler - CONTENT_LENGTH og CONTENT_TYPE, som man kan bedømme længden af ​​anmodningen i bytes og dens indhold.

Ud over selve dataene sætter serveren også andre miljøvariabler for det kaldte program; her er nogle af dem:

REQUEST_METHOD

Beskriver præcis, hvordan dataene er opnået

Eksempel:REQUEST_METHOD=FÅ

QUERY_STRING

Forespørgselsstreng, hvis GET-metoden blev brugt

Eksempel:QUERY_STRING= dit_navn=Hvalpe&din_alder=90&hobby=asm

CONTENT_LENGTH

Længde i bytes af anmodningsteksten

Eksempel:CONTENT_LENGTH=31

INDHOLDSTYPE

Anmod om kropstype

GATEWAY_INTERFACE

CGI protokol version

Eksempel:GATEWAY_ GRÆNSEFLADE= CGI/1.1

REMOTE_ADDR

IP-adressen på den eksterne vært, det vil sige den klient, der klikkede på knappen i formularen

Eksempel: REMOTE_ADDR=10.21.23.10

REMOTE_HOST

Navnet på fjernværten, dette kan være dens domænenavn eller for eksempel computernavnet i Windows miljø, hvis de ikke kan modtages, så indeholder feltet sin IP

Eksempel:REMOTE_HOST=wasm.ru

SCRIPT_NAME

Navnet på det script, der blev brugt i anmodningen.

Eksempel:SCRIPT_NAME=/cgi-bin/gols.pl

SCRIPT_FILENAME

Navnet på scriptfilen på serveren.

Eksempel:SCRIPT_FILENAME=c:/page/cgi-bin/gols.pl

SERVER _ SOFTWARE

Server software

Eksempel: Apache/1.3.19 (VINDE32)

Generelt er dette alt i korte træk, for mere detaljeret information om Common Gateway Interface, se den specialiserede dokumentation, jeg lavede denne beskrivelse for at minde dig om, og hvis du ikke vidste det, så hold dig opdateret. Lad os prøve at gøre noget i praksis.

Praktisk del.

Til praksis har vi brug for mindst 3 ting - en slags http-server til Windows, jeg prøvede alle eksemplerne på Apache 1.3.19 til Windows, serveren er gratis, du kan downloade den fra http://httpd.apache. org/download.cgi . Ja, og vi skal bruge en server, ikke en hvilken som helst server, men en, der er konfigureret til at køre CGI-scripts! Se dokumentationen for, hvordan du gør dette for den server, du bruger. Den anden ting, vi har brug for, er selvfølgelig en assembler; det er også nødvendigt, at compileren understøtter oprettelsen af ​​WIN32-konsolapplikationer, jeg bruger Tasm, men Fasm og Masm og mange andre *asms er perfekte. Og endelig er det vigtigste, at dette ønske er påkrævet.

Så jeg antager, at serveren blev installeret og konfigureret med succes af dig, så der i serverdokumenternes rodbibliotek er en index.html-fil, som vises perfekt i browseren, når du skriver adressen http://127.0 .0.1. Jeg vil også tage højde for, at der et sted i junglen af ​​servermapper er en "cgi-bin"-mappe, hvori scripts må køre.

Lad os tjekke serverindstillingerne, og samtidig skrive et lille script. Vores script vil være en almindelig *.bat fil. Jeg forudser spørgsmål - hvordan? virkelig? Ja, det er normalt batch-fil, som nævnt ovenfor, skelner CGI-specifikationen ikke mellem filtyper, det vigtigste er, at serveren kan køre den, og den har til gengæld adgang til stdin/stdout og miljøvariabler, en bat-fil, omend ikke fuldt ud, men det vil for eksempel passe os ret godt. Lad os oprette en fil med omtrent følgende indhold:

@echo off rem Anmod om header echo Indholdstype: text/html echo. rem Request body echo " Hej!
ekko "Med FÅ anmodning modtagne data: %QUERY_STRING%

Lad os kalde filen test.bat og placere den i mappen til at køre scripts, højst sandsynligt vil det være mappen "cgi-bin". Den næste ting vi skal gøre er at kalde dette script på en eller anden måde, i princippet kan dette gøres direkte ved at skrive noget i stil med følgende "http://127.0.0.1/cgi-bin/test.bat" i browseradressen vindue, men lad os kalde det fra vores hovedside, og samtidig kontrollere GET-metodens funktion. Lad os oprette en fil index.html i serverroden med følgende indhold:

Indtast de data, der skal overføres til serveren:
Data:

Nu, når du går ind på serveren (http://127.0.0.1 i browserens adresselinje), skal der vises en formular, skriv noget i den og klik på knappen "send", hvis alt blev gjort korrekt, vil du se svaret fra vores bat- i browservinduets script. Lad os nu se, hvad vi nåede frem til der.

Som du måske kan gætte, udsender "echo"-kommandoen til stdout; først og fremmest sender vi headeren af ​​vores svar til serveren - "echo Content-type: text/html". Dette er en standard CGI-specifikationsheader, der indikerer, at vi ønsker at overføre tekst eller et html-dokument; der er andre overskrifter. Meget vigtigt punkt– titel skal adskilt fra svarorganet tom linje, hvilket vi gør med følgende kommando "echo.". Dernæst sendes selve svarets brødtekst - dette er et almindeligt html-dokument. I dokumentets brødtekst viser jeg for klarhedens skyld en af ​​miljøvariablerne sendt til os af serveren - "QUERY_STRING", som allerede nævnt med GET-metoden (og det er præcis vores tilfælde), overføres alt i denne variable brugerindtastede data, som vi kan observere i script-svaret. Du har måske bemærket "anførselstegnene er malplacerede" i de sidste 2 linjer i filen, umiddelbart efter "ekko", de er der på grund af bat-filernes specificitet, da du kan se html-tags er omgivet af tegn "<» и «>", samtidig fungerer disse symboler som input/output omdirigering i bat-filer, og derfor kan vi ikke frit bruge dem her.

Jeg anbefaler at lege lidt med sådanne bat-scripts, det kan være meget nyttigt, prøv at se på andre miljøvariabler. Jeg vil sige lidt, afvigende fra emnet, på UNIX-systemer er kommandofortolkersprog meget højt udviklede, og grænsen mellem programmering i et kommandofortolkersprog og programmering i et "rigtigt" programmeringssprog er meget, meget sløret i nogle tilfælde, så simple scripts er ofte skrevet på UNIX-systemer specifikt i kommandofortolkersprog, men Windows-fortolkeren cmd.exe eller, tidligere, command.com er tydeligvis svage til disse formål.

Lad os nu gå videre til det faktiske hovedopgave i denne artikel, til faktisk at skrive et CGI-program i assembler. I princippet, hvis vi tager højde for alt ovenstående om CGI, kan vi drage en konklusion om, hvad CGI-grænsefladen kræver af vores program:

2. Programmet skal være i stand til at skrive til standardoutputstrømmen (stdout) for at kunne overføre resultatet af sit arbejde til serveren;

3. Af de to første punkter følger det, at for at serveren kan sende noget til vores program i stdin, og for at den kan reagere på det i stdout, skal CGI-programmet være en konsolapplikation;

Dette er ganske nok til at skabe en fuldgyldig CGI-applikation.

Lad os starte med det sidste punkt. For at få adgang til miljøvariablerne i en Windows-applikation, bruges API-funktionen "GetEnvironmentStrings", funktionen har ingen argumenter og returnerer en pointer til et array af miljøvariabler (NAME=VALUE) adskilt af nul, arrayet lukkes med et dobbelt nul, når programmet startes af serveren i programmiljøet udover standardvariabler, tilføjes de specifikke CGI-variabler beskrevet ovenfor, når programmet køres fra kommandolinje du vil naturligvis ikke se dem.

For at skrive noget til stdout eller læse fra stdin, skal vi først have håndtagene til disse streams, dette gøres ved hjælp af API-funktionen "GetStdHandle", en af ​​følgende værdier sendes som en funktionsparameter:

STD_INPUT_HANDLE - for stdin (standard input);

STD_OUTPUT_HANDLE - for stdout (standard output);

STD_ERROR_HANDLE - for stderr.

Funktionen returnerer det håndtag, vi har brug for til læse-/skriveoperationer. Den næste ting vi skal gøre er at skrive/læse disse streams. Dette gøres ved normale fillæse/skriveoperationer, dvs. ReadFile og WriteFile. Der er en subtilitet her, du tror måske, at WriteConsole/ReadConsole kan bruges til disse formål, men dette er faktisk sandt for konsoller og det vil fungere fantastisk, resultaterne, ligesom med WriteFile, vil blive udsendt til konsollen, men dette vil fortsætte indtil vi kører vores program som et script på serveren. Dette sker, fordi når vores program startes af serveren, vil de håndtag, der returneres af "GetStdHandle"-funktionen, ikke længere være konsolhåndtag som sådan, de vil være rørhåndtag, hvilket er nødvendigt for at forbinde to applikationer.

Her er et lille eksempel på, hvordan et CGI-program skal se ud i assemblersprog; Jeg tror, ​​det ikke vil være for svært at finde ud af det:>

386 .model flat,stdcall includelib import32.lib .const PAGE_READWRITE = 4h MEM_COMMIT = 1000h MEM_RESERVE = 2000h STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE = -11 .data hStdout ? hStdin dd ? hMem dd ? header: db "Content-Type: text/html",13,10,13,10,0 start_html: db " CGI-programmiljøet ser sådan ud:
",13,10,0 for_stdin: db " Programmets STDIN indeholder:
",13,10,0 end_html: db "",13,10,0 nwritten dd ? toscr db 10 dup (32) db " - Filtype",0 .code _start: xor ebx,ebx call GetStdHandle,STD_OUTPUT_HANDLE mov hStdout,eax call GetStdHandle,StHAND_INPmov call h_DIN,INPmov write_stdout, offset header call write_stdout, offset start_html call VirtualAlloc,ebx,1000,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE mov hMem,eax mov edi,eax call GetEnvironmentStringsA mov esi,eax next_symbol, mov al_, mov al, mov al_ : cmpsb jmp kort næste_symbol end_string: mov ,">rb<" add edi,3 cmp byte ptr ,0 jnz next_string inc edi stosb call write_stdout, hMem call write_stdout, offset for_stdin call GetFileSize,,ebx mov edi,hMem call ReadFile,,edi, eax,offset nwritten, ebx add edi, mov byte ptr ,0 call write_stdout, hMem call write_stdout, offset end_html call VirtualFree,hMem call ExitProcess,-1 write_stdout proc bufOffs:dword call lstrlen,bufOffs call WriteFile,,bufOffs,eax,offset nwritten,0 ret write_stdout endp extrn GetEnvironmentStringsA:near extrn GetStdHandle:near extrn ReadFile:near extrn WriteFile:near extrn GetFileSize:near extrn VirtualAlloc:near extrn VirtualFree:near extrn ExitProcess:near extrn lstrlen:near ends end _start

Den eksekverbare fil er bygget med kommandoerne:

tasm32.exe /ml test.asm

tlink32.exe /Tpe /ap /o test.obj

Glem ikke, at programmet skal være et konsolprogram.

Arkiver med programmet.

Du kan kalde dette program ved hjælp af html-formularen beskrevet ovenfor, du skal bare ændre navnet test.bat i formularen til test.exe og kopiere det til /cgi-bin/ tilsvarende, du kan indstille det til POST i anmodningsmetoden , behandler programmet det.

Jeg vil også bemærke, at du kan kalde programmet på en anden måde, du kan oprette en fil i cgi-bin biblioteket, for eksempel test.cgi, med en enkelt linje "#!c:/_path_/test.exe" og kalder det ind forespørgsler, og serveren vil til gengæld læse sin første linje og starte exe-filen; for dette er det nødvendigt, at *.cgi-udvidelsen angives i http-serverindstillingerne som en udvidelse til scripts. Med denne tilgang vil serveren starte vores program med kommandolinjen "test.exe path_to_test.exe", dette har flere fordele - den første er, at den person, der kører vores script, ikke engang vil gætte, hvad scriptet er skrevet i, det andet er måden det sendes til os navnet på filen med vores linje, kan vi f.eks. tilføje alle indstillinger for vores script til denne fil, hvilket forenkler fejlfinding, i øvrigt er det sådan alle tolke fungerer - du kan have bemærket, at der i alle perl/php/etc-programmer er en lignende linje - hvilket indikerer selve kommandofortolkeren. Så når serveren starter et cgi-program, hvis programudvidelsen er registreret som et script i indstillingerne, læser den den første linje i filen, og hvis den viser sig at være i formatet beskrevet ovenfor, starter den programmet angivet i linjen med navnet på denne fil efterfulgt af et mellemrum, lad os sige, at i Perletolken er angivet i linjen; efter at have modtaget en sådan gave, begynder den udførelsen, fordi Kommentaren i Perl er "#" symbolet, så springer den første linje over, og scriptet fortsætter med at blive udført, generelt er det en praktisk ting.

Det er dybest set alt, jeg ville skrive om, jeg ved ikke, hvor nyttigt alt dette vil være for dig, men jeg vil sige, at jeg har en intranetserver, der kører ved hjælp af assembler-scripts. Jeg indrømmer, at der ikke var nogen god grund til at gøre dette, men ikke desto mindre gjorde jeg det i starten blot af æstetiske årsager og en vis modvilje mod at lære pearl/php eller noget andet. MEN jeg afskrækker dig på ingen måde fra at lære Pearl, men tværtimod vil jeg sige, at det er nødvendigt at gøre dette, og endda meget nødvendigt, det indså jeg senere, men jeg tror stadig, at på tungt belastede servere, hvor hastigheden af ​​udførelse, indlæsning og mængden af ​​hukommelse optaget af applikationen spiller en rolle cgi-scripts skrevet i assembler vil tage deres retmæssige plads.

Når en bruger udfylder en html-formular og klikker på send, sendes dataene til webserveren. Webserveren, det være sig Apache, IIS eller en anden, kører det program, der er angivet som værdien af ​​handlingsattributten. I vores tilfælde er dette test.cgi. Webserveren kører test.cgi og sender dens parametre i form af en tekststreng med følgende indhold: navn1=værdi1&navn2=værdi2&....navnN=værdiN, dvs. parameter_name=værdi. Denne streng sendes til standardinput (STDIN) eller som værdien af ​​miljøvariablen QUERY_STRING. Følgelig kan denne linje læses i programmet på en af ​​to måder:

I det første tilfælde overføres parametre ved hjælp af POST-metoden, og i det andet ved hjælp af GET-metoden. I det første tilfælde læser vi strengen fra STDIN. Vi finder ud af længden af ​​linjen ud fra værdien af ​​miljøparameteren CONTENT_LENGTH. I den anden er den gemt i miljøvariablen QUERY_STRING. Værdien af ​​en miljøvariabel kan fås ved at kalde funktionen getenv. Metoden, hvorved en streng af parametre sendes til et CGI-program, kan defineres som følger: strcmp(getenv("REQUEST_METHOD"),"POST"). Dernæst skal du parse strengen og få de nødvendige parameterværdier. For ikke at skulle gøre dette hver gang, skrev vi et lille, men meget praktisk ITCGI-bibliotek til at skrive CGI-scripts. Dette bibliotek giver dig mulighed for fuldstændig at abstrahere fra metoden, hvormed parametre sendes, fra kodningen, fra parsing af strengen. Du kalder blot funktionen GetParamByName, hvortil du sender navnet på den parameter, du er interesseret i, og adressen på linjen, hvor værdien skal gemmes. Biblioteket giver dig også en række funktioner til at skrive effektive og manipulationssikre CGI-scripts.
I det enkleste tilfælde, når dit program ikke har brug for parametre, behøver du ikke selv at parse og afkode strengen, og heller ikke bruge vores bibliotek til dette. Det enkleste CGI-program ville være: Titlen er en obligatorisk del. Den sendes videre til webserveren og bestemmer, hvad der følger efter den. I de fleste tilfælde er det, hvad din titel vil være. Den fortæller webserveren, hvilken HTML-kode der kommer næste gang. Vi lærer andre typer overskrifter at kende lidt senere. Titlen kan indeholde flere linjer. Slutningen af ​​overskriften er angivet med to nye linjer - \n\n. Kompiler dette program og placer den eksekverbare fil i mappen /cgi-bin på dit websted. Omdøb den til test.cgi. Dette script kan tilgås direkte gennem en browser ved at skrive URL'en på kommandolinjen, for mig ser det for eksempel sådan ud http://site/cgi-bin/test.cgi Som et resultat vil du i din browser se linjen: "Hej, verden!".
Dernæst vil vi se på et CGI-program af samme type. Det accepterer ingen parametre, men det producerer mere nyttig information - en liste og værdier af alle miljøvariabler. Dette script vil være nyttigt, når du fejlretter dine CGI-programmer på forskellige webservere. Faktum er, at miljøvariabler er forskellige på forskellige webservere. Så for eksempel, for Apache-webserveren, er stien til webstedsbiblioteket gemt i miljøvariablen DOCUMENT_ROOT. For Microsoft Internet Information Server-webserveren er denne værdi gemt i PATH_TRANSLATED-variablen. På UNIX-operativsystemet er scriptet til at vise alle variabler som følger.
#!/bin/sh echo "content-type: text/plain\n\n" echo env
Bemærk CGI-titlen. Det er anderledes end det, vi havde i det foregående eksempel. plain betyder, at scriptet ikke udsender HTML-kode, men ren tekst. Browseren vil behandle den som normal tekst og vise den præcis, som den er. Der er ingen grund til at erstatte specialtegn som f.eks< на их эквиваленты <. Скопируйте этот скрипт в директорию /cgi-bin с именем env. Установите атрибут 755 (rwxr-xr-x). Вот результат выполнения такого скрипта на моем unix-сервере:
GATEWAY_INTERFACE=CGI/1.1 REMOTE_USER=itsoft REMOTE_ADDR=192.168.34.134 QUERY_STRING= REMOTE_PORT=1781 HTTP_USER_AGENT=Mozilla/4.0 (kompatibel; MSIE 5.0; Windows 98=wwwDOUS_AUTH/locit) Grundlæggende SERVER_SIGNATURE=
Apache/1.3.12 Server hos itsoft..3.12 (Unix) PHP/3.0.17 HTTP_CONNECTION=Keep-Alive HTTP_COOKIE=/cgi-bin/authenticate.cgi_LAST=956345778 PATH=/sbin:/usr/sbin:/bin:/ usr/bin:/usr/local/sbin: /usr/local/bin:/usr/X11R6/bin HTTP_ACCEPT_LANGUAGE=ru SERVER_PROTOCOL=HTTP/1..226.32.34 SERVER_PORT=80 SCRIPT_NAME=/cgi-bin/web/env SERVER_NAME=websted
C-programmet til Windows og Internet Information Server-webserveren vil se sådan ud:
#omfatte #omfatte void main() ( char *text; char str; int længde; FILE *in; sprintf(str,"command.com /c set>%s\\temp\\env.dmp",getenv("PATH_TRANSLATED")) ; system(str); sprintf(str,"%s\\temp\\env.dmp",getenv("PATH_TRANSLATED")); in = fopen(str, "rb"); if(!in) ( printf( "Indholdstype: text/plain\n\nKan ikke åbne filen %s.", str); return; ) fseek(in, 0, SEEK_END); length = ftell(in); fseek(in, 0, SEEK_SET ); text = (char*)malloc(længde+1); fread(tekst, 1, længde, in); text = 0; fclose(in); printf("Indholdstype: tekst/plain\n\n% s", tekst); fri(tekst); )
Kør først kommandoen command.com /c set>c:\www\mysite\temp\env.dmp. Resultatet af at udføre en sådan kommando vil være en liste over alle miljøvariabler, som derefter gemmes i en fil. Dernæst læser vi denne fil og returnerer dens indhold til webserveren. Du vil måske bemærke, at vi i dette tilfælde, som i det foregående eksempel, ikke udskriver html-kode, men ren tekst, og derfor har vi titlen: Content-type: text/plain. Glem ikke også, at dette cgi-script kun vil fungere under Internet Information Server. For Apache-webserveren skal du erstatte getenv("PATH_TRANSLATED") med getenv("DOCUMENT_ROOT").
Nedenfor er outputtet af dette script på WindowsNT, du kan se hvor mange parametre der er tilgængelige via miljøvariabler. Sådan et cgi-script vil være nyttigt for dig, når du opsætter dine scripts på en andens server, hvor miljøvariablerne kan afvige fra dine lokale. COMSPEC=C:\WINNT\SYSTEM32\COMMAND.COM COMPUTERNAME=JUPITER CONTENT_LENGTH=0 GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint , application/vnd.ms-excel, appliceret HTTP_ACCEPT_LANGUAGE=ru HTTP_CONNECTION=Keep-Alive HTTP_HOST=www.oxygensoftware.com HTTP_USER_AGENT=Mozilla/4.0 (kompatibel; MSIE 5.01; Windows NT 5.0) INC HTTP_ACCEPT_ENCODING=g C:\Program Files\Mts\Include INSTANCE_ID=1410 LIB=C:\Program Files\Mts\Lib LOCAL_ADDR=168.144.29.178 NUMBER_OF_PROCESSORS=2 OS2LIBPATH=C:\WINNT\system32\os2\dll; OS=Windows_NT PATH=C:\WINNT\system32;C:\WINNT;C:\Program Files\Mts PATH_TRANSLATED=e:\InetPub\Clients\oxygensoftware.com PATHEXT=.COM;.EXE;.BAT;.CMD; .VBS;.JS;.VBE;.JSE;.WSF;.WSH PROCESSOR_ARCHITECTURE=x86 PROCESSOR_IDENTIFIER=x86 Familie 6 Model 5 Trin 1, GenuineIntel PROCESSOR_LEVEL=6 PROCESSOR_REVISION=0501$GEMÆRKNING REMOTE3.4PADG MO.4.2$3.4PADG REMOTE3.6$ _VÆRT = 194.226.32.34 REQUEST_METHOD=HENT SCRIPT_NAME=/cgi-bin/env.exe SERVER_NAME=www.oxygensoftware.com SERVER_PORT=80 SERVER_PORT_SECURE=0 SERVER_PROTOCOL=HTTP/1.1 SERVER_SOFTWARESYSTEM=Microsoft-DRIICSYSTEM=Microsoft-0IICSYSTEM=Microsoft-0 :\ WINNT TEMP=C:\temp. der producerer en linje i html-formularparametre. Læs ovenfor om, hvordan formularparametrene læses; her giver jeg kildekoden til programmet og dets resultat for html-formularen beskrevet i fjerde kapitel.
#omfatte #omfatte void main() ( char* query=NULL; if(!strcmp(getenv("REQUEST_METHOD"),"POST")) (usigneret int len; len = atoi(getenv("CONTENT_LENGTH")); query = (char* )malloc(len+1); fread(query, 1, len, stdin); query = 0; ) else if(!strcmp(getenv("REQUEST_METHOD"),"GET")) ( query=(char*)malloc (strlen(getenv("QUERY_STRING"))); strcpy(query,getenv("QUERY_STRING")); ) else printf("ukendt REQUEST_METHOD\n"); printf("Indholdstype: text/plain\n\n %s", forespørgsel); gratis(forespørgsel); )
Kompiler denne kode. Det er platformsuafhængigt, så du kan kompilere det under både Unix og Windows. Tag HTML-formularen fra det fjerde kapitel, du kan tage en hvilken som helst anden. I handlingsfeltet skal du indtaste stien til dette program på din webserver. Resultat efter at have klikket på knappen "Udgiv":
text=nul&text=nul&list=0&list2=0&textarea=%C7%E4%E5%F1%FC+%F2%E5%EA%F1%F2+%EF%EE+%F3%EC%EE%EB%F7%E0%ED%E8 %FE

Dette er en streng, der indeholder en liste over alle parametre. Dernæst kan du bruge vores ITCGI-bibliotek eller selv analysere denne streng af parametre. Læs om biblioteket og dets praktiske anvendelse i næste afsnit.

  • Tutorial

God eftermiddag.
I denne artikel vil jeg gerne tale om FastCGI-protokollen og hvordan man arbejder med den. På trods af at selve protokollen og dens implementering dukkede op tilbage i 1996, er der simpelthen ingen detaljerede manualer til denne protokol - udviklerne skrev aldrig hjælp til deres eget bibliotek. Men for to år siden, da jeg lige begyndte at bruge denne protokol, hørte jeg ofte sætninger som "Jeg forstår ikke helt, hvordan man bruger dette bibliotek." Det er denne mangel, jeg vil rette - at skrive en detaljeret guide til at bruge denne protokol i et multi-threaded program og anbefalinger til valg af forskellige parametre, som enhver kunne bruge.

Den gode nyhed er, at metoden til indkodning af data i FastCGI og i CGI er den samme, kun metoden til at overføre dem ændres: Hvis et CGI-program bruger standard input-output-grænsefladen, så bruger et FastCGI-program sockets. Du skal med andre ord bare forstå nogle få funktioner i biblioteket for at arbejde med FastCGI, og så bare bruge erfaringen med at skrive CGI-programmer, som der heldigvis er rigtig mange eksempler på.

Så i denne artikel vil vi se på:
- Hvad er FastCGI, og hvordan adskiller det sig fra CGI-protokollen
- Hvorfor har jeg brug for FastCGI, når der allerede er mange sprog til webudvikling
- Hvilke implementeringer af FastCGI-protokollen findes?
- Hvad er stikkontakter
- Beskrivelse af FastCGI-bibliotekets funktioner
- Et simpelt eksempel på et multi-threaded FastCGI-program
- Enkelt Nginx-konfigurationseksempel
Desværre er det meget svært at skrive en artikel, der er lige så forståelig for begyndere som interessant for erfarne oldtimere, så jeg vil forsøge at dække alle punkterne så detaljeret som muligt, og du kan simpelthen springe over afsnit, der ikke er interessante til dig.

Hvad er FastCGI?

Du kan læse om FastCGI på Wikipedia. I en nøddeskal er det et CGI-program, der kører i en løkke. Hvis et almindeligt CGI-program genstartes for hver ny anmodning, bruger et FastCGI-program en kø af anmodninger, der behandles sekventielt. Forestil dig nu: din 4-8 kerneserver modtog 300-500 samtidige anmodninger. Et typisk CGI-program vil køre de samme 300-500 gange. Det er klart, at der er for mange processer - din server er fysisk ude af stand til at behandle dem alle på én gang. Det betyder, at du vil ende med en kø af processer, der venter på deres processortidsudsnit. Typisk vil planlæggeren fordele processoren jævnt (så ind I dette tilfælde prioriteterne for alle processer er de samme), hvilket betyder, at du vil have 300-500 "næsten klar" svar på anmodninger. Det lyder ikke særlig optimistisk, gør det? I FastCGI-programmet løses alle disse problemer ved en simpel anmodningskø (det vil sige, at anmodningsmultipleksing bruges).

Hvorfor har jeg brug for FastCGI, når jeg allerede har PHP, Ruby, Python, Perl osv.?

Måske er hovedårsagen, at et kompileret program vil køre hurtigere end et fortolket. For PHP er der for eksempel en hel række af acceleratorer, herunder APC, eAccelerator, XCache, som reducerer tiden for kodefortolkning. Men for C/C++ er alt dette simpelthen ikke nødvendigt.
Den anden ting du skal huske er dynamisk skrivning og skraldemanden fylder mange ressourcer. Nogle gange - meget. For eksempel optager heltalsarrays i PHP omkring 18 gange mere hukommelse (op til 35 gange afhængigt af forskellige PHP-kompileringsmuligheder) end i C/C++ for den samme mængde data, så tænk på overheaden for relativt store datastrukturer.
For det tredje kan et FastCGI-program gemme data, der er fælles for forskellige anmodninger. For eksempel, hvis PHP begynder at behandle en anmodning fra bunden hver gang, så kan FastCGI-programmet udføre en række forberedende handlinger, allerede inden den første anmodning ankommer, for eksempel allokere hukommelse, indlæse ofte brugte data osv. - selvfølgelig kan alt dette stige overordnet ydelse systemer.
For det fjerde er skalerbarhed. Hvis mod_php antager, at Apache-webserveren og PHP er på samme maskine, så kan FastCGI-applikationen bruge TCP-sockets. Du kan med andre ord have en hel klynge af flere maskiner, hvormed kommunikationen foregår over netværket. Samtidig understøtter FastCGI også Unix-domæne-sockets, som giver dig mulighed for effektivt at køre en FastCGI-applikation og en webserver på samme maskine, hvis det er nødvendigt.
For det femte - sikkerhed. Tro det eller ej, med standardindstillinger giver Apache dig mulighed for at gøre alt under solen. For eksempel, hvis en angriber uploader et ondsindet script exploit.php.jpg til et websted under dække af et "uskyldigt billede" og derefter åbner det i browseren, vil Apache "ærligt" udføre den ondsindede PHP-kode. Måske er den eneste ret pålidelige løsning at fjerne eller ændre alle potentielt farlige udvidelser fra navnene på downloadede filer, i dette tilfælde - php, php4, php5, phtml osv. Denne teknik bruges for eksempel i Drupal - en understregning føjes til alle "yderligere" udvidelser og resultatet er exploit.php_.jpg. Det skal bemærkes, at Systemadministrator kan tilføje hvad som helst yderligere udvidelse fil som PHP-handler, så noget .html kunne pludselig blive til et frygteligt sikkerhedshul, bare fordi .php så grimt ud, var dårligt for SEO, eller kunden ikke kunne lide. Så hvad giver FastCGI os med hensyn til sikkerhed? For det første, hvis du bruger Nginx-webserveren i stedet for Apache, vil den simpelthen tjene statiske filer. Prik. Med andre ord vil exploit.php.jpg-filen blive serveret "som den er", uden nogen form for behandling på serversiden, så det vil simpelthen ikke være muligt at køre et ondsindet script. For det andet kan FastCGI-programmet og webserveren arbejde under forskellige brugere, hvilket betyder, at de vil have forskellige rettigheder til filer og mapper. For eksempel kan en webserver kun læse downloadede filer - dette er nok til at returnere statiske data, og et FastCGI-program kan kun læse og ændre indholdet af mappen med downloadede filer - dette er nok til at downloade nye og slette gamle filer, men adgang direkte til de downloadede filer selv vil ikke have det, hvilket betyder, at det heller ikke vil være i stand til at udføre ondsindet kode. For det tredje kan et FastCGI-program køre i en chroot, der er forskellig fra chroot på webserveren. Chroot selv (ændring af rodmappen) giver dig mulighed for i høj grad at begrænse rettighederne til et program, det vil sige øge systemets overordnede sikkerhed, fordi programmet simpelthen ikke vil være i stand til at få adgang til filer uden for den angivne mappe.

Hvilken webserver med FastCGI-understøttelse er bedre at vælge?

Kort sagt, jeg bruger Nginx. Generelt er der en hel del servere, der understøtter FastCGI, inklusive kommercielle, så lad os overveje flere alternativer.
Apache er måske det første, der kommer til at tænke på, selvom det bruger meget flere ressourcer end Nginx. For eksempel, for 10.000 inaktive HTTP Keep-alive-forbindelser, bruger Nginx omkring 2,5 M hukommelse, hvilket er ret realistisk selv for en relativt svag maskine, og Apache er tvunget til at oprette en ny tråd for hver ny forbindelse, så 10.000 tråde er simpelthen fantastisk.
Lighttpd - Den største ulempe ved denne webserver er, at den behandler alle anmodninger i en tråd. Det betyder, at der kan være problemer med skalerbarheden – du vil simpelthen ikke kunne bruge alle 4-8 kerner af moderne processorer. Og for det andet, hvis webservertråden af ​​en eller anden grund fryser (for eksempel på grund af lang ventetid på et svar fra harddisken), fryser hele din server. Med andre ord vil alle andre klienter stoppe med at modtage svar på grund af en langsom anmodning.
En anden kandidat er Cherokee. Ifølge udviklerne virker det i nogle tilfælde hurtigere end Nginx og Lighttpd.

Hvilke implementeringer af FastCGI-protokollen er der?

I øjeblikket er der to implementeringer af FastCGI-protokollen - libfcgi.lib-biblioteket fra skaberne af FastCGI-protokollen og Fastcgi++ - et C++-klassebibliotek. Libfcgi er blevet udviklet siden 1996 og er ifølge Open Market meget stabil og mere udbredt, så vi vil bruge det i denne artikel. Jeg vil gerne bemærke, at biblioteket er skrevet i C, den indbyggede C++ "wrapper" kan ikke kaldes på højt niveau, så vi vil bruge C-grænsefladen.
Jeg synes, det nytter ikke at stoppe med at installere selve biblioteket - det har en makefile, så der burde ikke være nogen problemer. Derudover er dette bibliotek tilgængeligt fra pakker i populære distributioner.

Hvad er stikkontakter?

Et generelt koncept for stikkontakter kan fås fra Wikipedia. I en nøddeskal er sockets en metode til interproceskommunikation.
Som vi husker, bruger hver proces i alle moderne operativsystemer sit eget adresseområde. Operativsystemkernen er ansvarlig for direkte adgang til RAM, og hvis et program tilgår en hukommelsesadresse, der ikke eksisterer (i sammenhæng med et givet program), vil kernen returnere en segmenteringsfejl og lukke programmet. Det er vidunderligt - nu kan fejl i ét program simpelthen ikke skade andre - de er ligesom i andre dimensioner. Men da programmerne har forskellige adresserum, kan der heller ikke være delt data eller dataudveksling. Men hvad hvis du virkelig har brug for at overføre data fra et program til et andet? Faktisk blev sockets udviklet til at løse dette problem - to eller flere processer (læs: programmer) forbindes til den samme socket og begynder at udveksle data. Det viser sig at være en slags "vindue" til en anden verden - gennem det kan du modtage og sende data til andre strømme.
Afhængigt af den anvendte forbindelsestype er stikkontakter forskellige. For eksempel er der TCP-stik - de bruger almindeligt netværk til dataudveksling, det vil sige, at programmer kan køre på forskellige computere. Den næstmest almindelige mulighed - Unix domæne sockets - er egnet til kun at udveksle data inden for én maskine og ligner en almindelig sti i filsystem, men harddisken bruges faktisk ikke - al dataudveksling foregår i RAM. På grund af det faktum, at der ikke er behov for at bruge en netværksstack, er de lidt hurtigere (ca. 10%) end TCP-sockets. Til OS Windows givet muffevarianten kaldes et navngivet rør.
Eksempler på brug af sockets til GNU/Linux OS kan findes i denne artikel. Hvis du ikke har arbejdet med stikkontakter før, vil jeg anbefale at sætte dig ind i det – det er ikke obligatorisk, men det vil forbedre din forståelse af de ting, der præsenteres her.

Hvordan bruger man Libfcgi-biblioteket?

Så vi ønsker at skabe en multi-threaded FastCGI-applikation, så lad mig beskrive nogle af de vigtigste funktioner.
Først og fremmest skal biblioteket initialiseres:
int FCGX_Init(void);
Opmærksomhed! Denne funktion skal kaldes før alle andre funktioner i dette bibliotek og kun én gang (kun én gang, for et vilkårligt antal tråde).

Dernæst skal vi åbne et lyttestik:
int FCGX_OpenSocket(const char *sti, int backlog);
Stivariablen indeholder socket-forbindelsesstrengen. Både Unix-domæne-sockets og TCP-sockets understøttes, alle nødvendigt arbejde Biblioteket udfører selv udarbejdelsen af ​​parametre og funktionskald.
Eksempler på forbindelsesstrenge til Unix-domænesockets:
"/tmp/fastcgi/mysocket" "/tmp/fcgi_example.bare.sock"
Jeg tror, ​​at alt er klart her: du skal bare passere en unik sti som en streng, og alle processer, der interagerer med soklen, skal have adgang til den. Jeg gentager endnu en gang: denne metode virker kun inden for én computer, men er noget hurtigere end TCP-sokler.
Eksempel på forbindelsesstrenge til TCP-stik:
":5000" ":9000"
I dette tilfælde åbnes en TCP-socket på den angivne port (i dette tilfælde henholdsvis 5000 eller 9000), og anmodninger vil blive accepteret fra enhver IP-adresse. Opmærksomhed! Denne metode er potentielt usikker - hvis din server er forbundet til internettet, vil dit FastCGI-program acceptere anmodninger fra enhver anden computer. Dette betyder, at enhver angriber vil være i stand til at sende en "dødspakke" til dit FastCGI-program. Selvfølgelig er der ikke noget godt ved dette - i bedste tilfælde kan dit program simpelthen "crash" og resultere i et lammelsesangreb (DoS-angreb, hvis du vil), i værste fald fjernudførelse af kode (hvis du er virkelig uheldig), så begræns altid adgangen til sådanne porte ved hjælp af en firewall ( firewall), i dette tilfælde bør der kun gives adgang til de IP-adresser, der faktisk bruges under den normale drift af FastCGI-programmet (princippet om "alt, der ikke udtrykkeligt er tilladt, er forbudt").
Følgende er et eksempel på forbindelsesstrenge:
"*:5000" "*:9000"
Metoden ligner fuldstændig den forrige: en TCP-socket åbnes for at acceptere forbindelser fra enhver IP-adresse, så i dette tilfælde er det også nødvendigt at omhyggeligt konfigurere firewallen. Den eneste fordel ved en sådan forbindelseslinje er rent administrativ - enhver programmør eller systemadministrator, der læser konfigurationsfilerne, vil forstå, at dit program accepterer forbindelser fra enhver IP-adresse, så alt andet lige er det bedre at foretrække denne mulighed frem for den forrige en.
En mere sikker mulighed er eksplicit at angive IP-adressen i forbindelsesstrengen:
"5.5.5.5:5000" "127.0.0.1:9000"
I dette tilfælde vil anmodninger kun blive accepteret fra den angivne IP-adresse (i dette tilfælde - henholdsvis 5.5.5.5 eller 127.0.0.1), for alle andre IP-adresser vil denne port (i dette tilfælde - henholdsvis 5000 eller 9000) være lukket. Dette øger den samlede systemsikkerhed, så når det er muligt, skal du altid bruge dette forbindelsesstrengformat til TCP-sockets - hvad nu hvis systemadministratoren "simpelthen glemmer" at konfigurere firewallen? Vær opmærksom på det andet eksempel - adressen på den samme maskine (localhost) er angivet der. Dette giver dig mulighed for at oprette en TCP-socket på den samme maskine, hvis du af en eller anden grund ikke kan bruge Unix-domæne-sockets (for eksempel fordi chroot på webserveren og chroot af FastCGI-programmet er i forskellige mapper og ikke har fælles filstier). Desværre kan du ikke angive to eller flere forskellige IP-adresser, så hvis du virkelig har brug for at acceptere anmodninger fra flere webservere placeret på forskellige computere, bliver du enten nødt til at åbne porten helt (se. tidligere metode) og stol på dine firewall-indstillinger, eller brug flere stik pr forskellige havne. Desuden understøtter libfcgi-biblioteket ikke IPv6-adresser - tilbage i 1996 blev denne standard lige født, så du bliver nødt til at begrænse din appetit til almindelige IPv4-adresser. Sandt nok, hvis du virkelig har brug for IPv6-understøttelse, er det relativt nemt at tilføje det ved at patche FCGX_OpenSocket-funktionen - bibliotekslicensen tillader dette.
Opmærksomhed! Brug af funktionen til at angive en IP-adresse ved oprettelse af en socket er ikke tilstrækkelig beskyttelse - IP-spoofing-angreb (erstatning af IP-adressen på pakkeafsenderen) er mulige, så opsætning af en firewall er stadig påkrævet. Som en beskyttelse mod IP-spoofing kontrollerer firewallen typisk overensstemmelsen mellem pakkens IP-adresse og MAC-adressen på netværkskortet for alle værter på vores lokalt netværk(mere præcist, for broadcast-domænet med vores vært), og kasserer alle pakker, der kommer fra internettet, hvis returadresse er i zonen med private IP-adresser eller den lokale vært (masker 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/ 16, fc00::/7, 127.0.0.0/8 og::1/128). Det er dog stadig bedre at bruge denne mulighed biblioteker - i tilfælde af en forkert konfigureret firewall er det meget vanskeligere at sende en "dødspakke" fra en forfalsket IP-adresse end fra nogen anden, da TCP-protokollen har indbygget beskyttelse mod IP-spoofing.
Den sidste slags forbindelsesstreng er at bruge værtens domænenavn:
"example.com:5000" "localhost:9000"
I dette tilfælde opnås IP-adressen automatisk baseret på domænenavnet på den vært, du har angivet. Begrænsningerne er stadig de samme - værten skal have én IPv4-adresse, ellers vil der opstå en fejl. Men i betragtning af at socket oprettes én gang i begyndelsen af ​​arbejdet med FastCGI, er denne metode usandsynligt at være meget nyttig - dynamisk ændring af IP-adressen vil stadig ikke fungere (mere præcist, efter hver ændring af IP-adressen vil du have for at genstarte dit FastCGI-program). På den anden side vil dette måske være nyttigt for relativt stort netværk- at huske et domænenavn er stadig nemmere end at huske en IP-adresse.

Den anden parameter i backlog-funktionen angiver længden af ​​socket-anmodningskøen. Særlig betydning 0 (nul) angiver standardkølængden for dette operativsystem.
Hver gang der kommer en anmodning fra webserveren, placeres en ny forbindelse i denne kø, som venter på at blive behandlet af vores FastCGI-program. Hvis køen er helt fuld, vil alle efterfølgende forbindelsesanmodninger mislykkes - webserveren modtager et Connection refused-svar. I princippet er der ikke noget galt med dette - Nginx webserver der er en kø af anmodninger, og hvis der ikke er ledige ressourcer, vil nye anmodninger vente på deres tur til behandling allerede i webserverkøen (i hvert fald indtil timeout udløber). Derudover, hvis du har flere servere, der kører FastCGI, kan Nginx videregive en sådan anmodning til en mindre belastet server.
Så lad os prøve at finde ud af, hvad den optimale kølængde vil være. Generelt er det bedre at konfigurere denne parameter individuelt baseret på belastningstestdata, men vi vil forsøge at estimere det mest egnede område for denne værdi. Den første ting du skal vide er, at den maksimale kølængde er begrænset (bestemt af operativsystemets kerneindstillinger, normalt ikke mere end 1024 forbindelser). For det andet bruger køen ressourcer, billige, men stadig ressourcer, så du skal ikke gøre den urimelig lang. Lad os yderligere sige, at vores FastCGI-program har 8 arbejdstråde (ganske realistisk for moderne 4-8-kerne processorer), og hver tråd har brug for sin egen forbindelse - opgaver behandles parallelt. Det betyder, at vi ideelt set allerede skulle have 8 anmodninger fra webserveren for straks, uden unødvendige forsinkelser, at levere arbejde til alle tråde. Med andre ord, mindste størrelse anmodningskøer er antallet af arbejdertråde i et FastCGI-program. Du kan prøve at øge denne værdi med 50%-100% for at give lidt frihøjde til belastningen, da tiden for dataoverførsel over netværket er begrænset.
Lad os nu bestemme den øvre grænse for denne værdi. Her skal vi vide, hvor mange anmodninger vi rent faktisk kan behandle og begrænse anmodningskøen til denne værdi. Forestil dig, at du har gjort denne kø for stor – så meget, at dine kunder simpelthen bliver trætte af at vente på deres tur, og de simpelthen forlader din side uden at vente på svar. Det er åbenbart, at der ikke er noget godt ved dette - webserveren skulle sende en anmodning om at åbne en forbindelse, hvilket i sig selv er dyrt, og så kun lukke denne forbindelse, fordi FastCGI-programmet ikke havde tid nok til at behandle denne anmodning. Kort sagt, vi spilder kun processortid, men vi har bare ikke nok af det! Men dette er ikke det værste - det er værre, når klienten nægter at modtage information fra dit websted allerede efter, at anmodningen er begyndt at blive behandlet. Det viser sig, at vi bliver nødt til fuldstændig at behandle en i det væsentlige ubrugelig anmodning, som, ser du, kun vil forværre situationen. Teoretisk set kan der opstå en situation, hvor de fleste af klienterne ikke vil vente på et svar, når din processor er 100 % indlæst. Ikke godt.
Så lad os sige, at vi kan behandle en anmodning på 300 millisekunder (det vil sige 0,3 sekunder). Dernæst ved vi, at 50 % af de besøgende i gennemsnit forlader en ressource, hvis en webside tager mere end 30 sekunder at indlæse. Det er klart, at 50 % af utilfredse mennesker er for meget, så vi vil begrænse den maksimale sideindlæsningstid til 5 sekunder. Dette betyder en fuldstændig færdig webside - efter at have anvendt cascading style sheets og eksekvering af JavaScript - kan denne fase på et gennemsnitligt websted tage 70 % af den samlede indlæsningstid for en webside. Så der er ikke mere end 5 dage tilbage til at indlæse data over netværket *0,3 = 1,5 sekunder. Dernæst skal du huske, at html-koden, typografiark, scripts og grafik overføres i forskellige filer, og først html-koden og derefter alt det andet. Men efter at have modtaget html-koden browseren begynder at anmode om de resterende ressourcer parallelt, så vi kan estimere indlæsningstiden for html-koden som 50 % af den samlede tid til at modtage data. Så vi har ikke mere end 1,5 * 0,5 = 0,75 sekunder tilbage til at behandle en anmodning. Hvis en tråd i gennemsnit behandler en anmodning på 0,3 sekunder, så skulle der være 0,75/0,3 = 2,5 anmodninger pr. at bemærke, at ovenstående beregninger er betingede - hvis du har et specifikt sted, kan værdierne, der bruges i beregningen, bestemmes meget mere nøjagtigt, men det giver stadig et udgangspunkt for mere optimal ydelsesjustering.

Så vi har modtaget en socket-deskriptor, hvorefter vi skal allokere hukommelse til anmodningsstrukturen. Beskrivelsen af ​​denne struktur er som følger:
typedef struct FCGX_Request ( int requestId; int role; FCGX_Stream *in; FCGX_Stream *out; FCGX_Stream *err; char **envp; struct Params *paramsPtr; int ipcFd; int isBeginProcessed; int keepStatus; int keep-flag; int listen_sock; int detached; ) FCGX_Request;
Opmærksomhed! Efter at have modtaget en ny anmodning, vil alle tidligere data gå tabt, så evt langtidsopbevaring data, brug dyb kopiering (kopier selve dataene, ikke pointer til dataene).
Du bør vide følgende om denne struktur:
- variablerne ind, ud og fejl spiller rollen som henholdsvis input-, output- og fejlstrømme. Inputstrømmen indeholder POST-anmodningsdataene, svaret fra FastCGI-programmet (f.eks. http-headere og html-kode på websiden) skal sendes til outputstrømmen, og fejlstrømmen vil blot tilføje en post til webserveren fejllog. I dette tilfælde behøver du slet ikke bruge fejlstrømmen - hvis du virkelig har brug for at logge fejl, så er det måske bedre at bruge separat fil- datatransmission over netværket og den efterfølgende behandling af webserveren kræver yderligere ressourcer.
- envp-variablen indeholder værdierne af miljøvariabler indstillet af webserveren og http-headere, for eksempel: SERVER_PROTOCOL, REQUEST_METHOD, REQUEST_URI, QUERY_STRING, CONTENT_LENGTH, HTTP_USER_AGENT, HTTP_COOKIE, HTTP_REFERER og så videre. Disse overskrifter er defineret af henholdsvis CGI- og HTTP-protokolstandarderne; eksempler på deres brug kan findes i ethvert CGI-program. Selve dataene er lagret i en række strenge, hvor det sidste element i arrayet indeholder en nul-pointer (NULL) for at angive slutningen af ​​arrayet. Hver linje (hvert element i strengmatrixen) indeholder én variabelværdi i formatet VARIABLE_NAME=VALUE, for eksempel: CONTENT_LENGTH=0 (i dette tilfælde betyder det, at af denne anmodning der er ingen POST-data, fordi dens længde er nul). Hvis envp-strengarrayet ikke indeholder den header, du har brug for, betyder det, at den ikke blev transmitteret. Hvis du ønsker at få alle variabelværdierne videregivet til FastCGI-programmet, skal du blot læse alle linjerne i envp-arrayet i en loop, indtil du støder på en pointer til NULL.
Faktisk er vi færdige med beskrivelsen af ​​denne struktur - du behøver ikke alle de andre variabler.

Hukommelsen er blevet tildelt, nu skal du initialisere anmodningsstrukturen:
int FCGX_InitRequest(FCGX_Request *request, int sok, int flag);
Funktionsparametrene er som følger:
request - pointer til den datastruktur, der skal initialiseres
sock er socket-beskrivelsen, som vi modtog efter at have kaldt FCGX_OpenSocket-funktionen. Jeg vil gerne bemærke, at i stedet for en færdiglavet deskriptor kan du passere 0 (nul) og modtage en socket med standardindstillinger, men for os er denne metode slet ikke interessant - socket åbnes på en tilfældig fri port , hvilket betyder, at vi ikke vil være i stand til at konfigurere vores web korrekt -server - vi ved ikke på forhånd, hvor præcist dataene skal sendes.
flag - flag. Faktisk kan kun ét flag sendes til denne funktion - FCGI_FAIL_ACCEPT_ON_INTR - ring ikke FCGX_Accept_r ved brydning.

Efter dette skal du få ny anmodning:
int FCGX_Accept_r(FCGX_Request *request);
Du skal overføre anmodningsstrukturen, der allerede er initialiseret på det forrige trin, til den. Opmærksomhed! I et flertrådet program skal du bruge synkronisering, når du kalder denne funktion.
Faktisk udfører denne funktion alt arbejdet med sockets: For det første sender den et svar til webserveren på den tidligere anmodning (hvis der var en), lukker den tidligere datakanal og frigiver alle ressourcer, der er knyttet til den (inklusive anmodningsstrukturvariabler) , modtager derefter en ny anmodning, åbnes ny kanal dataoverførsel og klargør nye data i anmodningsstrukturen til efterfølgende behandling. Hvis der er en fejl ved modtagelse af en ny anmodning, returnerer funktionen en fejlkode mindre end nul.

Dernæst skal du sandsynligvis hente miljøvariabler; til dette kan du enten selv behandle request->envp-arrayet eller bruge funktionen
char *FCGX_GetParam(const char *navn, FCGX_ParamArray envp);
hvor navn er en streng, der indeholder navnet på miljøvariablen eller http-headeren, hvis værdi du vil have,
envp - et array af miljøvariabler, der er indeholdt i request->envp variablen
Funktionen returnerer værdien af ​​den miljøvariabel, vi skal bruge som en streng. Lad den opmærksomme læser ikke blive forskrækket over typemisforholdet mellem char ** og FCGX_ParamArray - disse typer er erklæret synonymer (typedef char **FCGX_ParamArray).
Derudover skal du sandsynligvis sende et svar til webserveren. For at gøre dette skal du bruge request->out output-strømmen og funktionen
int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream);
hvor str er en buffer, der indeholder de data, der skal udlæses, uden den afsluttende null (det vil sige, at bufferen kan indeholde binære data),
n - bufferlængde i bytes,
stream - den strøm, som vi ønsker at udlæse data i (request->out eller request->err).

Hvis du bruger standard nulterminerede C-strenge, vil det være mere praktisk at bruge funktionen
int FCGX_PutS(const char *str, FCGX_Stream *stream);
som blot vil bestemme længden af ​​strengen ved hjælp af strlen(str) og kalde den forrige funktion. Derfor, hvis du kender længden af ​​strengen på forhånd (du bruger f.eks. C++ std::strings), er det bedre at bruge den forrige funktion af effektivitetsmæssige årsager.
Jeg vil gerne bemærke, at disse funktioner fungerer perfekt med UTF-8-strenge, så der burde ikke være problemer med flersprogede webapplikationer.
Du kan også kalde disse funktioner flere gange, mens du behandler den samme anmodning, i nogle tilfælde kan dette forbedre ydeevnen. For eksempel skal du sende nogle stor fil. I stedet for at downloade hele denne fil fra din harddisk og derefter sende den i ét stykke, kan du begynde at sende data med det samme. Som et resultat vil klienten i stedet for en hvid browserskærm begynde at modtage de data, han er interesseret i, hvilket rent psykologisk vil tvinge ham til at vente lidt længere. Med andre ord, du får lidt tid til at indlæse siden. Jeg vil også gerne bemærke, at de fleste ressourcer (cascading style sheets, JavaScript osv.) er angivet i begyndelsen af ​​websiden, det vil sige, at browseren vil være i stand til at analysere en del af html-koden og begynde at indlæse disse ressourcer tidligere - endnu en grund til at vise data i dele.

Den næste ting, du muligvis skal gøre, er at behandle POST-anmodningen. For at få dens værdi skal du læse data fra request->in stream ved hjælp af funktionen
int FCGX_GetStr(char * str, int n, FCGX_Stream *stream);
hvor str er en pegepind til bufferen,
n - bufferstørrelse i bytes,
stream - den strøm, som vi læser data fra.
Størrelsen af ​​de transmitterede data i en POST-anmodning (i bytes) kan bestemmes ved hjælp af miljøvariablen CONTENT_LENGTH, hvis værdi, som vi husker, kan opnås ved hjælp af FCGX_GetParam-funktionen. Opmærksomhed! At oprette en str-buffer baseret på værdien af ​​CONTENT_LENGTH-variablen uden nogen begrænsninger er en meget dårlig idé: enhver angriber kan sende en hvilken som helst POST-anmodning, uanset hvor stor, og din server kan simpelthen løbe tør for ledig RAM (dette vil resultere i en DoS-angreb, hvis du vil). I stedet er det bedre at begrænse bufferstørrelsen til en rimelig værdi (fra nogle få kilobyte til flere megabyte) og kalde funktionen FCGX_GetStr flere gange.

Den sidste vigtige funktion blinker output- og fejlstrømmene (sender til klienten de stadig usendte data, som vi formåede at placere i output- og fejlstrømmene) og lukker forbindelsen:
void FCGX_Finish_r(FCGX_Request *request);
Jeg vil især bemærke, at denne funktion er valgfri: FCGX_Accept_r-funktionen sender også data til klienten og lukker den aktuelle forbindelse, før den modtager en ny anmodning. Spørgsmålet opstår: hvorfor er det så nødvendigt? Forestil dig, at du allerede har sendt klienten alle de nødvendige data, og nu skal du udføre nogle sidste handlinger: skrive statistik til databasen, fejl til logfilen osv. Det er klart, at forbindelsen til klienten ikke længere er nødvendig, men klienten (det vil sige browseren) venter stadig på information fra os: hvad nu hvis vi sender noget andet? Det er indlysende, at vi ikke kan ringe til FCGX_Accept_r før tid - herefter skal vi begynde at behandle den næste anmodning. Det er i dette tilfælde, at du skal bruge FCGX_Finish_r-funktionen - den giver dig mulighed for at lukke den aktuelle forbindelse, før du modtager en ny anmodning. Ja, vi vil være i stand til at behandle det samme antal anmodninger pr. tidsenhed som uden at bruge denne funktion, men klienten vil modtage et svar tidligere - han skal ikke længere vente på afslutningen af ​​vores endelige operationer, og det er netop på grund af den højere anmodningsbehandlingshastighed, som vi bruger FastCGI.
Dette afslutter faktisk beskrivelsen af ​​bibliotekets funktioner og begynder behandlingen af ​​de modtagne data.

Et simpelt eksempel på et multi-threaded FastCGI-program

Jeg tror, ​​at alt vil være klart i eksemplet. Det eneste er, at udskrivning af fejlretningsmeddelelser og "sove" i arbejdstråden udelukkende sker til demonstrationsformål. Når du kompilerer programmet, så glem ikke at inkludere bibliotekerne libfcgi og libpthread (parametre gcc compiler: -lfcgi og -lpthread).

#omfatte #omfatte #omfatte #include "fcgi_config.h" #include "fcgiapp.h" #define THREAD_COUNT 8 #define SOCKET_PATH "127.0.0.1:9000" //gemmer det åbne socket-håndtag statisk int socketId; statisk void *doit(void *a) (int rc, i; FCGX_Request request; char *server_name; if(FCGX_InitRequest(&request, socketId, 0) != 0) ( //fejl ved initialisering af anmodningsstrukturen printf("Kan ikke init request\n"); return NULL; ) printf("Anmodning er påbegyndt\n"); for(;;) ( static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; //prøv at modtage en ny anmodning printf("Prøv at acceptere ny anmodning \n" ); pthread_mutex_lock(&accept_mutex); rc = FCGX_Accept_r(&request); pthread_mutex_unlock(&accept_mutex); if(rc< 0) { //ошибка при получении запроса printf("Can not accept new request\n"); break; } printf("request is accepted\n"); //получить значение переменной server_name = FCGX_GetParam("SERVER_NAME", request.envp); //вывести все HTTP-заголовки (каждый заголовок с новой строки) FCGX_PutS("Content-type: text/html\r\n", request.out); //между заголовками и телом ответа нужно вывести пустую строку FCGX_PutS("\r\n", request.out); //вывести тело ответа (например - html-код веб-страницы) FCGX_PutS("\r\n", request.out); FCGX_PutS(" \r\n", request.out); FCGX_PutS("\r\n", request.out); FCGX_PutS(" \r\n", request.out); FCGX_PutS("

FastCGI Hej! (multi-threaded C, fcgiapp-bibliotek)

\r\n", request.out); FCGX_PutS("

Anmodning accepteret fra vært ", request.out); FCGX_PutS(servernavn ? servernavn: "?", request.out); FCGX_PutS("

\r\n", request.out); FCGX_PutS("\r\n", request.out); FCGX_PutS("\r\n", request.out); //"falde i søvn" - efterligning flertrådet miljø søvn(2); //luk den aktuelle forbindelse FCGX_Finish_r(&request); //endelige handlinger - registrering af statistik, logningsfejl mv. ) returner NULL; ) int main(void) ( int i; pthread_t id; //initialiser biblioteket FCGX_Init(); printf("Lib er påbegyndt\n"); //åbn en ny socket socketId = FCGX_OpenSocket(SOCKET_PATH, 20); if( socketId< 0) { //ошибка при открытии сокета return 1; } printf("Socket is opened\n"); //создаём рабочие потоки for(i = 0; i < THREAD_COUNT; i++) { pthread_create(&id[i], NULL, doit, NULL); } //ждем завершения рабочих потоков for(i = 0; i < THREAD_COUNT; i++) { pthread_join(id[i], NULL); } return 0; }

Enkelt Nginx-konfigurationseksempel

Rent faktisk, enkleste eksempel config ser sådan ud:

Server ( server_name localhost; location / ( fastcgi_pass 127.0.0.1:9000; #fastcgi_pass unix:/tmp/fastcgi/mysocket; #fastcgi_pass localhost:9000; include fastcgi_params; ) )

I dette tilfælde er denne konfiguration nok til at vores FastCGI-program fungerer korrekt. De kommenterede linjer er et eksempel på at arbejde med Unix-domæne-sockets og angive et domæneværtsnavn i stedet for en IP-adresse.
Efter at have kompileret og kørt programmet og opsat Nginx, fik jeg en stolt inskription på localhost-adressen:
FastCGI Hej! (multi-threaded C, fcgiapp-bibliotek)

Tak til alle, der læste til slutningen.

Ny side 3

CGI

CGI scripts

For at websteder virkelig kan være interaktive, skal de udveksle oplysninger med brugeren, ikke blot tillade ham at downloade dokumenter. Brug af Common Gateway Interface-programmer (kaldet CGI scripts), kan du oprette datadrevne websider. Som du vil lære, kan en node ved hjælp af CGI-scripts modtage anmodninger og svare brugeren.

Fordi CGI-scripts genererer HTML-dokumenter, mens systemet kører, står brugeren over for dynamiske websider. Du kan endda generere sider tilfældigt, så hver bruger, der besøger dit websted, vil se et lidt anderledes billede end det forrige.

Hvorfor websteder bruger CGI

At skabe dynamik HTML-filer der er ingen grund til at bruge CGI-scripts. Men uden sådanne scripts, når der er behov for en ny interaktiv dynamik hjemmeside, bliver du nødt til at ændre serverprogrammet. Over tid kan serverprogrammet blive usædvanligt stort. For at forhindre en sådan ændring af serveren bruger udviklere CGI. Ved hjælp af CGI-scripts kan serveren overføre opgaven med at skabe dynamiske webdokumenter til et applikationsprogram, der er bygget til disse specifikke behov. Du vil oprette dit applikationsprogram ved hjælp af C/C++, Perl, JavaScript, VBScript eller et andet programmeringssprog.

Serverprogrammet skal kalde CGI-scriptet

Du kan ikke udføre et CGI-script direkte fra et browserprogram. For at bruge scriptet skal det være placeret på den samme computer, hvor serveren er placeret. For at du kan se output genereret af et script i din browser, skal serveren udføre scriptet. Men dette er spørgsmål til serveradministratoren.

Browser, server og CGI

Som du ved, for at en browser skal modtage HTML-dokumenter, etablerer den først kontakt med serveren og anmoder derefter om dokumentet (normalt bestemmer din browser FÅ- HTTP-metode til at modtage information fra serveren). Dernæst, hvis dokumentet eksisterer, reagerer serveren på browseren ved at sende HTML-dokumentet til den og lukker derefter forbindelsen. Brugen af ​​CGI-scripts ændrer kun denne proces på serversiden. Browseren ved ikke, at serveren kalder CGI-scriptet, og den er ligeglad med, hvordan serveren sender data til den. Når du skriver CGI-scripts, bekymrer du dig som webprogrammør kun om serverens input og output. Browseren vil etablere kontakt med serverprogrammet, som igen udfører CGI-scriptet. Dit script udfører til gengæld den nødvendige databehandling for at formatere det nødvendige output. Typisk vil din server sende output fra scriptet i formularen til HTML-browseren. For at opnå dette tilføjer serverprogrammet den nødvendige headerinformation til outputtet, der genereres af scriptet, og sender denne headerinformation sammen med dataene tilbage til browseren. Serveren lukker derefter forbindelsen og venter på nye anmodninger.

Som du måske ved, er servere, der kører 32-bit operativsystemer som f.eks Windows 95/98 eller Windows NT, kan behandle anmodninger fra mange brugere samtidigt. Det betyder, at flere brugere kan bruge scriptet samtidigt. Derfor vil hver af dem, afhængigt af anmodningen, se sit eget billede af serverens svar.

Forholdet mellem serveren og CGI-scriptet

Når et serverprogram kalder et script, skal serveren udføre flere grundlæggende handlinger: Kald scriptet og forsyn det med de nødvendige data sendt fra browseren til dit script, forsyn scriptet med værdier miljøvariabler, tilgængelig for scriptet og behandle scriptets output, herunder at sikre, at der medtages yderligere headeroplysninger, som er nødvendige for, at browseren kan fortolke scriptets data.

Som du allerede ved, er HTTP den protokol, hvorigennem webklienter og servere forsynes med information. HTTP-headeroplysninger hjælper programmer med at kommunikere effektivt. Derfor er det nødvendigt at være særlig opmærksom på de headeroplysninger, som serveren leverer til browseren. For eksempel, når et serverprogram er klar til at sende data til browseren, sender det headers, der beskriver dataens status, typen af ​​data osv. Til gengæld bruger browseren overskriften ( Indholdstype) for at forberede til visning af data på skærmen. Serveren er ansvarlig for at give denne metainformation til browseren, hver gang den sender data til den.

CGI database

Brugere bruger ofte scripts til at give adgang til databaser. Fordi databaser kan gemme utrolige mængder information, skriver programmører scripts, der fungerer som en grænseflade ikke kun til klienten, men også til databasen. Som du vil se senere, er typen af ​​transaktion mellem klient og server til udveksling af dynamiske data ret generel. Du skal forstå, hvordan scripts oprettes, der interagerer med databasen for at modtage og sende information. Men før du arbejder med CGI-databaseprogrammer, skal du lære de grundlæggende programmeringsteknikker til at skabe professionelle CGI-programmer.

Hvor er scripts placeret?

CGI-standarder foreskriver ikke, hvor scripts skal placeres, det vil sige, at de ikke forudbestemmer drevet og mappen. Typisk forventer webserveren at finde scripts i mappen /CGI-BIN som er placeret i selve serverprogrammets bibliotek. Hvis du lægger dine scripts på en andens server, skal du definere en mappe til dine filer, der indeholder scripts.

CGI script filtypenavn

HTTP-servere til Windows-systemer bruger normalt EXE- eller PL-udvidelsen til CGI-filer. For eksempel, hvis du opretter et CGI-program (script) ved hjælp af C-programmeringssproget, så vil udvidelsen af ​​dine script-filer sandsynligvis være EXE. Ligeledes hvis du opretter et script ved hjælp af Perl sprog, vil din filtypenavn være PL.

Nogle servere forventer dog, at CGI-udvidelser bruges til scripts. Faktisk inkluderer mange systemer CGI-udvidelsen som en del af serverkonfigurationsfilen. Hvis du ikke er sikker på, hvilken filtypenavn serveren understøtter, skal du kontakte din webmaster. Ellers vil serveren kalde dine scripts forkert.

Grundlæggende om interaktion mellem en webserver og et CGI-script

CGI-specifikationen definerer den information, som serveren skal give til scriptet, samt informationen fra scriptet, som serveren kræver. For at dit script opfylder specifikationen og fungerer korrekt med serveren, skal du følge kravene defineret af specifikationen.

Når en webbruger laver en forbindelse, der får serveren til at fremkalde scripts, kræver serveren stort antal miljøvariabler, der bruges af scriptet til at indhente information. Disse miljøvariabler indeholder oplysninger om den browser, der sender anmodningen, serveren, der behandler den, og de data, der sendes til dit script. CGI-miljøvariabler skelner mellem store og små bogstaver, og hver variabel er defineret i CGI-specifikationen.

miljøvariabler

Variabel AUTH_TYPE

CGI-scripts bruger en miljøvariabel AUTH_TYPE for at identificere den bruger, der forsøger at få adgang til scriptet. Hvis serveren er konfigureret til at understøtte brugergodkendelse, skal den bruger, der forsøger at få adgang til scriptet, angive sit brugernavn og adgangskode. For eksempel angiver følgende variabelværdi, at brugeren skal have et grundlæggende identifikationsniveau:

AUTH_TYPE = Grundlæggende

CONTENT_LENGTH variabel

Scripts bruger miljøvariable CONTENT_LENGTH for at bestemme det nøjagtige antal bytes, der er indeholdt i de tilsluttede data. For eksempel, hvis anmodningen indeholder et dokument, der er 1,024 byte langt, indstilles miljøvariablen til følgende værdi:

CONTENT_LENGTH = 1024

Variabel INDHOLDSTYPE

Scripts bruger denne miljøvariabel til anmodninger, der indeholder vedhæftede oplysninger. Denne type anmodning refererer til en HTTP-operation STOLPE. Oplysningerne i variablen angiver typen af ​​vedhæftede data (MIME type.subtype). For eksempel hvis anmodningen indeholder en tilføjet HTML-dokument, så vil miljøvariablen tage følgende værdier:

CONTENT_TYPE = tekst/html

Variabel GATEWAY_INTERFACE

Scripts bruger denne variabel til at bestemme versionen, udgivelsesnummeret, af CGI-specifikationen, som webserveren overholder. Specifikationens udgivelsesnummerformat er CGI/udgivelsesnummer. For eksempel, for CGI release 1.1 ville miljøvariablen være:

GATEWAY_INTERFACE = CGI/1.1

Variabel PATH_INFO

Scripts bruger denne variabel til at bestemme yderligere stioplysninger, der skal gives til klienter. Med andre ord kan serveren få adgang til scriptet ved hjælp af den virtuelle scriptsti efterfulgt af Yderligere Information om stien. Serverprogrammet skal afkode denne yderligere information, hvis den kommer fra en URL, før serveren sender den til scriptet. Typisk angiver disse yderligere oplysninger en ressource, som scriptet skal returnere, hvis anmodningen lykkes.

Stien er skrevet til i forhold form, hvor rodmappen på serveren tages som base. Med andre ord er serverens rodbibliotek grundlaget for den relative sti, som er tildelt variablen PATH_INFO. For eksempel hvis stien gives c:/cgi-bin/example1.exe/sports.html, så vil miljøvariablen se sådan ud:

PATH_INFO = /sport.html

Variabel PATH_OVERSÆTTET

Scripts bruger denne variabel til at opnå endelig, direkte brugbar stiinformation. Serveren oversætter den variable information ved at udføre de nødvendige stitransformationer. For eksempel hvis variablen PATH_OVERSÆTTET har betydningen /sport.html, og rodmappen på serveren er c:\, så vil miljøvariablen have følgende værdi:

PATH_TRANSLATED = c:\sports.html

Variabel QUERY_STIRNG

Scripts bruger denne variabel til at få information i tekstform (bestående af argumenter), der vises til højre for spørgsmålstegnet, efter at URL'en er overført fra brugeren til scriptet til behandling. Denne tekststreng indeholder input til scriptet. Dernæst erstatter serveren hvert mellemrum i denne tekst med "+"-tegnet, og alle ikke-udskrivbare tegn med "%dd"-tegnet, hvor d er basen decimalsystem Regning.

Scriptet skal indeholde kode for at dekryptere denne tekststreng. Når serveren videregiver disse oplysninger til scriptet, må den ikke afkode anmodningsoplysningerne på nogen måde. Serveren skal også indstille variablen QUERY_STRING i tilfælde af at brugeren giver nogle anmodningsoplysninger. For eksempel til URL http://www.jamsa.com/cgi-bin/grandma.exe?name=margaret+alarcon Miljøvariablen har følgende værdi:

QUERY_STRING = navn=margaret+alarcon

Variabel REMOTE_ADDR

Scripts bruger denne variabel til at få IP-adressen på den fjernvært (browser), der foretager anmodningen. For eksempel kan værdien af ​​en miljøvariabel være:

REMOTE_ADDR = 204.212.52.209

Variabel REMOTE_HOST

Scripts bruger denne variabel til at få navnet på den vært, som anmodningen er lavet fra. Hvis serveren ikke kender navnet på den vært, der foretager anmodningen, skal serveren tildele en værdi til miljøvariablen REMOTE_ADDR og tildel ikke værdier til variablen REMOTE_HOST. For eksempel for en node jamsa.com Miljøvariablen vil indeholde følgende værdi:

REMOTE_HOST = jamsa.com

Variabel REMOTE_IDENT

Bruges til at give et navn fjernbruger lave en anmodning til serveren. Webserverprogrammet er software. kalder dit script. Hvis HTTP-webserveren understøtter RFS 931 (Authentication Server Protocol), vil serveren indstille denne variabel til værdien af ​​det brugernavn, som serveren har. Scripts kan kun bruge denne variabel til at registrere en bruger. For eksempel hvis fjernbrugernavnet pschmauder og den vil være placeret på den eksterne node jamsa.com, så vil variablen have følgende værdi:

REMOTE_IDENT = pschmauder.www.jamsa.com

Variabel REMOTE_USER

Bruges til at få navnet på fjernbrugeren uden navnet på den vært, som han sender anmodningen fra. Hvis serveren understøtter brugergodkendelse, og scriptet er sikkert, vil serveren indstille brugernavnet og tildele det til denne variabel. Antag for eksempel, at fjernbrugerens navn er pschmauder. Så vil variablen se sådan ud:

REMOTE_USER = pschmauder

Variabel REQUEST_METHOD

Bruges til at bestemme typen af ​​HTTP-anmodning, der sendes af browseren til serveren og bruges til at fremkalde scripts. Denne variabel kan tage værdier FÅ, HOVED eller STOLPE. For eksempel hvis browseren sender FÅ- metode, indeholder miljøvariablen følgende:

REQUEST_METHOD = FÅ

Variabel SCRIPT_NAME

Bruges til at definere den virtuelle sti til scriptet, der vil blive lanceret af serveren. For eksempel hvis der er en URL http://www.jamsa.com/cgi-bin/someprog.exe, så vil miljøvariablen have følgende værdi:

SCRIPT_NAME = cgi-bin/example1.exe

Variabel SERVER NAVN

Bruges til at bestemme domænenavnet eller IP-adressen på den computer, hvor webserveren er placeret. For eksempel, når serveren returnerer en IP-adresse, vil miljøvariablen se sådan ud:

SERVER_NAME = 204.212.52.209

Variabel SERVER_PORT

Bruges til at bestemme det portnummer, som brugeren (browseren) bruger til at kommunikere med webserveren. Hvis standard HTTP-porten bruges, så er denne værdi 80. Hvis en anden port bruges, f.eks. http://www.jamsa.com:3000, så tager variablen følgende værdi:

SERVER_PORT = 3000

Variabel SERVER_PROTOCOL

Bruges til at angive navnet og udstedelsesnummeret på den protokol, der bruges af klienten (browseren) til at sende en anmodning til webserveren. Ved at analysere indholdet af variablen kan scriptet identificere navnet og udstedelsesnummeret på den protokol, det skal bruge, når data overføres til serveren. Protokolnavnet og udstedelsesnummerformatet er som følger: protokol/udstedelsesnummer. For eksempel vil miljøvariablen for HTTP 1.1 se sådan ud:

SERVER_PROTOCOL = HTTP/1.1

Variabel SERVER_SOFTWARE

Som du ved, udfører en webserver CGI-scripts. Fordi et script kan udføres forskelligt for forskellige serverprogrammer, bruger scripts denne variabel til at bestemme navnet på webserverprogrammet og dets versionsnummer. Formatet på webservernavnet og versionsnummeret skal overføres til CGI'en som følger: navn/version. For eksempel for FOLK WEB - server version 1.01, vil miljøvariablen se sådan ud:

SERVER_SOFTWARE = ​​​​FolkWeb/1.01 (Windows-32bit)

Yderligere miljøvariabler

Ud over miljøvariabler. diskuteret tidligere, placerer serveren også data fra anmodningsheaderen modtaget fra klienten i miljøvariabler. Serveren tildeler værdier til variabler, hvis navne begynder med HTTP_-præfikset efterfulgt af headernavnet. Serveren erstatter alle bindestreger (-) i overskriften med (_). Serveren kan også udelukke eventuelle overskrifter, den allerede har behandlet ved hjælp af miljøvariabler som f.eks AUTH_TYPE, CONTENT_TYPE Og CONTENT_LENGTH.

Variabel HTTP_ACCEPTER

Bruges til at bestemme, hvilke MIME-typer browseren kan acceptere. De er defineret i de HTTP-headere, som browseren sender til serveren. MIME-typen er som bekendt angivet i formen type/udvidelse. Hvis der er flere MIME-typer, er de adskilt med kommaer. For eksempel kan en miljøvariabel have følgende værdi:

HTTP_ACCEPT = audio/aif, text/html, text/plain

Variabel HTTP_USER_AGENT

Bruges til at identificere den type browser, der sender anmodningen til serveren. For eksempel kan en miljøvariabel indeholde følgende:

HTTP_USER_AGENT = Mozilla/2.01 Gold(Win95PE)

CGI kommandolinjeindstillinger

Typisk bruger CGI-scripts kommando streng som input for at udføre forespørgslen ISINDEX, giver dig mulighed for at tilføje interaktive søgeordssøgninger til dine HTML-dokumenter. Det er dog ikke alle serverprogrammer, der understøtter ISINDEX- anmodning. Browseren sender en kommandolinjeanmodning til serveren. Serverprogrammet kan identificere input-kommandolinjen ved at bestemme, om den anvendte browser FÅ- HTTP-metode og om URL-strengen indeholder tegn uuencoded =.

Hvis browseren bruger FÅ- HTTP-metoden og URL-søgestrengen indeholder ikke tegn uuencoded=, derefter udføres anmodningen i form af en kommandolinje. Før serveren kalder det relevante script, skal serverprogrammet opdele kommandolinjen ved at bruge tegnet (+) for at adskille parametrene. Serveren udfører derefter yderligere afkodning (om nødvendigt) af hver parameter, der sendes i URL-søgestrengen, og gemmer hver strengparameter i et array kaldet argv.

Yderligere afkodning udført af serveren består i at adskille individuelle linjer ved at bruge og-tegnet (&) som afgrænsning. Serveren deler derefter hver af disse strenge igen ved at bruge tegnet (=) til at adskille variabelnavnet, som vises til venstre for (=)-tegnet, fra variabelværdien, der vises til højre for (=)-tegnet . Serveren gemmer antallet af elementer indeholdt i arrayet argv, i en variabel af heltalstypen argс.

Hvis serveren fandt et lighedstegn inde i strengen QUERY_STRING miljøvariabel, så sender den ikke kommandolinjen som input til scriptet. Også hvis serverprogrammet af en eller anden grund ikke kan sende arrayet argv script, vil det give de ukodede anmodningsoplysninger i en miljøvariabel QUERY_STRING.

Standard input ( STDIN)

Når browseren anmoder om serveren (for eksempel ved hjælp af HTTP-metoden STOLPE), den information, scriptet modtager, kommer fra standardinputhåndtaget stdin. Serverprogrammet sender en miljøvariabel til scriptet CONTENT_LENGTH. Denne variabel indeholder antallet af bytes, som serveren sender til scriptet gennem dette håndtag. Scriptet kan bruge værdien af ​​en variabel CONTENT_LENGTH for at bestemme, hvor meget data der skal komme fra standard input. Serveren forsyner også scriptet med en miljøvariabel INDHOLDSTYPE, som hjælper scriptet med at bestemme, hvordan det skal behandle de data, det modtager. I slutningen af ​​denne datastrøm kan serveren sende en ende-på-fil-markør eller ikke. Det er dog scriptet, der skal bestemme, hvor meget data der skal læses, og det bruger en miljøvariabel til dette CONTENT_LENGTH.

For eksempel, hvis formularen bruger HTTP-metoden STOLPE(

), og de data, der sendes til serveren, er kodet som følger: navn=alberta&mand=kunst, så vil serveren tildele til variablerne CONTENT_LENGHT Og INDHOLDSTYPE følgende værdier:

CONTENT_LENGHT = 24 CONTENT_TYPE = APPLICATION/x-www-form-urlencoded

Standard output ( STDOUT)

Når CGI-scriptet er færdig med at behandle de data, der modtages fra serveren, skal det sende sit svar til serveren. For at sende sine data til serveren, skal den sende dem til standard outputfilbeskrivelsen STDOUT. Generelt er de data, som scriptet sender tilbage til serveren, et HTTP-svar, inklusive en header, efterfulgt af en tom linje og efterfulgt af resten af ​​svaret. Typisk er outputtet af et script de HTML-dokumenter, der genereres af scriptet.

Scriptets direkte svar på browseren

Typisk producerer scriptet et svar, som serveren fortolker og sender tilbage til browseren. Fordelen ved at sende scriptets output til serveren er, at scriptet ikke skal sende den fulde HTTP-header for hver anmodning. Nogle scripts aflaster dog serveren og sender deres output direkte til browseren. For at skelne scripts, der sender data direkte til browseren, fra scripts, der sender dem til serveren, kræver CGI-protokollen, at navnene på scripts, der sender data direkte til browseren, begynder med bogstaverne nph-(som fortæller serveren Ikke at analysere overskriften - initialiser ikke overskriften). Hvis scriptnavnet starter sådan, vil serveren ikke indsætte headeren i scriptdataene. I dette tilfælde påhviler ansvaret selve scriptet.

CGI-titler

Som du lærte tidligere, starter outputtet af et script med en header. Denne header består af en tekstlinje i samme format som HTTP-headeren, der slutter med en tom linje (en linje der kun indeholder CRLF). Hvis script-outputtet indeholder andre overskrifter end direktiver til serveren, så sender serveren disse overskrifter til browseren som svar på dens anmodning. Den nuværende CGI-specifikation definerer tre direktiver:

  • INDHOLDSTYPE
  • BELIGGENHED
  • STATUS

Mark Indholdstype i CGI-headeren angiver typen/udvidelsen af ​​MIME-data, som scriptet sender tilbage til browseren. Typisk producerer scripts et HTML-dokument som output. I dette tilfælde CGI-headeren Indholdstype indeholder følgende:

Indholdstype: tekst/html

Mark Beliggenhed header angiver dokumentet. Scripts bruger normalt feltet Beliggenhed for at angive dokumentets placering. Hvis dokumentet ikke er placeret på serveren, og indholdet af feltet er en URL, omdirigerer serveren browseren til den relevante node. Hvis dokumentet er på serveren, og feltet er en virtuel sti, udsteder serveren dette dokument til browseren. For at pege på et dokument på en ekstern server, kan overskriftsfeltets værdi se ud som:

Sted: http://www.cetis.ru

Mark Status Headeren indeholder HTTP-statusværdien, som serveren sender fra scriptet til browseren. Serveren, der kalder scriptet, bruger forskellige HTTP-statuskoder. Det kan være en god idé at sende statuskoden direkte til browseren, især hvis der opstår fejl.

Følgende eksempel illustrerer det typiske output et script ville producere, når der sendes data til en server. Når dataene når serverprogrammet, videresender serveren dataene til browseren:

Indholdstype: tekst/html Dette er titlen Dette er brødtekst genereret af dit CGI-script.

Læg mærke til den tomme linje mellem de første linjer. Denne tomme linje er absolut nødvendig. Følgende C-kodestykke opretter dokumentet ovenfor ved hjælp af funktionen printf:

// Mere kode ovenfor: printf("Indholdstype: text/html\n"); printf("\n"); // Sørg for at inkludere denne tomme linje printf(" \n"); printf(" \n"); printf(" Dette er titlen\n"); printf("\n"); printf(" \n"); printf("Dette er brødteksten genereret af dit CGI-script.\n"); printf("\n"); printf("\n"); // Mere kode nedenfor...

Sikring af et ensartet dataflow mellem serveren og applikationsprogrammet, der kører under serveren. CGI definerer kommunikationsprotokollen mellem serveren og programmet.

  • CGI definerer rækkefølgen af ​​interaktion mellem serveren og applikationsprogrammet, hvor serveren fungerer som den initierende part;
  • CGI definerer mekanismen for den faktiske udveksling af data og kontrolkommandoer i denne interaktion, som ikke er defineret i HTTP.

Begreber som adgangsmetode, headervariabler, MIME, datatyper er lånt fra HTTP og gør specifikationen gennemsigtig for dem, der er fortrolige med selve protokollen.

Når man skal beskrive forskellige programmer, som kaldes af HTTP-serveren og implementeres i CGI-standarden, skal du bruge følgende terminologi:

Et CGI-script er et program skrevet i overensstemmelse med Common Gateway Interface-specifikationen. CGI-scripts kan skrives i et hvilket som helst programmeringssprog (C, C++ (programmeringssprog), PASCAL, FORTRAN osv.) eller kommandosprog(shell (operativsystemer), cshell, kommando MS-DOS sprog, Perl osv.). Scriptet kan endda skrives i EMAC-editorsproget på Unix-systemer.

En gateway er et CGI-script, der bruges til at udveksle data med andre internetinformationsressourcer eller dæmonapplikationer. Et typisk CGI-program startes af en HTTP-server for at udføre noget arbejde, returnerer resultaterne til serveren og fuldfører dets eksekvering. Gatewayen gør præcis det samme, bortset fra at den faktisk initierer interaktion som klient med et tredje program. Hvis dette tredje program er Internet service, for eksempel en Gopher-server, bliver gatewayen en Gopher-klient, som sender en anmodning på Gopher-porten, og efter at have modtaget et svar videresender den til HTTP-serveren.

Fælles Gateway Interface CGI

CGI (Common Gateway Interface) er en mekanisme til at få adgang til programmer på webserversiden. CGI-specifikationen blev udviklet for at udvide mulighederne for www-tjenesten ved at forbinde forskellig ekstern software. Ved brug af CGI giver webserveren browseren adgang til eksekverbare programmer, der kører på dens (server) side gennem standard input- og outputstrømme.

CGI bruges til at skabe dynamiske websteder, såsom når websider genereres ud fra resultaterne af en databaseforespørgsel. I dag er populariteten af ​​CGI faldet, fordi... mere avancerede er dukket op alternative løsninger(f.eks. modulære webserverudvidelser).

Webservere

Webserveren er netværksapplikation, der serverer HTTP-anmodninger fra klienter, typisk webbrowsere. En webserver accepterer anmodninger og returnerer svar, normalt sammen med en HTML-side, et billede, en fil, en mediestrøm eller andre data. Webservere er grundlaget for World Wide Web. Efterhånden som rækken af ​​netværkstjenester udvides, bliver webservere i stigende grad brugt som gateways for applikationsservere eller selv leverer sådanne funktioner (f.eks. Apache Tomcat).

Mange udviklere er involveret i at skabe webserversoftware, men de mest populære softwareprodukter er Apache (Apache Software Foundation), IIS (Microsoft), Google Web Server (GWS, Google Inc.) og nginx.

  • Apache - gratis software, distribueret under en GPL-kompatibel licens. Apache har været førende i popularitet på World Wide Web i mange år på grund af dets pålidelighed, fleksibilitet, skalerbarhed og sikkerhed.
  • IIS (Internet Information Services) er et proprietært sæt servere til adskillige internettjenester udviklet af Microsoft og distribueret med Windows-familien af ​​serveroperativsystemer. Hovedkomponenten i IIS er webserveren, som også understøttes FTP protokoller, POP3, SMTP, NNTP.
  • Google Webserver(GWS) - udviklet af Google baseret på Apache-webserveren. GWS er ​​optimeret til at køre Google Applications.
  • nginx er en HTTP-server kombineret med en caching-proxyserver. Udviklet af I. Sysoev for virksomheden Rambler. I efteråret 2004 blev den første offentligt tilgængelige udgivelse frigivet, og nu bruges nginx på 9-12% af webservere. Browsere
  • Browser, webbrowser (webbrowser) er en klientapplikation til adgang til webservere via HTTP og visning af websider. Som regel understøtter browsere desuden en række andre protokoller (for eksempel ftp, file, mms, pop3).

De første HTTP-klienter var konsolbaserede og arbejdede i teksttilstand, så du kan læse hypertekst og navigere i links. I dag bruges konsolbrowsere (såsom lynx, w3m eller links) praktisk talt ikke af almindelige besøgende på webstedet. Ikke desto mindre er sådanne browsere meget nyttige for webudviklere, da de giver dig mulighed for at "se" en webside gennem "øjnene" på en søgerobot.

Historisk set var den første browser i moderne forstand (dvs. med en grafisk grænseflade osv.) NCSA Mosaic-programmet, udviklet af Marc Andersen og Eric Bina. Mosaic havde ret begrænsede muligheder, men den er åben kilde blev grundlaget for mange efterfølgende udviklinger.

Hvordan CGI virker

En generaliseret algoritme til at arbejde gennem CGI kan præsenteres som følger:

  1. Nummereret listeelement
  2. Klienten anmoder om CGI-applikationen via sin URI.
  3. Webserveren accepterer anmodningen og indstiller miljøvariabler, hvorigennem data og serviceoplysninger overføres til applikationen.
  4. Webserveren omdirigerer anmodninger via standard input (stdin) til input af det kaldte program.
  5. CGI-applikationen udfører alle de nødvendige operationer og genererer resultaterne som HTML.
  6. Den genererede hypertekst returneres til webserveren via standardoutputstrømmen (stdout). Fejlmeddelelser sendes via stderr.
  7. Webserveren videregiver resultaterne af anmodningen til klienten.

Dataudvekslingsmekanismer

  • gennem miljøvariabler;
  • via kommandolinjen;
  • via standard input;
  • via standardudgang.

miljøvariabler

Ved opstart eksternt program serveren opretter specifikke miljøvariabler, hvorigennem den transmitterer både serviceinformation og data til applikationen. Alle variabler kan opdeles i generelle miljøvariabler, som genereres til enhver form for anmodning, og anmodningsorienterede variabler.

Generelle miljøvariabler

  • SERVER_SOFTWARE - definerer navnet og versionen af ​​serveren.
  • SERVER_NAME - definerer serverens domænenavn.
  • GATEWAY_INTERFACE - bestemmer interfaceversionen.

Forespørgselsorienterede miljøer

  • SERVER_PROTOCOL - serverprotokol. Generelt blev CGI udviklet ikke kun til brug i www med HTTP-protokollen, men også til andre protokoller, men det blev kun udbredt i www.
  • SERVER_PORT - definerer TCP-porten (Transmission Control Protocol), hvorigennem kommunikationen udføres. Som standard bruges port 80 til at arbejde via HTTP, men den kan omtildeles, når serveren konfigureres.
  • REQUEST_METHOD - definerer adgangsmetoden informationsressource. Dette er den vigtigste variabel i CGI. Forskellige metoder adgang bruger forskellige dataoverførselsmekanismer. Denne variabel kan tage værdierne GET, POST, HEAD osv.
  • PATH_INFO - Sender stien, en del af URL-specifikationen, til programmet, som det er angivet i klienten. I virkeligheden betyder det, at stien (script-adressen) overføres i den form, der er angivet i HTML-dokumentet.
  • PATH_TRANSLATED er det samme som PATH_INFO, men kun efter at serveren har erstattet inserts defineret i dens konfiguration.
  • SCRIPT_NAME - definerer scriptadressen som angivet af klienten.
  • QUERY_STRING - variablen bestemmer indholdet af anmodningen til scriptet.

Identifikation af brugeren og dennes maskine

  • REMOTE_HOST - domæneadresse den maskine, som anmodningen er lavet fra.
  • REMOTE_ADDR - IP-adressen på den anmodende maskine.
  • AUTH_TYPE - brugeridentifikationstype. Bruges hvis scriptet er beskyttet mod uautoriseret brug.
  • REMOTE_USER - bruges til at identificere brugeren.
  • REMOTE_IDENT - denne variabel genereres af serveren, hvis den understøtter brugeridentifikation ved hjælp af RFC-931-protokollen. Det anbefales at bruge denne variabel til den første brug af scriptet.

Variabler, der bestemmer typen og længden af ​​information, der overføres fra klient til server

  • CONTENT_TYPE - definerer MIME-typen for data, der sendes til scriptet. Ved at bruge denne variabel kan du behandle med ét script forskellige formater data.
  • CONTENT_LENGTH - bestemmer størrelsen af ​​de data i bytes, der sendes til scriptet. Denne variabel er ekstremt vigtig, når der udveksles data ved hjælp af POST-metoden, fordi der ikke er nogen anden måde at bestemme størrelsen på de data, der skal læses fra standardinput.

Det er også muligt at videregive andre miljøvariabler. I dette tilfælde indledes navnet med præfikset "HTTP_". Et særligt tilfælde er repræsenteret af variabler, der genereres i hovedet på et HTML-dokument i META-tags. De sendes i meddelelseshovedet, og nogle servere kan generere miljøvariabler fra disse overskriftsfelter.

Kommandolinjeindstillinger

Kommandolinjen bruges kun til forespørgsler af typen ISIN-DEX. For HTML FORMS eller andre forespørgsler af uspecificeret type, bruges kommandolinjen ikke. Hvis serveren bestemmer, at scriptet tilgås via et ISINDEX-dokument, udtrækkes søgekriteriet fra URL'en og konverteres til kommandolinjeparametre. I dette tilfælde er parameteradskillelsestegnet "+"-symbolet. Anmodningstypen bestemmes af tilstedeværelsen eller fraværet af tegnet "=" i anmodningen. Hvis dette tegn er til stede, er anmodningen ikke en ISINDEX-anmodning; hvis der ikke er noget tegn, tilhører anmodningen ISIN-DEX-typen. Parametrene udtrukket fra anmodningen placeres i argv-arrayet af kommandolinjeparametre. I dette tilfælde er der efter udvælgelsen en transformation af alle hexadecimale tegn til deres ASCII-koder. Hvis antallet af parametre overstiger de grænser, der er angivet i kommandosproget, for eksempel i shellen, genereres kommandolinjen ikke, og data overføres kun gennem QUERY_STRING. Generelt bør du på forhånd tænke over mængden af ​​data, der sendes til scriptet og vælge den passende adgangsmetode. Størrelsen af ​​miljøvariabler er også begrænset, og hvis du skal overføre mange data, så er det bedre straks at vælge POST-metoden, dvs. overførsel af data via standard input.

Standard inputformat

Standardinput bruges, når data overføres til et script ved hjælp af POST-metoden. Mængden af ​​overførte data er specificeret af miljøvariablen CONTENT_LENGTH og datatypen af ​​variabelen CONTENT_TYPE. Hvis du har brug for at sende en anmodning som: a=b&b=c fra en HTML-formular, så CONTENT_LENGTH =7, CONTENT_TYPE =application/x-www-form-urlencoded, og det første tegn i standardinput vil være tegnet "a ”. Du skal altid huske, at serveren ikke overfører slutningen af ​​filen til scriptet, og derfor skal læsningen afsluttes i henhold til antallet af læste tegn. Senere vil vi se på eksempler på scripts og diskutere funktionerne i deres implementering i forskellige operativsystemer.

Standard outputformat

Standardoutput bruges af scriptet til at returnere data til serveren. I dette tilfælde består output af en header og selve dataene. Resultatet af scriptet kan overføres til klienten uden nogen form for transformation på serversiden, hvis scriptet sikrer konstruktionen af ​​den fulde HTTP-header, ellers modificerer serveren headeren i overensstemmelse med HTTP-specifikationen. Meddelelseshovedet skal adskilles fra meddelelsesteksten med en tom linje. Typisk angiver scripts kun tre HTTP-headerfelter: Indholdstype, Beliggenhed, Status.

Indholdstype

Angivet i det tilfælde, hvor scriptet selv genererer et dokument "on the fly" og returnerer det til klienten. I dette tilfælde er der ikke noget rigtigt dokument tilbage i serverfilsystemet. Når du bruger denne type script, skal du huske på, at ikke alle servere og klienter fungerer som forventet af scriptudvikleren. Når de angiver indholdstype: tekst/html, scanner nogle klienter således ikke den modtagne tekst for tilstedeværelsen af ​​indlejret grafik. Normalt angiver indholdstypen teksttyper tekst/almindelig og tekst/html.

Beliggenhed

Bruges til omdirigering. Nogle gange hjælper omdirigering med at overvinde server- eller klientbegrænsninger på integreret grafikbehandling eller forbehandling på serversiden. I dette tilfælde opretter scriptet en fil på disken og angiver dens adresse i Location. Serveren transmitterer således det virkelige eksisterende fil. For nylig er servere begyndt at buffere de data, der returneres til klienter, hvilket fører til at løse problemer i forbindelse med genkørsel af scripts for at indlejre grafik og aflæse computeren, der kører HTTP-serveren.

Anvendelser af CGI

Den mest almindelige opgave, som CGI bruges til, er at skabe interaktive sider, hvis indhold afhænger af brugerens handlinger. Typiske eksempler på sådanne websider er en hjemmesideregistreringsformular eller en kommentarformular. Et andet område af CGI-applikationer, der forbliver bag kulisserne for brugerinteraktion, er relateret til indsamling og behandling af kundeoplysninger: indstilling og læsning af cookies; indhentning af data om browseren og operativsystemet; tælle antallet af besøg på en webside; overvågning af webtrafik mv.

Disse muligheder leveres af, at CGI-scriptet kan forbindes til en database eller få adgang til serverens filsystem. Et CGI-script kan således gemme information i databasetabeller eller filer og hente det derfra efter anmodning, hvilket ikke kan gøres ved hjælp af HTML.

Det er vigtigt at vide, at CGI ikke er et programmeringssprog! Dette er en simpel protokol, der tillader en webserver at sende data gennem stdin og læse dem fra stdout. Derfor kan ethvert serverprogram, der er i stand til at arbejde med standard input/output-strømme, bruges som CGI-handler.

Fordele ved CGI

Mange CGI-funktioner er nu duplikeret af teknologier som DHTML, ActiveX eller Java-applets. De vigtigste fordele ved at bruge serverscripts er, at du kan være sikker på, at alle klienter (med sjældne undtagelser, normalt forbundet med blokering af adgang til visse ressourcer på firewall-niveau) vil være i stand til at arbejde med serverapplikation. Klientprogrammer kan simpelthen være deaktiveret i browseren eller slet ikke understøttet.

Ulemper ved CGI

Den største ulempe ved denne teknologi er de øgede ydelseskrav til webserveren. Faktum er, at hvert opkald til en CGI-applikation medfører, at der opstår en ny proces, med alle de medfølgende omkostninger. Hvis ansøgningen er skrevet med fejl, så er en situation mulig, når den for eksempel går i en løkke. Browseren vil afbryde forbindelsen, når timeoutet udløber, men på serversiden vil processen fortsætte, indtil administratoren tvinger den til at blive afsluttet. I denne henseende har klientscripts en betydelig fordel, fordi de udføres lokalt.

En anden ulempe ved CGI er, at webserveren er mindre sikker end andre løsninger. Forkert indstilling adgangsrettigheder til serverressourcer fra en CGI-applikation kan bringe ikke kun webserverens funktionalitet i fare, men også informationssikkerhed. Dog kan evt netværksteknologi kan per definition betragtes som potentielt usikker.