Tvangsmessig handel cgi. En kort digresjon om CGI. Hva er CGI

  • Opplæringen

God ettermiddag.
I denne artikkelen vil jeg gjerne snakke om FastCGI-protokollen og hvordan du arbeider med den. Til tross for at selve protokollen og dens implementering dukket opp tilbake i 1996, er det rett og slett ingen detaljerte manualer for denne protokollen - utviklerne skrev aldri hjelp til sitt eget bibliotek. Men for to år siden, da jeg nettopp begynte å bruke denne protokollen, hørte jeg ofte setninger som "Jeg forstår ikke helt hvordan jeg bruker dette biblioteket." Det er denne ulempen jeg vil korrigere - å skrive en detaljert veiledning for bruk av denne protokollen i et flertråds program og anbefalinger for valg ulike parametere, som kan brukes av alle.

Den gode nyheten er at metoden for å kode data i FastCGI og i CGI er den samme, bare metoden for å overføre dem endres: hvis et CGI-program bruker standard input-output-grensesnitt, så bruker et FastCGI-program sockets. Med andre ord, du trenger bare å forstå noen få funksjoner i biblioteket for å jobbe med FastCGI, og så bare bruke erfaringen med å skrive CGI-programmer, som det heldigvis er mange eksempler på.

Så i denne artikkelen skal vi se på:
- Hva er FastCGI og hvordan skiller det seg fra CGI-protokollen
- Hvorfor trenger jeg FastCGI når det allerede er mange språk for webutvikling
- Hvilke implementeringer av FastCGI-protokollen finnes?
- Hva er stikkontakter
- Beskrivelse av FastCGI-bibliotekets funksjoner
- Et enkelt eksempel på et flertråds FastCGI-program
- Enkelt Nginx-konfigurasjonseksempel
Dessverre er det veldig vanskelig å skrive en artikkel på samme måte forståelig for nybegynnere og interessant for erfarne oldtimers, så jeg vil prøve å dekke alle punktene så detaljert som mulig, og du kan ganske enkelt hoppe over de delene som ikke er interessante for deg.

Hva er FastCGI?

Du kan lese om FastCGI på Wikipedia. I et nøtteskall er det et CGI-program som kjører i en loop. Hvis et vanlig CGI-program startes på nytt for hver ny forespørsel, bruker et FastCGI-program en kø med forespørsler som behandles sekvensielt. Tenk deg nå: din 4-8 kjerneserver mottok 300-500 samtidige forespørsler. Et typisk CGI-program vil kjøre de samme 300-500 ganger. Det er åpenbart for mange prosesser - serveren din er fysisk ute av stand til å behandle dem alle på en gang. Dette betyr at du vil ende opp med en kø med prosesser som venter på prosessortidsdelen. Vanligvis vil planleggeren fordele prosessoren jevnt (så i dette tilfellet er prioriteringene til alle prosesser de samme), noe som betyr at du vil ha 300-500 "nesten klare" svar på forespørsler. Det høres ikke særlig optimistisk ut, gjør det? I FastCGI-programmet løses alle disse problemene med en enkel forespørselskø (det vil si at forespørselsmultipleksing brukes).

Hvorfor trenger jeg FastCGI når jeg allerede har PHP, Ruby, Python, Perl, etc.?

Kanskje, hovedårsaken- det kompilerte programmet vil kjøre raskere enn det tolkede. For PHP, for eksempel, er det en hel rekke akseleratorer, inkludert APC, eAccelerator, XCache, som reduserer tiden for kodetolkning. Men for C/C++ er alt dette rett og slett ikke nødvendig.
Den andre tingen du må huske er at dynamisk skriving og søppelsamleren tar opp mye ressurser. Noen ganger - mye. For eksempel tar heltallsarrayer i PHP omtrent 18 ganger mer minne (opptil 35 ganger avhengig av ulike PHP-kompileringsalternativer) enn i C/C++ for samme mengde data, så tenk på overheaden for relativt store datastrukturer.
For det tredje kan et FastCGI-program lagre data som er felles for forskjellige forespørsler. For eksempel, hvis PHP begynner å behandle en forespørsel fra bunnen av hver gang, så kan FastCGI-programmet gjøre en rekke forberedende handlinger selv før den første forespørselen kommer, for eksempel allokere minne, laste inn ofte brukte data, etc. - åpenbart kan alt dette forbedre den generelle ytelsen til systemet.
For det fjerde er skalerbarhet. Hvis mod_php antar at Apache-nettserveren og PHP er på samme maskin, kan FastCGI-applikasjonen bruke TCP-sockets. Med andre ord kan du ha en hel klynge av flere maskiner, kommunikasjon med som utføres over nettverket. Samtidig støtter FastCGI også Unix-domene-sockets, som lar deg effektivt kjøre en FastCGI-applikasjon og en webserver på samme maskin om nødvendig.
For det femte - sikkerhet. Tro det eller ei, med standardinnstillinger lar Apache deg gjøre alt under solen. For eksempel, hvis en angriper laster opp et ondsinnet skript exploit.php.jpg til et nettsted under dekke av et "uskyldig bilde" og deretter åpner det i nettleseren, vil Apache "ærlig" kjøre den ondsinnede PHP-koden. Kanskje den eneste ganske pålitelige løsningen er å fjerne eller endre alle potensielt farlige utvidelser fra navnene på nedlastede filer, i dette tilfellet - php, php4, php5, phtml, etc. Denne teknikken brukes for eksempel i Drupal - et understrek legges til alle "ekstra" utvidelser og resultatet er exploit.php_.jpg. Det skal imidlertid bemerkes at systemadministratoren kan legge til evt ytterligere utvidelse fil som en PHP-behandler, så noe .html kunne plutselig bli til et forferdelig sikkerhetshull bare fordi .php-en så stygg ut, var dårlig for SEO eller kunden ikke likte. Så hva gir FastCGI oss når det gjelder sikkerhet? For det første, hvis du bruker Nginx-webserveren i stedet for Apache, vil den ganske enkelt servere statiske filer. Punktum. Med andre ord vil exploit.php.jpg-filen bli servert "som den er", uten noen behandling på serversiden, så det vil rett og slett ikke være mulig å kjøre et ondsinnet skript. For det andre kan FastCGI-programmet og webserveren fungere under forskjellige brukere, noe som betyr at de vil ha forskjellige rettigheter til filer og mapper. For eksempel kan en webserver bare lese nedlastede filer - dette er nok til å returnere statiske data, og et FastCGI-program kan bare lese og endre innholdet i mappen med nedlastede filer - dette er nok til å laste ned nye og slette gamle filer, men tilgang direkte til de nedlastede filene selv vil ikke ha, noe som betyr oppfylle ondsinnet kode det vil han heller ikke kunne. For det tredje kan et FastCGI-program kjøres i en chroot som er forskjellig fra chrooten til webserveren. Chroot selv (endre rotkatalogen) lar deg begrense programrettighetene sterkt, det vil si øke generell sikkerhet systemet, fordi programmet rett og slett ikke vil kunne få tilgang til filer utenfor den angitte katalogen.

Hvilken webserver med FastCGI-støtte er bedre å velge?

Kort sagt, jeg bruker Nginx. Generelt er det ganske mange servere som støtter FastCGI, inkludert kommersielle, så la oss vurdere flere alternativer.
Apache er kanskje det første du tenker på, selv om det bruker mye mer ressurser enn Nginx. For eksempel, for 10 000 inaktive HTTP Keep-alive-tilkoblinger, bruker Nginx omtrent 2,5 millioner minne, noe som er ganske realistisk selv for en relativt svak maskin, og Apache blir tvunget til å opprette en ny tråd for hver ny tilkobling, så 10 000 tråder er ganske enkelt Fantastisk.
Lighttpd - Den største ulempen med denne webserveren er at den behandler alle forespørsler i en tråd. Dette betyr at det kan være problemer med skalerbarheten – du vil rett og slett ikke kunne bruke alle 4-8 kjerner av moderne prosessorer. Og for det andre, hvis nettservertråden av en eller annen grunn fryser (for eksempel på grunn av lang ventetid på svar fra harddisken), vil hele serveren fryse. Med andre ord vil alle andre klienter slutte å motta svar på grunn av en treg forespørsel.
En annen kandidat er Cherokee. I følge utviklerne fungerer det i noen tilfeller raskere enn Nginx og Lighttpd.

Hvilke implementeringer av FastCGI-protokollen finnes?

For øyeblikket er det to implementeringer av FastCGI-protokollen - libfcgi.lib-biblioteket fra skaperne av FastCGI-protokollen, og Fastcgi++ - et C++-klassebibliotek. Libfcgi har blitt utviklet siden 1996 og er ifølge Open Market veldig stabil og mer utbredt, så vi vil bruke det i denne artikkelen. Jeg vil merke meg at biblioteket er skrevet i C, den innebygde C++ "wrapperen" kan ikke kalles høyt nivå, så vi vil bruke C-grensesnittet.
Jeg tror det ikke er noen vits i å stoppe med å installere selve biblioteket - det har en makefile, så det burde ikke være noen problemer. Dessuten i populære distribusjoner dette biblioteket er tilgjengelig fra pakker.

Hva er stikkontakter?

Et generelt konsept for stikkontakter kan fås fra Wikipedia. I et nøtteskall er stikkontakter en metode for kommunikasjon mellom prosesser.
Som vi husker, i alle moderne operativsystemer bruker hver prosess sitt eget adresseområde. Operativsystemkjernen er ansvarlig for direkte tilgang til RAM, og hvis et program får tilgang til en minneadresse som ikke eksisterer (i sammenheng med et gitt program), vil kjernen returnere en segmenteringsfeil og lukke programmet. Dette er fantastisk - nå kan feil i ett program rett og slett ikke skade andre - de er så å si i andre dimensjoner. Men siden programmene har ulike adresserom, kan det heller ikke være delt data eller datautveksling. Men hva om du virkelig trenger å overføre data fra ett program til et annet? Faktisk ble sockets utviklet for å løse dette problemet - to eller flere prosesser (les: programmer) kobles til samme socket og begynner å utveksle data. Det viser seg å være et slags "vindu" inn i en annen verden - gjennom det kan du motta og sende data til andre strømmer.
Avhengig av hvilken type tilkobling som brukes, er stikkontakter forskjellige. For eksempel er det TCP-stikkontakter - de bruker vanlig nettverk for datautveksling, det vil si at programmer kan kjøres på forskjellige datamaskiner. Det nest vanligste alternativet - Unix domene sockets - er egnet for å utveksle data bare innenfor én maskin og ser ut som en vanlig bane i filsystemet, men i virkeligheten HDD ikke brukt - all datautveksling skjer i RAM. På grunn av det faktum at det ikke er nødvendig å bruke nettverksstabel, er litt raskere (omtrent 10%) enn TCP-sockets. For OS Windows gitt muffevarianten kalles et navngitt rør.
Eksempler på bruk av sockets for GNU/Linux OS finner du i denne artikkelen. Hvis du ikke har jobbet med stikkontakter før, vil jeg anbefale å sette deg inn i det – det er ikke obligatorisk, men det vil forbedre forståelsen av tingene som presenteres her.

Hvordan bruker jeg Libfcgi-biblioteket?

Så vi ønsker å lage en flertråds FastCGI-applikasjon, så la meg beskrive noen av de viktigste funksjonene.
Først av alt, må biblioteket initialiseres:
int FCGX_Init(void);
Merk følgende! Denne funksjonen må kalles før alle andre funksjoner i dette biblioteket og bare én gang (bare én gang, for et hvilket som helst antall tråder).

Deretter må vi åpne en lyttekontakt:
int FCGX_OpenSocket(const char *path, int backlog);
Stivariabelen inneholder socket-tilkoblingsstrengen. Både Unix domene sockets og TCP sockets støttes, alle nødvendig arbeid Biblioteket vil gjøre utarbeidelsen av parametere og funksjonskall selv.
Eksempel på tilkoblingsstrenger for Unix-domenekontakter:
"/tmp/fastcgi/mysocket" "/tmp/fcgi_example.bare.sock"
Jeg tror alt er klart her: du trenger bare å passere en unik bane som en streng, og alle prosesser som samhandler med kontakten må ha tilgang til den. Jeg gjentar nok en gang: denne metoden fungerer bare innenfor én datamaskin, men er noe raskere enn TCP-sockets.
Eksempel på tilkoblingsstrenger for TCP-sokler:
":5000" ":9000"
I dette tilfellet åpnes en TCP-socket på den angitte porten (i dette tilfellet henholdsvis 5000 eller 9000), og forespørsler vil bli akseptert fra enhver IP-adresse. Merk følgende! Denne metoden er potensielt usikker - hvis serveren din er koblet til Internett, vil FastCGI-programmet godta forespørsler fra en hvilken som helst annen datamaskin. Dette betyr at enhver angriper vil kunne sende en "dødspakke" til FastCGI-programmet ditt. Selvfølgelig er det ingenting bra med dette - i beste fall kan programmet ditt ganske enkelt "krasje" og resultere i et tjenestenekt (DoS-angrep, hvis du vil), i verste fall, ekstern kjøring av kode (hvis du er virkelig uheldig), så begrens alltid tilgangen til slike porter ved å bruke en brannmur (brannmur), og tilgang bør kun gis til de IP-adressene som faktisk brukes til vanlig arbeid FastCGI-programmer (prinsippet om "alt som ikke er eksplisitt tillatt" er forbudt).
Følgende er et eksempel på tilkoblingsstrenger:
"*:5000" "*:9000"
Metoden er helt lik den forrige: en TCP-kontakt åpnes for å akseptere tilkoblinger fra en hvilken som helst IP-adresse, så i dette tilfellet er det også nødvendig å konfigurere brannmuren nøye. Den eneste fordelen med en slik tilkoblingslinje er rent administrativ - alle som leser konfigurasjonsfiler en programmerer eller systemadministrator vil forstå at programmet ditt godtar tilkoblinger fra hvilken som helst IP-adresse, så alt annet likt er det bedre å foretrekke dette alternativet fremfor det forrige.
Et sikrere alternativ er å spesifisere IP-adressen eksplisitt i tilkoblingsstrengen:
"5.5.5.5:5000" "127.0.0.1:9000"
I dette tilfellet vil forespørsler bare bli akseptert fra den angitte IP-adressen (i dette tilfellet - henholdsvis 5.5.5.5 eller 127.0.0.1), for alle andre IP-adresser denne havnen(i dette tilfellet - henholdsvis 5000 eller 9000) vil bli stengt. Dette øker den generelle systemsikkerheten, så når det er mulig, bruk alltid dette tilkoblingsstrengformatet for TCP-sockets - hva om systemadministratoren "bare glemmer" å konfigurere brannmuren? Vær oppmerksom på det andre eksemplet - adressen til den samme maskinen (localhost) er angitt der. Dette lar deg lage en TCP-socket på samme maskin hvis du av en eller annen grunn ikke kan bruke Unix-domene-sockets (for eksempel fordi webserverens chroot og FastCGI-programmet chroot er i forskjellige mapper og ikke har felles filstier ). Dessverre kan du ikke spesifisere to eller flere forskjellige IP-adresser, så hvis du virkelig trenger å godta forespørsler fra flere webservere på forskjellige datamaskiner, må du enten åpne porten helt (se forrige metode) og stole på innstillingene til brannmuren din, eller bruk flere sockets på forskjellige porter. Dessuten støtter ikke libfcgi-biblioteket IPv6-adresser - tilbake i 1996 ble denne standarden nettopp født, så du må begrense appetitten til vanlige IPv4-adresser. Riktignok, hvis du virkelig trenger IPv6-støtte, er det relativt enkelt å legge det til ved å lappe FCGX_OpenSocket-funksjonen – biblioteklisensen tillater dette.
Merk følgende!Å bruke funksjonen til å spesifisere en IP-adresse når du oppretter en socket er ikke tilstrekkelig beskyttelse - IP-spoofing-angrep (erstatter IP-adressen til pakkesenderen) er mulig, så det er fortsatt nødvendig å sette opp en brannmur. Vanligvis, som et forsvar mot IP-spoofing, kontrollerer brannmuren samsvaret mellom pakkens IP-adresse og MAC-adressen nettverkskort for alle våre verter lokalt nettverk(mer presist, for kringkastingsdomenet med verten vår), og forkaster alle pakker som kommer fra Internett, returadresse som er plassert i sonen med private IP-adresser eller lokal vert (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 imidlertid fortsatt bedre å bruke denne bibliotekfunksjonen - i tilfelle en feilkonfigurert brannmur er det mye vanskeligere å sende en "dødspakke" fra en forfalsket IP-adresse enn fra noen annen, siden TCP-protokollen har innebygd beskyttelse mot IP-spoofing.
Den siste typen tilkoblingsstreng er å bruke vertens domenenavn:
"example.com:5000" "localhost:9000"
I dette tilfellet vil IP-adressen hentes automatisk basert på domenenavnet til verten du spesifiserte. Restriksjonene er fortsatt de samme - verten må ha én IPv4-adresse, ellers vil det oppstå en feil. Men gitt at kontakten opprettes en gang helt i begynnelsen av arbeidet med FastCGI, er det lite sannsynlig at denne metoden vil være veldig nyttig - dynamisk endring av IP-adressen vil fortsatt ikke fungere (mer presist, etter hver endring av IP-adressen du vil ha for å starte FastCGI-programmet på nytt). På den annen side vil kanskje dette være nyttig for relativt stort nettverk- Å huske et domenenavn er fortsatt enklere enn å huske en IP-adresse.

Den andre parameteren i backlog-funksjonen spesifiserer lengden på socket-forespørselskøen. Spesiell betydning 0 (null) indikerer standard kølengde for dette operativsystemet.
Hver gang en forespørsel kommer fra webserveren, blir en ny tilkobling plassert i denne køen som venter på å bli behandlet av vårt FastCGI-program. Hvis køen er helt full, vil alle påfølgende tilkoblingsforespørsler mislykkes - webserveren vil motta et svar som er nektet tilkobling. I prinsippet er det ikke noe galt med dette - Nginx webserver det er en kø med forespørsler, og hvis det ikke er ledige ressurser, vil nye forespørsler vente på sin tur for behandling allerede i nettserverkøen (i hvert fall til ventetiden går ut). I tillegg, hvis du har flere servere som kjører FastCGI, kan Nginx sende en slik forespørsel til en mindre belastet server.
Så la oss prøve å finne ut hva den optimale kølengden vil være. Generelt er det bedre å konfigurere denne parameteren individuelt basert på dataene belastningstesting, men vi vil prøve å anslå det mest passende området for denne verdien. Det første du trenger å vite er at den maksimale kølengden er begrenset (bestemt av operativsystemets kjerneinnstillinger, vanligvis ikke mer enn 1024 tilkoblinger). For det andre bruker køen ressurser, billige, men fortsatt ressurser, så du bør ikke gjøre den urimelig lang. Deretter, la oss si at FastCGI-programmet vårt har 8 arbeidertråder (ganske realistisk for moderne 4-8 kjerneprosessorer), og hver tråd trenger egen forbindelse- oppgaver behandles parallelt. Dette betyr ideelt sett at vi allerede har 8 forespørsler fra webserveren for å umiddelbart, uten unødvendige forsinkelser, kunne gi arbeid til alle tråder. Med andre ord, minimum forespørselskøstørrelse er antall FastCGI-programarbeidertråder. Du kan prøve å øke denne verdien med 50%-100% for å gi litt takhøyde for lasten, siden tiden for dataoverføring over nettverket er begrenset.
La oss nå bestemme den øvre grensen for denne verdien. Her må vi vite hvor mange forespørsler vi faktisk kan behandle og begrense forespørselskøen til denne verdien. Tenk deg at du har gjort denne køen for stor – så mye at kundene dine rett og slett blir lei av å vente på tur og de forlater nettstedet ditt uten å vente på svar. Det er åpenbart ikke noe godt med dette - webserveren måtte sende en forespørsel om å åpne en tilkobling, noe som i seg selv er dyrt, og deretter lukke denne tilkoblingen bare fordi FastCGI-programmet ikke hadde nok tid til å behandle denne forespørselen. Kort sagt, vi kaster bare bort prosessortid, men vi har bare ikke nok av det! Men dette er ikke det verste - det er verre når klienten nekter å motta informasjon fra nettstedet ditt allerede etter at forespørselen har begynt å bli behandlet. Det viser seg at vi må behandle en i det vesentlige ubrukelig forespørsel fullstendig, som du skjønner bare vil forverre situasjonen. Teoretisk sett kan det oppstå en situasjon der de fleste klientene ikke vil vente på svar når prosessoren din er 100 % lastet. Ikke bra.
Så la oss si at vi kan behandle én forespørsel på 300 millisekunder (det vil si 0,3 sekunder). Deretter vet vi at i gjennomsnitt forlater 50 % av besøkende en ressurs hvis en nettside tar mer enn 30 sekunder å laste. Det er klart at 50 % av misfornøyde er for mange, så vi vil begrense maksimal tid siden lastes inn på 5 sekunder. Dette betyr at en helt ferdig nettside - etter bruk av cascading style sheets og utføring av JavaScript - kan dette stadiet på et gjennomsnittlig nettsted ta 70 % av den totale innlastingstiden til en nettside. Så det er ikke mer enn 5 minutter igjen for å laste data over nettverket *0,3 = 1,5 sekunder Deretter bør du huske at html-koden, stilark, skript og grafikk overføres i forskjellige filer, og først html-koden, og deretter alt annet, men etter å ha mottatt html-koden nettleseren begynner å be om de gjenværende ressursene parallelt, slik at vi kan estimere lastetiden til html-koden som 50 % av den totale tiden for å motta data. Så vi har ikke mer enn 1,5 * 0,5 = 0,75 sekunder igjen til å behandle en forespørsel. Hvis i gjennomsnitt én tråd behandler en forespørsel på 0,3 sekunder, bør det være 0,75/0,3 = 2,5 forespørsler per tråd Siden vi har 8 arbeidertråder, bør den resulterende køstørrelsen være 2,5. Jeg vil merke meg at beregningene ovenfor er betingede - hvis du har et spesifikt nettsted, kan verdiene som brukes i beregningen bestemmes mye mer nøyaktig, men det gir fortsatt et utgangspunkt for mer optimal ytelsesjustering.

Så vi har mottatt en socket-deskriptor, hvoretter vi må tildele minne for forespørselsstrukturen. Beskrivelsen av denne strukturen 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 keep flagConnection; int appStatusrit; int listen_sock; int detached ) FCGX_Request;
Merk følgende! Etter å ha mottatt en ny forespørsel, vil alle tidligere data gå tapt, så om nødvendig langtidslagring data, bruk dyp kopiering (kopier selve dataene, ikke pekere til dataene).
Du bør vite følgende om denne strukturen:
- variablene inn, ut og feil spiller rollen som henholdsvis input-, output- og feilstrømmer. Inndatastrømmen inneholder POST-forespørselsdataene, svaret til FastCGI-programmet (for eksempel http-hoder og html-kode for nettsiden) må sendes til utdatastrømmen, og feilstrømmen vil ganske enkelt legge til en oppføring til webserveren feil logg. I dette tilfellet trenger du ikke bruke feilstrømmen i det hele tatt - hvis du virkelig trenger å logge feil, så er det kanskje bedre å bruke en egen fil for dette - overføring av data over nettverket og den påfølgende behandlingen av webserveren bruker ekstra ressurser.
- envp-variabelen inneholder verdiene til miljøvariabler satt av webserveren og http-hoder, for eksempel: SERVER_PROTOCOL, REQUEST_METHOD, REQUEST_URI, QUERY_STRING, CONTENT_LENGTH, HTTP_USER_AGENT, HTTP_COOKIE, HTTP_REFERER og så videre. Disse overskriftene er definert av henholdsvis CGI- og HTTP-protokollstandardene. Eksempler på deres bruk kan finnes i et hvilket som helst CGI-program. Selve dataene er lagret i en rekke strenger, med det siste elementet i matrisen som inneholder en null-peker (NULL) for å indikere slutten av matrisen. Hver linje (hvert element i strengmatrisen) inneholder én variabelverdi i formatet VARIABLE_NAME=VALUE, for eksempel: CONTENT_LENGTH=0 (i dette tilfellet betyr det at denne forespørselen ikke har POST-data, siden lengden er null). Hvis envp-strengmatrisen ikke inneholder overskriften du trenger, betyr det at den ikke ble overført. Hvis du ønsker å få alle variabelverdiene sendt til FastCGI-programmet, les ganske enkelt alle linjene i envp-matrisen i en løkke til du møter en peker til NULL.
Faktisk er vi ferdige med beskrivelsen av denne strukturen - du trenger ikke alle de andre variablene.

Minnet er tildelt, nå må du initialisere forespørselsstrukturen:
int FCGX_InitRequest(FCGX_Request *forespørsel, int sokk, int flagg);
Funksjonsparametrene er som følger:
request - peker til datastrukturen som skal initialiseres
sock er socket-beskrivelsen som vi mottok etter å ha kalt FCGX_OpenSocket-funksjonen. Jeg vil merke at i stedet for en ferdig deskriptor, kan du passere 0 (null) og motta en sokkel med standardinnstillinger, men for oss er denne metoden ikke i det hele tatt interessant - kontakten vil bli åpnet på en tilfeldig ledig port , som betyr at vi ikke vil kunne konfigurere weben vår riktig -server - vi vet ikke på forhånd hvor nøyaktig dataene skal sendes.
flagg - flagg. Faktisk kan bare ett flagg sendes til denne funksjonen - FCGI_FAIL_ACCEPT_ON_INTR - ikke kall FCGX_Accept_r når du bryter.

Etter dette må du få ny forespørsel:
int FCGX_Accept_r(FCGX_Request *request);
Du må legge inn forespørselsstrukturen som allerede er initialisert på forrige trinn. Merk følgende! I et flertråds program må du bruke synkronisering når du kaller denne funksjonen.
Faktisk gjør denne funksjonen alt arbeidet med sockets: først sender den et svar til webserveren på forrige forespørsel (hvis det var en), lukker den forrige datakanalen og frigir alle ressurser knyttet til den (inkludert forespørselsstrukturvariabler) , så mottar den en ny forespørsel, åpner en ny datakanal og klargjør nye data i forespørselsstrukturen for påfølgende behandling. Hvis det er en feil ved mottak av en ny forespørsel, returnerer funksjonen en feilkode som er mindre enn null.

Neste må du sannsynligvis få Miljøvariabler, for dette kan du enten behandle request->envp-arrayet selv, eller bruke funksjonen
char *FCGX_GetParam(const char *navn, FCGX_ParamArray envp);
der navn er en streng som inneholder navnet på miljøvariabelen eller http-overskriften hvis verdi du ønsker å få,
envp - en rekke miljøvariabler som er inneholdt i request->envp-variabelen
Funksjonen returnerer verdien til miljøvariabelen vi trenger som en streng. La den oppmerksomme leseren ikke bli skremt av typen misforhold mellom char ** og FCGX_ParamArray - disse typene er erklært synonymer (typedef char **FCGX_ParamArray).
I tillegg må du sannsynligvis sende et svar til webserveren. For å gjøre dette, må du bruke utgangsstrømmen for forespørsel->ut og funksjonen
int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream);
der str er en buffer som inneholder dataene som skal sendes ut, uten den avsluttende nullverdien (det vil si at bufferen kan inneholde binære data),
n - bufferlengde i byte,
stream - strømmen som vi ønsker å sende ut data til (request->out eller request->err).

Hvis du bruker standard nullterminerte C-strenger, vil det være mer praktisk å bruke funksjonen
int FCGX_PutS(const char *str, FCGX_Stream *stream);
som ganske enkelt vil bestemme lengden på strengen ved å bruke strlen(str) og call forrige funksjon. Derfor, hvis du vet lengden på strengen på forhånd (du bruker for eksempel C++ std::strings), er det bedre å bruke den forrige funksjonen av effektivitetshensyn.
Jeg vil merke meg at disse funksjonene fungerer perfekt med UTF-8-strenger, så det burde ikke være noen problemer med flerspråklige nettapplikasjoner.
Du kan også ringe disse funksjonene flere ganger mens du behandler samme forespørsel, i noen tilfeller kan dette forbedre ytelsen. Du må for eksempel sende noen stor fil. I stedet for å laste ned hele denne filen fra harddisken og deretter sende den i ett stykke, kan du begynne å sende data med en gang. Som et resultat, klienten i stedet hvit skjerm Nettleseren vil begynne å motta dataene den er interessert i, noe som rent psykologisk vil tvinge den til å vente litt lenger. Med andre ord, du får litt tid før siden lastes. Jeg vil også merke meg at de fleste ressurser (cascading style sheets, JavaScript, etc.) er angitt i begynnelsen av nettsiden, det vil si at nettleseren vil kunne analysere deler av html-koden og begynne å laste disse ressursene tidligere - enda en grunn til å vise data i deler.

Det neste du må gjøre er å behandle POST-forespørselen. For å få verdien, må du lese data fra forespørselen->in stream ved å bruke funksjonen
int FCGX_GetStr(char * str, int n, FCGX_Stream *stream);
der str er en peker til bufferen,
n - bufferstørrelse i byte,
stream - strømmen som vi leser data fra.
Størrelsen på de overførte dataene i en POST-forespørsel (i byte) kan bestemmes ved hjelp av miljøvariabelen CONTENT_LENGTH, hvis verdi, som vi husker, kan oppnås ved å bruke FCGX_GetParam-funksjonen. Merk følgende!Å lage en str-buffer basert på verdien av variabelen CONTENT_LENGTH uten noen restriksjoner er en veldig dårlig idé: enhver angriper kan sende en hvilken som helst POST-forespørsel, uansett hvor stor, og serveren din kan ganske enkelt gå tom for ledig plass RAM(det vil vise seg å være et DoS-angrep, hvis du vil). I stedet er det bedre å begrense bufferstørrelsen til en rimelig verdi (fra noen få kilobyte til flere megabyte) og kalle opp FCGX_GetStr-funksjonen flere ganger.

Den siste viktige funksjonen blinker utdata- og feilstrømmene (sender til klienten de fortsatt usendte dataene som vi klarte å plassere i utdata- og feilstrømmene) og lukker forbindelsen:
void FCGX_Finish_r(FCGX_Request *request);
Jeg vil spesielt merke meg at denne funksjonen er valgfri: FCGX_Accept_r-funksjonen sender også data til klienten og lukker gjeldende tilkobling før den mottar en ny forespørsel. Spørsmålet oppstår: hvorfor er det nødvendig? Tenk deg at du allerede har sendt klienten alle nødvendige data, og nå må du utføre noen siste operasjoner: skrive statistikk til databasen, feil i loggfilen, etc. Det er klart at tilkoblingen til klienten ikke lenger er nødvendig, men klienten (som betyr nettleseren) venter fortsatt på informasjon fra oss: hva om vi sender noe annet? Det er åpenbart at vi ikke kan ringe FCGX_Accept_r på forhånd - etter dette må vi begynne å behandle neste forespørsel. Det er i dette tilfellet at du vil trenge FCGX_Finish_r-funksjonen - den vil tillate deg å lukke gjeldende tilkobling før du mottar en ny forespørsel. Ja, vi vil kunne behandle samme antall forespørsler per tidsenhet som uten å bruke denne funksjonen, men klienten vil få svar tidligere - han trenger ikke lenger å vente på slutten av vår endelige operasjon, og det er nettopp på grunn av den høyere forespørselsbehandlingshastigheten som vi bruker FastCGI.
Dette avslutter faktisk beskrivelsen av bibliotekets funksjoner og begynner behandlingen av de mottatte dataene.

Et enkelt eksempel på et flertråds FastCGI-program

Jeg tror alt vil være klart i eksemplet. Det eneste er at utskrift av feilsøkingsmeldinger og "sove" i arbeidertråden gjøres utelukkende for demonstrasjonsformål. Når du kompilerer programmet, ikke glem å inkludere libfcgi- og libpthread-bibliotekene (gcc-kompilatoralternativer: -lfcgi og -lpthread).

#inkludere #inkludere #inkludere #include "fcgi_config.h" #include "fcgiapp.h" #define THREAD_COUNT 8 #define SOCKET_PATH "127.0.0.1:9000" //lagrer det åpne kontakthåndtaket statisk int socketId; statisk void *doit(void *a) ( int rc, i; FCGX_Request request; char *server_name; if(FCGX_InitRequest(&request, socketId, 0) != 0) ( //feil ved initialisering av forespørselsstrukturen printf("Kan ikke init request\n"); return NULL; ) printf("Forespørsel er initiert\n"); for(;;) ( static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; //prøv å motta en ny forespørsel printf("Prøv å godta ny forespørsel \n" ); pthread_mutex_lock(&accept_mutex); rc = FCGX_Accept_r(&request);< 0) { //ошибка при получении запроса printf("Can not accept new request\n"); break; } printf("request is accepted\n"); //получить значение переменной server_name = FCGX_GetParam("SERVER_NAME", request.envp); //вывести все HTTP-заголовки (каждый заголовок с ny linje) FCGX_PutS("Innholdstype: tekst/html\r\n", request.out); //mellom overskriftene og brødteksten til svaret må du skrive ut en tom linje FCGX_PutS("\r\n", request.out); //utgi brødteksten til svaret (for eksempel html-koden til nettsiden) 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 Hei! (flertrådig C, fcgiapp-bibliotek)

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

Forespørsel akseptert fra verten ", 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); //"sovner" - imitasjon av et flertrådsmiljø sleep(2); //lukk gjeldende tilkobling FCGX_Finish_r(&request); //endelige handlinger - registrering av statistikk, logging feil, etc. ) return NULL; ) int main(void) ( int i; pthread_t id; //initialiser biblioteket FCGX_Init(); printf("Lib er startet\n"); //åpne 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-konfigurasjonseksempel

Faktisk ser det enkleste eksemplet på en konfigurasjon slik ut:

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

I dette tilfellet er denne konfigurasjonen nok for riktig drift vårt FastCGI-program. De kommenterte linjene er et eksempel på arbeid med Unix-domene-sockets og spesifisering av et domenevertsnavn i stedet for en IP-adresse.
Etter å ha kompilert og kjørt programmet, og Nginx-innstillinger Jeg har en stolt inskripsjon på min lokale vertsadresse:
FastCGI Hei! (flertrådig C, fcgiapp-bibliotek)

Takk til alle som leste til slutt.

Kapittel #9.

Programmering med CGI

Å inkludere en del om CGI i en bok om databaser kan virke like rart som å inkludere et kapittel om bilreparasjon i en kokebok. For å gå til matbutikken trenger du selvfølgelig en fungerende bil, men er det hensiktsmessig å snakke om dette? En fullstendig diskusjon av CGI og webprogrammering generelt ligger utenfor denne bokens omfang, men kort introduksjon Disse emnene er nok til å utvide mulighetene til MySQL og mSQL for å presentere data på nettet.

Dette kapittelet er først og fremst ment for de som studerer databaser, men som ønsker å få litt kunnskap om webprogrammering. Hvis etternavnet ditt er Berners-Lee eller Andreessen, vil du neppe finne noe her som du ikke allerede vet. Men selv om du ikke er ny til CGI, kan det være ganske nyttig å ha en rask referanse mens du dykker ned i mysteriene til MySQL og mSQL.

Hva er CGI?

Som de fleste akronymer sier ikke Common Gateway Interface (CGI) så mye. Grensesnitt med hva? Hvor er denne porten? Hva slags fellesskap snakker vi om? For å svare på disse spørsmålene, la oss gå litt tilbake og ta en titt på WWW som helhet.

Tim Berners-Lee, en fysiker som jobbet ved CERN, kom opp med ideen om nettet i 1990, selv om planen dateres tilbake til 1988. Ideen var å gjøre det mulig for partikkelfysikkforskere å enkelt og raskt dele multimediedata - tekst , bilder og lyd - gjennom Internett. WWW besto av tre hoveddeler: HTML, URL og HTTP. HTML - Et formateringsspråk som brukes til å presentere innhold på nettet. URL - dette er adressen som brukes til å hente HTML (eller annet) innhold fra webserveren. Og endelig HTTP - det er et språk som forstås av webserveren og lar klienter be om dokumenter fra serveren.

Muligheten til å sende informasjon av alle typer over Internett var revolusjonerende, men en annen mulighet ble snart oppdaget. Hvis du kan sende hvilken som helst tekst via nettet, hvorfor kan du da ikke sende tekst opprettet av et program, og ikke hentet fra ferdig fil? Dette åpner et hav av muligheter. Et enkelt eksempel: du kan bruke et program som skriver ut nåværende tid, slik at leseren ser riktig tidspunkt hver gang de ser på siden. Flere smarte hoder ved National Center for Supercomputing Applications ( Nasjonalt senter Supercomputer Application Development - NCSA), som laget en webserver, så denne muligheten, og CGI dukket snart opp.

CGI er et sett med regler som lar programmer på en server sende data til klienter gjennom en webserver. CGI-spesifikasjonen ble ledsaget av endringer i HTML og HTTP som introduserte en ny funksjon kjent som skjemaer.

Hvis CGI tillater programmer å sende data til en klient, utvider skjemaer denne muligheten ved å la klienten sende data til det CGI-programmet. Nå kan brukeren ikke bare se gjeldende tid, men også stille klokken! CGI-former har åpnet døren til ekte interaktivitet i nettverdenen. Vanlige CGI-applikasjoner inkluderer:

  • Dynamisk HTML. Hele nettsteder kan genereres av ett CGI-program.
  • Søkemotorer som finner dokumenter som inneholder brukerspesifiserte ord.
  • Gjestebøker og oppslagstavler der brukere kan legge til meldingene sine.
  • Bestillingsskjemaer.
  • Spørreskjemaer.
  • Henter informasjon fra en database som ligger på serveren.

I påfølgende kapitler vil vi diskutere alle disse CGI-applikasjonene, så vel som noen andre. De gir alle en flott måte å koble CGI til en database, som er det vi er interessert i i denne delen.

HTML-skjemaer

Før du utforsker detaljene til CGI, er det nyttig å se på den vanligste måten sluttbrukere gir et grensesnitt til CGI-programmer på: HTML-skjemaer. Skjemaer er en del HTML-språk, gir slutt bruker Enger forskjellige typer. Data som legges inn i felt kan sendes til webserveren. Felter kan brukes til å skrive inn tekst eller være knapper som brukeren kan klikke eller sjekke. Her er et eksempel på en HTML-side som inneholder et skjema:

<НТМL><НЕАD><ТITLЕ>Min skjemaside


<р>Dette er en side med et skjema.


Skriv inn navnet ditt:



Dette skjemaet lager en streng på 40 tegn der brukeren kan skrive inn navnet sitt. Under inngangslinjen er det en knapp, når den klikkes, overføres skjemadataene til serveren. Nedenfor er skjemarelaterte koder som støttes av HTML 3.2, den mest brukte standarden i dag. Tag- og attributtnavn kan angis uansett, men vi følger den valgfrie konvensjonen om at startkoder skrives med store bokstaver og avsluttende tagger skrives med små bokstaver.


Denne taggen indikerer begynnelsen av skjemaet. En avsluttende kode er påkrevd på slutten av skjemaet

. Mellom tagger
Tre attributter er tillatt: ACTION spesifiserer URL-en eller den relative banen til CGI-programmet som dataene skal sendes til; METHOD spesifiserer HTTP-metoden som skjemaet skal sendes gjennom (dette kan være GET eller POST, men vi vil nesten alltid bruke POST); ENCTYPE spesifiserer datakodingsmetoden (denne bør kun brukes hvis du har en klar forståelse av hva du gjør).


Gir den mest fleksible måten for brukerinndata. Faktisk er det ni forskjellige typer stikkord . Typen er spesifisert av TYPE-attributtet. Det forrige eksemplet bruker to tagger : en med type SUBMIT og den andre med standard type TEXT. De ni typene er som følger:

TEKST

Et felt der brukeren kan skrive inn én tekstlinje.

PASSORD

Samme som TEKST, men teksten du skriver inn vises ikke på skjermen.

SJEKKER

En avmerkingsboks som brukeren kan velge og fjerne.

RADIO

En alternativknapp som må kombineres med minst én annen alternativknapp. Brukeren kan bare velge én av dem.

SENDE INN

En knapp som, når den klikkes, sender skjemaet til webserveren.

NULLSTILLE

En knapp som, når den klikkes, gjenoppretter skjemaet til standardverdiene.

FIL

Ligner på et tekstvindu, men krever at du skriver inn navnet på filen som skal sendes til serveren.

SKJULT

Et usynlig felt der data kan lagres.

BILDE

Ligner på SUBMIT-knappen, men du kan angi et bilde for bildet på knappen.

I tillegg til TYPE-attributt-taggene har vanligvis et NAME-attributt som assosierer dataene som er angitt i feltet med et eller annet navn. Navnet og dataene sendes til serveren i stilen verdi=verdi. I forrige eksempel ble tekstfeltet kalt fornavn . Du kan bruke VALUE-attributtet til å tilordne forhåndsdefinerte verdier til felt av typen TEXT, PASSWORD, FILE og HIDDEN. Det samme attributtet, brukt med knapper som SUBMIT eller RESET, viser den angitte teksten på dem. Felt av typen RADIO og CHECKBOX kan vises som kontrollert ved å bruke CHECKED-attributtet uten å spesifisere en verdi.

SIZE-attributtet brukes til å angi lengden på TEXT, PASSWORD og FILE-feltene. MAXLENGTH-attributtet kan brukes til å begrense lengden på innskrevet tekst. SRC-attributtet spesifiserer URL-en til bildet som brukes i IMAGE-typen. Til slutt spesifiserer ALIGN-attributtet justeringen av bildet for BILDE-typen og kan være TOP, MIDDLE, BOTTOM (standard), LEFT eller RIGHT (opp, midt, ned, venstre, høyre).

.

Samme som tag , ved taggen , og all tekst mellom taggene vil bli akseptert som standardtekst , som ligner på VALUE-attributtet for en tag . For tag

, som gir plass til å skrive inn et essay. Dataene heter "essay". En tekstblokk er 70 tegn bred og 10 linjer dyp. Mellomrom mellom tagger

kan brukes til en prøveoppgave. -->

typer "SEND" og "TILLBAKEL" henholdsvis. "SUBMIT"-knappen har en overstyrt "Enter data"-etikett, og "RESET"-knappen har en standardetikett (definert av nettleseren). Ved å klikke på "SEND"-knappen vil du sende dataene til webserveren "TILLBAKEL"-knappen vil gjenopprette dataene til dens opprinnelige tilstand, og slette alle brukerangitte data. -->




Den eneste inndatatypen vi ikke har brukt her er IMAGE-typen for taggen . Det kan brukes som en alternativ metode for innsending av skjema. Imidlertid er IMAGE-typen sjelden kompatibel med tekstbaserte og mindre responsive nettlesere, så det er lurt å unngå det med mindre nettstedet ditt har en grafisk-tung stil.

Når du har lært det grunnleggende om HTML-skjemaer, kan du begynne å lære om selve CGI.

CGI-spesifikasjon

Så hva er egentlig "reglene" som lar et CGI-program i for eksempel Batavia, Illinois, kommunisere med en nettleser i Ytre Mongolia? Den offisielle CGI-spesifikasjonen, sammen med et vell av annen informasjon om CGI, kan finnes på NCSA-serveren på http://hoohoo . ncsa.uluc.edu/cgi/. Dette kapittelet eksisterer imidlertid av denne grunn, slik at du ikke trenger å reise lenge og lete etter det selv.

Det er fire måter som CGI sender data mellom CGI-npor-rammen og webserveren, og dermed webklienten:

  • Miljøvariabler.
  • Kommandolinje.
  • Standard inndataenhet.
  • Standard utgangsenhet.

Med disse fire metodene videresender serveren alle dataene som sendes av klienten til CGI-programmet. CGI-programmet gjør deretter sin magi og sender utdataene tilbake til serveren, som videresender det til klienten.

Disse dataene er basert på Apache HTTP-serveren. Apache er den vanligste webserveren som kjører på nesten alle plattformer, inkludert Windows 9x og Windows NT. De kan imidlertid gjelde for alle HTTP-servere som støtter CGI. Noen proprietære servere, for eksempel de fra Microsoft og Netscape, kan ha tilleggsfunksjoner eller fungere litt annerledes. Siden ansiktet til nettet fortsetter å endre seg i en utrolig hastighet, er standarder fortsatt i utvikling, og det vil utvilsomt være endringer i fremtiden. Når det gjelder CGI, ser det imidlertid ut til at teknologien er etablert – på bekostning av å bli erstattet av andre teknologier, for eksempel appleter. Eventuelle CGI-programmer du skriver ved hjelp av denne informasjonen vil nesten helt sikkert kunne kjøre i mange år på de fleste webservere.

Når et CGI-program kalles opp gjennom et skjema, det vanligste grensesnittet, sender nettleseren serveren en lang streng som begynner med banen til CGI-programmet og navnet. Dette etterfølges av diverse andre data kalt baneinformasjon, som sendes til CGI-programmet gjennom miljøvariabelen PATH_INFO (Figur 9-1). Baneinformasjonen etterfølges av et "?"-tegn, etterfulgt av skjemadataene, som sendes til serveren ved hjelp av HTTP GET-metoden. Disse dataene gjøres tilgjengelig for CGI-programmet gjennom miljøvariabelen QUERY_STRING. Eventuelle data som siden sender ved hjelp av HTTP POST-metoden, som oftest brukes, vil bli sendt til CGI-programmet via standard enhet input. En typisk streng som en server kan motta fra en nettleser er vist i fig. 9-1. Program navngitt formlest i katalogen cgi-bin kalt opp av serveren med tilleggsbaneinformasjon ekstra informasjon og choice=help request-data - antagelig som en del av den opprinnelige URL-en. Til slutt sendes selve skjemadataene (teksten «CGI-programmering» i «søkeord»-feltet) via HTTP POST-metoden.

Miljøvariabler

Når serveren kjører et CGI-program, sender den først noen data som skal kjøres i form av miljøvariabler. Spesifikasjonen definerer offisielt sytten variabler, men mange flere brukes uformelt gjennom mekanismen beskrevet nedenfor, kalt HTTP_/nec/zams/n. CGI-program

har tilgang til disse variablene på samme måte som alle shell-miljøvariabler når de kjøres fra kommandolinjen. I et shell-skript, for eksempel, kan miljøvariabelen F00 nås som $F00; i Perl ser dette kallet ut som $ENV("F00"); i C - getenv("F00"); osv. Tabell 9-1 viser variablene som alltid settes av serveren - selv om de er null. I tillegg til disse variablene, blir dataene som returneres av klienten i forespørselshodet tilordnet variabler av formen HTTP_F00, der F00 er navnet på overskriften. For eksempel inkluderer de fleste nettlesere versjonsinformasjon i en overskrift kalt USEfl_AGENT. Din CGI-npor-ramma kan hente disse dataene fra HTTP_USER_AGENT-variabelen.

Tabell 9-1.CGI-miljøvariabler

Miljøvariabel

Beskrivelse

CONTENT_LENGTH

Lengde på data overført ved bruk av POST- eller PUT-metoder, i byte.

INNHOLDSTYPE

MIME-typen til dataene vedlagt ved bruk av POST- eller PUT-metodene.

GATEWAY_INTERFACE

Versjonsnummeret til CGI-spesifikasjonen som støttes av serveren.

PATH_INFO

Ytterligere baneinformasjon sendt av klienten. For eksempel for forespørselen http://www.myserver.eom/test.cgi/this/is/a/ sti?felt=grønn verdien av variabelen PATH_ INFO vil være /dette/er/en/bane.

PATH_TRANSLATED

Samme som PATH_INFO, men serveren produserer alle


Mulig oversettelse, for eksempel navneutvidelser som "-konto". »

QUERY_STRING

Alle data etter "?" i URL. Dette er også dataene som sendes når skjemaets REQ-UEST_METHOD er ​​GET.

REMOTE_ADDR

IP-adressen til klienten som sender forespørselen.

REMOTE_HOST

Vertsnavnet til klientmaskinen, hvis tilgjengelig.

REMOTE_IDENT

Hvis webserveren og klienten støtter typeidentifikasjon identd så er dette brukernavnet til kontoen som sender forespørselen.

REQUEST_METHOD

Metoden klienten bruker for å gjøre forespørselen. For CGI-programmene vi skal lage vil dette vanligvis være POST eller GET.

SERVER NAVN Vertsnavnet – eller IP-adressen hvis ikke noe navn er tilgjengelig – til maskinen som kjører webserveren.
SERVER_PORT Portnummeret som brukes av webserveren.
SERVER_PROTOCOL
Protokollen som brukes av klienten for å kommunisere med serveren. I vårt tilfelle er denne protokollen nesten alltid HTTP.
SERVER_SOFTWARE Informasjon om versjonen av webserveren som kjører CGI-programmet.

SCRIPT_NAME

Banen til skriptet som skal kjøres, som spesifisert av klienten. Kan brukes når en URL refererer til seg selv, og slik at skript referert på forskjellige steder kan utføres forskjellig avhengig av plasseringen.

Her er et eksempel på et CGI Perl-skript som skriver ut alle miljøvariablene satt av serveren, samt eventuelle arvede variabler, for eksempel PATH, satt av skallet som startet serveren.

#!/usr/bin/perl -w

skrive ut<< HTML;

Innholdstype: tekst/html\n\n

<р>Miljøvariabler

HTML

foreach (nøkler %ENV) ( skriv ut "$_: $ENV($_)
\n"; )

skrive ut<


HTML

Alle disse variablene kan brukes og til og med modifiseres av CGI-programmet ditt. Disse endringene påvirker imidlertid ikke webserveren som kjører programmet.

Kommandolinje

CGI lar argumenter sendes til CGI-programmet som kommandolinjeparametere, som sjelden brukes. Den brukes sjelden fordi dens praktiske anvendelser er få, og vi vil ikke dvele ved den i detalj. Poenget er at hvis miljøvariabelen QUERY_STRING ikke inneholder tegnet "=", vil CGI-programmet bli utført med kommandolinjeparameterne hentet fra QUERY_STRING. For eksempel, http://www.myserver.com/cgi- bin/finger?root vil kjøre fingerrot på www.minserver.com.

Det er to hovedbiblioteker som gir et CGI-grensesnitt til Perl. Den første er cgi-lib.pl Nytte cgi-lib.pl veldig vanlig fordi det lenge var det eneste store biblioteket som var tilgjengelig. Den er designet for å fungere i Perl 4, men fungerer med Perl 5. Det andre biblioteket, CGI.pm, nyere og på mange måter overlegen cgi-lib.pl. CGI.pm skrevet for Perl 5 og bruker en fullstendig objektorientert design for arbeid med CGI-data. Modul CGI.pm analyserer standardinndataenheten og QUERY_STRING-variabelen og lagrer dataene i et CGI-objekt. Programmet ditt trenger bare å lage et nytt CGI-objekt og bruke enkle metoder som paramQ for å hente dataene du trenger. Eksempel 9-2 fungerer som en kort demonstrasjon av hvordan CGI.pm tolker dataene. Alle Perl-eksempler i dette kapittelet vil bruke CGI.pm.

Eksempel 9-2. Parsing CGI-data i Perl

#!/usr/bin/perl -w

bruk CGI qw(:standard);

# CGI.pm-modulen brukes. qw(:standard) importerer

# navneområde for standard CGI-funksjoner å få

# klarere kode. Dette kan gjøres hvis i skriptet

# bare ett CGI-objekt brukes.

$mycgi = ny CGI; #Opprett et CGI-objekt som skal være inngangsporten til skjemadataene

@fields = $mycgi->param; # Hent navnene på alle utfylte skjemafelt

print header, start_html("CGI.pm test"); ft Metoder "header" og "start_html",

# sørget for

# CGI.pm, gjør det enklere å få HTML.

# "header" gir ut den nødvendige HTTP-headeren, en

#"start_html" gir ut en HTML-header med det gitte navnet,

#a er også en tag .

skrive ut "<р>Skjemadata:
";

foreach (@fields) ( skriv ut $_, ":",- $mycgi->param($_), "
"; }

# For hvert felt, skriv ut navnet og verdien oppnådd med

# $mycgi->param("feltnavn").

print end_html; # Stenografi for visning av sluttkoder "

".

Behandler inndata i C

Siden kjerne-API-ene for MySQL og mSQL er skrevet i C, vil vi ikke helt forlate C til fordel for Perl, men vi vil gi noen C-eksempler der det er aktuelt. Det er tre mye brukte C-biblioteker for CGI-programmering: cgic Tom Boutell*; cgihtml Eugene Kim og libcgi fra EIT*. Vi tror at cgic er den mest komplette og enkle å bruke. Det den derimot mangler er muligheten til å liste opp alle formvariablene når du ikke kjenner dem på forhånd. Faktisk kan det legges til med en enkel oppdatering, men det er utenfor rammen av dette kapittelet. Derfor bruker vi i eksempel 9-3 biblioteket cgihtml, for å gjenta Perl-skriptet ovenfor i C.

Eksempel 9-3.Parsing av CGI-data i C

/* cgihtmltest.c - Typisk CGI-program for å vise nøkler og deres verdier

fra data mottatt fra skjemaet */

#inkludere

#include "cgi-lib.h" /* Dette inneholder alle CGI-funksjonsdefinisjoner */

#include "html-lib.h" /* Dette inneholder "alle HTML-hjelpefunksjonsdefinisjoner */

void print_all(lliste 1)

/* Disse funksjonene sender ut dataene som sendes inn av skjemaet i samme format som Perl-skriptet ovenfor. Cgihtml har også en innebygd funksjon

Print_entries(), som gjør det samme ved å bruke HTML-listeformat. */ (

node*vindu;

/* "Node"-typen er definert i cgihtml-biblioteket og refererer til en koblet liste som lagrer alle skjemadataene. */

vindu = I.hode; /* Setter en peker til begynnelsen av skjemadataene */

while (vindu != NULL) ( /* Gå gjennom den koblede listen til det siste (første tomme) elementet */

printf(" %s:%s
\n",vindu->oppføring.navn,erstatt_ltgt(vindu->oppføring.verdi));

/* Skriv ut data. Replace__ltgt() er en funksjon som forstår HTML-kodingen av tekst og sørger for at den sendes ut riktig til klientnettleseren. */

vindu = vindu->neste; /* Flytt til neste listeelement. */

} }

int main() (

lister oppføringer; /* Peker til analyserte data*/

int status; /* Heltall som representerer status */

Html__header(); /* Hjelpe HTML-funksjon, sender ut HTML-overskriften*/

Html_begin("cgihtml test");

/* En HTML-hjelpefunksjon som skriver ut begynnelsen av en HTML-side med den angitte tittelen. */

status = read_cgi_input(&oppføringer); /* Skriver inn og analyserer skjemadata*/

Printf("<р>Skjemadata:
");

Print_all(oppføringer); /* Kaller print_all() funksjonen definert ovenfor. */

html_end(); /* HTML-hjelpefunksjon som skriver ut slutten av HTML-siden. */

Liste_clear(&oppføringer); /* Frigjør minne okkupert av skjemadata. */

returner 0; )

Standard utgangsenhet

Dataene som sendes av CGI-programmet til standardutgangsenheten leses av webserveren og sendes til klienten. Hvis skriptnavnet begynner med nph-, da sendes dataene direkte til klienten uten innblanding fra webserveren. I dette tilfellet må CGI-programmet generere riktig HTTP-header som klienten vil forstå. I ellers la webserveren generere HTTP-headeren for deg.

Selv om du ikke bruker nph-scenario, serveren må gis ett direktiv som vil fortelle den informasjon om utdataene dine. Dette er vanligvis Content-Type HTTP-headeren, men kan også være Location-headeren. Overskriften må følges av en tom linje, det vil si en linjemating eller en CR/LF-kombinasjon.

Content-Type-overskriften forteller serveren hvilken type data CGI-programmet ditt produserer. Hvis dette er en HTML-side, bør strengen være Content-Type: tekst/html. Plasseringsoverskriften forteller serveren en annen URL - eller en annen bane på samme server - hvor klienten skal henvises. Overskriften skal se slik ut: Sted: http:// www. min server. no/et annet/sted/.

Etter HTTP-hodene og en tom linje kan du sende de faktiske dataene som er produsert av programmet ditt - en HTML-side, et bilde, tekst eller noe annet. Blant CGI-programmene som følger med Apache server, Det er nph-test-cgi Og test-cgi som på en fin måte viser forskjellen mellom henholdsvis nph- og ikke-nph-stiloverskrifter.

I denne delen vil vi bruke biblioteker CGI.pm Og cgic, som har funksjoner for å sende ut både HTTP- og HTML-hoder. Dette vil tillate deg å fokusere på å sende ut det faktiske innholdet. Disse hjelpefunksjonene er brukt i eksemplene gitt tidligere i dette kapittelet.

Viktige funksjoner i CGI-skript

Du vet allerede i utgangspunktet hvordan CGI fungerer. Klienten sender data, vanligvis ved hjelp av et skjema, til webserveren. Serveren kjører CGI-programmet og sender data til det. CGI-programmet utfører sin prosessering og returnerer utdataene til serveren, som sender den videre til klienten. Nå fra å forstå hvordan CGI npor-rammer fungerer, må vi gå videre til å forstå hvorfor de er så mye brukt.

Selv om du allerede vet nok fra dette kapittelet til å kunne sette sammen et enkelt fungerende CGI-program, er det noen flere ting du trenger å vite. viktige saker før du oppretter faktisk fungerende programmer for MySQL eller mSQL. Først må du lære å jobbe med flere skjemaer. Deretter må du lære noen sikkerhetstiltak som vil forhindre at angripere ulovlig får tilgang til eller ødelegger serverfilene dine.

Lagring av staten

Statlig memorering er et viktig middel for å gi god service brukerne dine, og tjener ikke bare til å bekjempe forherdede kriminelle, slik det kan virke. Problemet er forårsaket av det faktum at HTTP er en såkalt "minneløs" protokoll. Dette betyr at klienten sender data til serveren, serveren returnerer data til klienten, og så går alle sin vei. Serveren lagrer ikke data om klienten som kan være nødvendig i etterfølgende operasjoner. Likeledes er det ingen garanti for at klienten vil beholde noen data om transaksjonen som kan brukes senere. Dette setter en umiddelbar og betydelig begrensning på bruken av World Wide Web.

Å skrive CGI med denne protokollen ligner på å ikke kunne huske en samtale. Når du snakker med noen, uansett hvor ofte du har snakket med dem før, må du presentere deg selv og se etter et felles samtaleemne. Det er ikke nødvendig å forklare at dette ikke bidrar til produktiviteten. Figur 9-2 viser at når en forespørsel når et CGI-program, er den fullstendig nytt eksemplar program som ikke har noen forbindelse med det forrige.

På klientsiden, med bruken av Netscape Navigator, dukket det opp en tilsynelatende raskt laget løsning kalt informasjonskapsler. Den består av å lage en ny HTTP-header som kan sendes frem og tilbake mellom klienten og serveren, på samme måte som Content-Type og Location-hodene. Klientens nettleser, når den mottar informasjonskapselhodet, må lagre den i informasjonskapseldata, samt navnet på domenet der denne informasjonskapselen opererer. Deretter, hver gang en URL innenfor det angitte domenet besøkes, må en cookie-header returneres til serveren for bruk av CGI-programmer på den serveren.

Informasjonskapselmetoden brukes hovedsakelig til å lagre bruker-ID. Informasjon om den besøkende kan lagres i en fil på servermaskinen. Denne brukerens unike ID kan sendes som en informasjonskapsel til brukerens nettleser, og hver gang brukeren besøker siden, sender nettleseren automatisk denne IDen til serveren. Serveren sender IDen til CGI-programmet, som åpner den tilsvarende filen og får tilgang til alle data om brukeren. Alt dette skjer ubemerket av brukeren.

Til tross for nytten av denne metoden, bruker de fleste store nettsteder den ikke som deres eneste måte å huske tilstand på. Det er en rekke årsaker til dette. For det første støtter ikke alle nettlesere informasjonskapsler. Inntil nylig støttet ikke hovednettleseren for personer med begrenset syn (for ikke å nevne personer med utilstrekkelig Internett-tilkoblingshastighet) - Lynx - informasjonskapsler. Den støtter dem fortsatt ikke "offisielt", selv om noen av dens allment tilgjengelige "sidegrener" gjør det. For det andre, og enda viktigere, knytter informasjonskapsler brukeren til en bestemt maskin. En av de store fordelene med nettet er at det er tilgjengelig fra hvor som helst i verden. Uansett hvor nettsiden din ble opprettet eller lagret, kan den vises fra hvilken som helst Internett-tilkoblet maskin. Imidlertid, hvis du prøver å få tilgang til en informasjonskapselaktivert side fra en annens maskin, vil all din personlige informasjon som vedlikeholdes av informasjonskapselen gå tapt.

Mange nettsteder bruker fortsatt informasjonskapsler for å tilpasse brukersider, men de fleste utfyller dem med et tradisjonelt grensesnitt for pålogging/passordstil. Hvis nettstedet åpnes fra en nettleser som ikke støtter informasjonskapsler, inneholder siden et skjema der brukeren skriver inn påloggingsnavnet og passordet som ble tildelt ham da han først besøkte nettstedet. Vanligvis er denne formen liten og upretensiøs, for ikke å skremme av de fleste brukere som ikke er interessert i noen personalisering, men bare ønsker å gå videre. Etter at brukeren har skrevet inn et påloggingsnavn og passord i skjemaet, finner CGI en fil som inneholder data om den brukeren, som om navnet ble sendt med en informasjonskapsel. Ved å bruke denne metoden kan brukeren registrere seg på et personlig tilpasset nettsted fra hvor som helst i verden.

I tillegg til oppgavene med å ta hensyn til brukerpreferanser og langsiktig lagring av informasjon om ham, mer subtilt eksempel huske staten levert av populære søkemotorer. Når du søker ved hjelp av tjenester som AltaVista eller Yahoo, vil du vanligvis få mange flere resultater enn det som kan vises i et lettlest format. Dette problemet løses ved å vise et lite antall resultater - vanligvis 10 eller 20 - og gi noen navigasjonsmuligheter for å se neste gruppe resultater. Selv om denne oppførselen virker normal og forventet for den gjennomsnittlige nettsurferen, er implementeringen av den ikke-triviell og krever statlig lagring.

Når en bruker først gjør et søk til en søkemotor, samler den inn alle resultatene, kanskje begrenset til en forhåndsdefinert grense. Trikset er å produsere disse resultatene i små mengder om gangen, samtidig som du husker hva slags bruker som ba om disse resultatene og hvilken porsjon han forventer neste gang. Ser vi bort fra kompleksiteten til selve søkemotoren, står vi overfor problemet med konsekvent å gi brukeren noe informasjon på én side. Tenk på eksempel 9-4, som viser et CGI-skript som skriver ut ti linjer av en fil og gir den muligheten til å se på neste eller forrige ti linjer.

Eksempel 9-4. Lagrer tilstand i et CGI-skript

#!/usr/bin/perl -w

bruk CGI;

Open(F,"/usr/dict/words") or die("Han kan ikke åpne! $!");

#Dette er filen som skal sendes ut, den kan være hva som helst.

$output = ny CGI;

sub print_range ( # Dette hovedfunksjon programmer, min $start = shift;

# Startlinjen til filen, min $count = 0;

# Peker, min $line = "";

# Gjeldende fillinje, skriv ut $output->header,

$output->start_html("Min ordbok");

# Produserer HTML med tittelen "Min ordbok", skriv ut " \n";

mens (($count< $start) and ($line = )) ( $count++; )

# Hopp over alle linjene før den første, mens (($count< $start+10) and ($line ? )) ( skriv ut $line; $count++; )

# Skriv ut de neste 10 linjene.

min $newnext = $start+10; min $newprev = $start-10;

# Angi innledende strenger for "Neste" og "Forrige" URL-er,

skrive ut "

";

med mindre ($start == 0) ( # Inkluder "Forrige" URL med mindre du

# er ikke lenger i begynnelsen.

print qq%Forrige%; )

med mindre (eof) ( # Inkluder "Neste" URL med mindre du # ikke på slutten av filen.

print qq%Next%;

}

skriv ut "HTML;

HTML

exit(0); )

# Hvis det ikke er data, start på nytt,

if (ikke $output->param) (

&print_range(0); )

# Ellers, start fra linjen spesifisert i dataene.

&print_range($output->param("start"));

I dette eksemplet lagres tilstanden ved hjelp av den enkleste metoden. Det er ingen problemer med å lagre data, siden vi holder dem i en fil på serveren. Vi trenger bare å vite hvor vi skal starte utdata, så skriptet inkluderer ganske enkelt startpunktet for neste eller forrige gruppe med linjer i URL-en - alt som trengs for å generere neste side.

Men hvis du trenger mer enn bare muligheten til å bla gjennom en fil, kan det være tungvint å stole på en URL. Du kan lindre denne vanskeligheten ved å bruke et HTML-skjema og inkludere tilstandsdata i tagger type SKJULT. Denne metoden har blitt brukt med suksess på mange nettsteder, slik at koblinger kan lages mellom relaterte CGI-programmer eller utvide bruken av et enkelt CGI-program, som i forrige eksempel. I stedet for å lenke til bestemt objekt, for eksempel hjemmesiden, kan URL-dataene peke til en automatisk generert bruker-ID.

Slik fungerer AltaVista og andre søkemotorer. Det første søket genererer en bruker-ID, som er skjult bak kulissene i påfølgende URL-er. Tilknyttet denne IDen er én eller flere filer som inneholder resultatene av spørringen. Nettadressen inneholder ytterligere to verdier: din nåværende posisjon i resultatfilen og retningen du vil navigere videre i den. Disse tre verdiene er alt du trenger for å få det til å fungere kraftige systemer navigering av store søkemotorer.

Det er imidlertid fortsatt noe som mangler. Filen som ble brukt i vårt eksempel /usr/diett/ord veldig stor. Hva om vi gir opp halvveis i lesingen, men ønsker å komme tilbake til det senere? Hvis du ikke husker URL-en til neste side, er det ingen måte å gå tilbake på, ikke engang AltaVista vil tillate det. Hvis du starter datamaskinen på nytt eller bruker en annen datamaskin, vil du ikke kunne gå tilbake til de tidligere søkeresultatene uten å gå inn i søket på nytt. Imidlertid er denne langsiktige tilstandslagringen kjernen i nettsidetilpasningen vi diskuterte ovenfor, og det er verdt å se på hvordan den kan brukes. Eksempel 9-5 er en modifisert versjon av eksempel 9-4.

Eksempel 9-5. Stabil tilstand memorering

#!/usr/bin/perl -w

bruk CGI;

umask 0;

Open(F,"/usr/dict/words") or die("Han kan ikke åpne! $!");

Chdir("brukere") or die("Jeg kan ikke gå til katalogen $!");

# Dette er katalogen der alle data vil bli lagret

# om brukeren.

Soutput = ny CGI;

if (ikke $output->param) (

skriv ut $output->header,

$output->start_html("Min ordbok");

skriv ut "HTML;


<р>Skriv inn brukernavnet ditt:


HTML

exit(0); )

$user = $output->param("brukernavn");

## Hvis det ikke er noen brukerfil, opprett den og installer den

## startverdi er "0",

if (ikke -e "$user") (

open (U, ">$user") or die("Jeg kan ikke åpne! $!");

skriv ut U "0\n";

lukke U;

&print_range("0");

## hvis brukeren eksisterer og ikke er spesifisert i URL-en

## startverdi, les siste verdi og start derfra.

) elsif (ikke $output->param("start")) (

Open(U,"Suser") or die("Jeg kan ikke åpne brukeren! $!");

$start = ; lukke U;

chomp $starl;

uprint range($start);

## Hvis brukeren eksisterer og ikke er spesifisert i URL-en

## startverdi, skriv ned startverdi

## til brukerfilen og start utdata.

)ellers(

Open(U,">$user") or die("Jeg kan ikke åpne brukeren for å skrive! $!");

print U $output->param("start"), "\n";

lukke U;

&print_range($output->param("start 1)); )

sub print_range(

min $start = skift;

min $telling = 0;

min $line = " "

skriv ut $output->header,

$output->start_html(" Min ordbok ");

skrive ut "

\n"; 

mens (($count< $start) and ($line = )) ( $count++; )

mens (($count< $start+10) and ($line = ))

print $line; $count++;

min $newnext = $start+10;

min $newprev = $start-10;

skrive ut "

med mindre (Sstart == 0)

{

skrive ut

qq%

Tidligere%;

}

med mindre (eof) ( print qq% Next%;

# Merk at brukernavnet "brukernavn" er lagt til URL-en.

# Ellers vil CGI-en glemme hvilken bruker den hadde å gjøre med.

}

skriv ut $output->end_html;

exit(0") ;

}

Sikkerhetstiltak

Når du bruker Internett-servere, enten de er HTTP eller andre typer servere, er sikkerhet et kritisk problem. Datautveksling mellom klient og server utført innen

CGI tar opp en rekke viktige spørsmål knyttet til databeskyttelse. Selve CGI-protokollen er ganske sikker. Et CGI-program mottar data fra serveren via standard input eller miljøvariabler, som begge er sikre metoder. Men når et CGI-program først har kontroll over dataene, er det ingen begrensninger på hva det kan gjøre. Et dårlig skrevet CGI-program kan tillate en angriper å få tilgang til serversystemet. Tenk på følgende eksempel på et CGI-program:

#!/usr/bin/perl -w

bruk CGI;

min $output = ny CGI;

mitt $brukernavn = $output»param("brukernavn");

skriv ut $output->header, $output->start_html("Fingerutgang"),

"

", "finger $brukernavn", "
", $output->end_html;

Dette programmet gir et gyldig CGI-grensesnitt til kommandoen finger. Hvis du kjører programmet bare liker finger.cgi, den vil liste alle nåværende brukere på server. Hvis du kjører det som finger.cgi?brukernavn=fred, så vil den vise informasjon om brukeren "fred" på serveren. Du kan til og med kjøre det som finger. cgi?userna-me=bob@f oo.com for å vise informasjon om den eksterne brukeren. Men hvis du kjører det som finger.cgi?brukernavn=fred;[e-postbeskyttet] Uønskede ting kan skje. Backstroke-operatoren """" i Perl skaper en shell-prosess og utfører en kommando som returnerer et resultat. I dette programmet " finger $brukernavn* brukes som en enkel måte å utføre fingerkommandoen på og få utdata. De fleste kommandoprosessorer lar deg imidlertid kombinere flere kommandoer på én linje. For eksempel gjør enhver prosessor som Bourne-prosessoren dette ved å bruke symbolet "; ""Derfor finger.cgi?brukernavn=fred; finger fred;mail vil kjøre kommandoen først deretter kommandoen post finger.cgi?brukernavn=fred; som kan sende hele serverpassordfilen til en uønsket bruker.

En løsning er å analysere skjemadataene for å se etter skadelig innhold. Du kan for eksempel se etter symbolet ";" og slett alle tegnene etter den. Det er mulig å umuliggjøre et slikt angrep ved å bruke alternative metoder. Ovennevnte CGI-program kan skrives om som følger:

#!/usr/local/bin/perl -w

bruk CGI;

min $output = ny CGI;

mitt $brukernavn = $output->param("brukernavn");

$|++;

# Deaktiver buffering for å sende alle data til klienten,

skriv ut $output->header, $putput->start_html("Fingerutgang"), "

\n"; 

$pid = open(C_OUT, "-|");# Dette Perl-idiomet skaper en underordnet prosess og åpnes

# kanal mellom foreldre- og underordnede prosesser,

if ($pid) (# Dette er den overordnede prosessen.

skrive ut ; ft Skriv ut utdataene fra den underordnede prosessen.

skrive ut "

", $output->end_html;

exit(O); ft Avslutt programmet. )

elsif (definert $pid) ( # Dette er en underordnet prosess.

$|++; # Deaktiver bufring.

exec("/usr/bin/finger",$brukernavn) eller die("exec()-kallet mislyktes.");

# Utfører fingerprogrammet med brukernavn som det eneste
# kommandolinjeargument. ) else (die("gaffel() mislyktes"); )

# Feilkontroll.

Som du kan se, er ikke dette et mye mer komplekst program. Men hvis du kjører det som for å vise informasjon om den eksterne brukeren. Men hvis du kjører det som finger.cgi?brukernavn=fred; da vil fingerprogrammet bli utført med argumentet fred;mail finger.cgi?brukernavn=fred; som ett brukernavn.

Som et ekstra sikkerhetstiltak kjører dette skriptet eksplisitt som /usr/bin/finger. I det usannsynlige tilfellet at webserveren sender CGI-programmet ditt en uvanlig PATH, kan det å kjøre bare finger føre til at feil program kjøres. Et annet sikkerhetstiltak du kan ta er å undersøke PATH-miljøvariabelen og sørge for at den har en akseptabel verdi. Det er en god idé å fjerne den gjeldende arbeidskatalogen fra PATH med mindre du er sikker på at det ikke er tilfelle der du faktisk trenger å kjøre programmet i den.

Et annet viktig sikkerhetshensyn er knyttet til brukerrettigheter. Som standard kjører webserveren CGI-programmet med rettighetene til brukeren som startet selve serveren. Dette er vanligvis en pseudobruker som "ingen" som har begrensede rettigheter, så CGI-programmet har få rettigheter heller. Dette er vanligvis en god ting, for hvis en angriper kan få tilgang til serveren gjennom et CGI-program, vil han ikke kunne gjøre mye skade. Eksemplet med et program for å stjele passord viser hva som kan gjøres, men den faktiske skaden på systemet er vanligvis begrenset.

Men å kjøre som en begrenset bruker begrenser også mulighetene til CGI. Hvis et CGI-program trenger å lese eller skrive filer, kan det bare gjøre det der det har slik tillatelse. For eksempel, i det andre eksemplet på lagringstilstand, opprettholdes en fil for hver bruker. CGI-programmet må ha lese- og skrivetillatelse på katalogen som inneholder disse filene, for ikke å snakke om selve filene. Dette kan gjøres ved å opprette katalogen som samme bruker som serveren, med lese- og skriverettigheter kun for den brukeren. For en bruker som "ingen" har imidlertid bare root denne muligheten. Hvis du ikke er en superbruker, må du kommunisere med systemadministratoren hver gang du gjør en endring i CGI.

En annen måte er å gjøre katalogen fri til å lese og skrive, og i hovedsak fjerne all beskyttelse fra den. Siden disse filene kun kan nås fra omverdenen gjennom programmet ditt, er ikke faren så stor som den kan virke. Men hvis en feil oppdages i programmet, vil den eksterne brukeren ha full tilgang til alle filer, inkludert muligheten til å ødelegge dem. I tillegg vil legitime brukere som kjører på serveren også kunne endre disse filene. Hvis du skal bruke denne metoden, må alle brukere av serveren være pålitelige. Bruk også den åpne katalogen kun for filer som trengs av CGI-programmet; med andre ord, ikke utsett unødvendige filer i fare.

Hvis dette er første gang du går inn i CGI-programmering, er det en rekke måter du kan fortsette å utforske. Dusinvis av bøker er skrevet om dette emnet, hvorav mange ikke antar noen kunnskap om programmering. "CGI-programmering på World Wide Web" utgitt av O"Reilly and Associates, dekker materiale fra enkle skript på forskjellige språk til virkelig fantastiske triks og triks. Offentlig informasjon er også tilgjengelig i overflod på WWW. Et godt sted å starte er CGI gjort veldig enkelt(Egentlig bare om CGI) kl http://www.jmarshall.com/easy/cgi/ .

CGI og databaser

Siden begynnelsen av Internett-æraen har databaser samhandlet med utviklingen av World Wide Web. I praksis ser mange mennesker på nettet som bare én gigantisk database med multimedieinformasjon.

Søkemotorer gir et hverdagslig eksempel på fordelene med databaser. Søkemotoren går ikke rundt på hele Internett og leter etter søkeord i det øyeblikket du ber om dem. I stedet bruker nettstedsutviklere andre programmer for å lage en gigantisk indeks som fungerer som en database som søkemotoren henter oppføringer fra. Databaser lagrer informasjon i en form som tillater rask, tilfeldig tilgang.

Fordi de er flytende, gir databaser nettet enda mer kraft: de gjør det til et potensielt grensesnitt for hva som helst. Systemadministrasjon kan for eksempel gjøres eksternt via et webgrensesnitt i stedet for å kreve at en administrator logger inn på ønsket system. Å koble databaser til nettet er kjernen i et nytt nivå av interaktivitet på Internett.

En av grunnene til å koble databaser til nettet gjør seg jevnlig kjent: mye av verdens informasjon er allerede i databaser. Databaser som er før nettet kalles eldre databaser (i motsetning til ikke-netttilkoblede databaser som er opprettet i nyere tid, som bør kalles en "dårlig idé"). Mange selskaper (og til og med enkeltpersoner) står nå overfor utfordringen med å gi tilgang til disse eldre databasene via nettet. Med mindre den gamle databasen din er MySQL eller mSQL, er dette emnet utenfor denne bokens omfang.

Som nevnt tidligere er det bare fantasien som kan begrense mulighetene for kommunikasjon mellom databaser og nettet. For tiden er det tusenvis av unike og nyttige databaser tilgjengelig fra nettet. Databasetypene som opererer utenfor disse applikasjonene varierer mye. Noen av dem bruker CGI-programmer som grensesnitt til en databaseserver som MySQL eller mSQL. Disse typene er av størst interesse for oss. Andre bruker kommersielle applikasjoner til grensesnitt med populære skrivebordsdatabaser som Microsoft Access og Claris FileMaker Pro. Andre jobber ganske enkelt med flate tekstfiler, som er de enkleste databasene som er mulig.

Ved å bruke disse tre typene databaser kan du utvikle nyttige nettsteder av enhver størrelse eller kompleksitet. Et av målene våre i løpet av de neste kapitlene vil være å bruke kraften til MySQL mSQL på nettet ved hjelp av CGI-programmering.



Gratis og åpen kildekode Perl Handlevogn og Commerce CGI-skript

Handlekurvene, inventar og oppfyllelse, e-handel (eller e-handel) Perl CGI-skript som er oppført på denne siden lar deg sette opp din egen nettbutikk på samme måte som Amazon.coms berømte nettbokhandel. Vanligvis viser skriptene dine produkter på nettstedet ditt, lar de besøkende velge og legge inn bestillinger og overføre bestillingene. Noen av skriptene er integrert med et bestemt kredittkortbestillingssystem (noen av dem kan faktisk være skrevet av en bestemt kredittkortbehandlingsleverandør som prøver å markedsføre varene deres).

Hvis du driver en nettbutikk, kan det hende du også må ha noen midler for å samle inn kredittkortbetalinger - se artikkelen Hvordan samle inn kredittkortbetalinger på nettstedet ditt, som også viser noen tredjepartshandlere som lar deg samle inn betalinger uten å måtte din egen selgerkonto. Vær oppmerksom på at noen (eller kanskje alle) selgerne som er oppført på den siden kan gi deg et bestillingssystem som du kan bruke gratis, så du trenger kanskje ikke engang å installere et handlekurvskript hvis behovene dine ikke er kompliserte.

(Tips: Hvis du får en intern serverfeil etter å ha installert et Perl-skript, kan du være interessert i denne artikkelen: Perl CGI Debugging: How to Solve a 500 Internal Server Error.)

Hvis du ikke er bundet til å bruke et Perl-skript, kan siden også være relevant for deg.

Relaterte sider

  • Driver nettstedets design bort kundene dine? Noen grunnleggende brukervennlighetstips for kommersielle nettsteder
  • Syv enkle måter å irritere besøkende på nettstedet ditt - en satirisk titt på noen brukervennlighetsfeil gjort av nye webmastere
  • Hvordan sjekke nettstedet ditt med flere nettlesere på en enkelt maskin (kontroll av kompatibilitet på tvers av nettlesere)

Gratis handlekurver, nettbutikk og Perl-skript for lagerstyring

Agora - Gratis programvare for handlekurv for e-handel

Agora lar deg tilpasse utseendet til handlekurven din ved å bruke en online CSS-manager, redigere eller installere butikkmaler, gi dynamiske oppdateringer til produktkategorier og underkategorilister, generere produktsider dynamisk fra butikkdatabasen, etc. Den har ubegrensede produktalternativer, volumpriser, ubegrensede produktkategorier, plasser et produkt i flere kategorier, flere skattesteder, tilpassbare "Fremhevede produkter"-lister, støtte for et bredt utvalg av betalingsbehandlingsporter (inkludert PayPal) og salg og lokale avgifter, støtte for fraktkostnader, inkludert internasjonal frakt, frakt etter vekt, prosentandel av total bestilling, flat rate, og så videre. Du administrerer butikken din på nett, og programvaren gir sporings- og feillogger. Du kan sette opp butikken din med enten . Programvaren er utgitt under GNU General Public License.

Interchange webbasert applikasjonsserver

Interchange er en åpen kildekode-handelsserver skrevet i Perl. For å sitere nettstedet sitt, "er det satt opp for å utføre salg, ordrebehandling, innholdsstyring, kundeservice, rapportering og analyse, personalisering, tradisjonell detaljhandel, levering av digitale varer, ombestilling av B2B-deler, ikke-kommersiell innholdsstyring, auksjoner, kontroll av ordrestatus, forsyningskjedestyring, prosjektledelse, online samarbeid og til og med en MP3 Jukebox." Det kan integreres med betalingsbehandlingstjenester, salgsstedssystemer, eksterne systemer for administrasjon av kunder, etc. Den er lisensiert under GNU General Public License.

Nettbutikk

Dette er en konfigurerbar handlekurv som lar kundene dine velge varer (og sette dem tilbake hvis de ombestemmer seg), søke etter noen kriterier osv. Det ser ut til å være utgitt under GNU General Public License, og er dermed åpen kildekode.

[Oppdater: dette skriptet ser ut til å ha blitt forlatt.] Yams er et handlekurvsystem for e-handel som bruker en MySQL-backend. Funksjonene inkluderer en produktsøkefunksjon, visning av relaterte produkter, vedvarende handlekurv, støtte for flere produkttyper, brukerregistreringssystem, sesjons-IDer for sporing, støtte for flere leveringsadresser, inntektsrapporter oppdelt etter henvisninger, fungerer som et CGI-skript eller under mod_perl, lagersporing, ordrestyringsverktøy, beregning av fraktkostnader, etc. Det krever at du har en Apache-server, MySQL, Mail::Sendmail-modul, etc.

[Oppdater: Dette skriptet ser ut til å ha blitt forlatt.] AllCommerce er et e-handels- og oppfyllelsessystem som lar deg få tilgang til lager- og ordreinformasjon. Den støtter MySQL, PostgreSQL og Oracle (dvs. du trenger en av disse databasene). Skriptet er utgitt under GNU General Public License.

Commerce.cgi

Commerce.cgi er et handlekurvsystem med en butikksjef som lar deg administrere beholdningen din (legge til, slette, redigere varer i butikkbeholdningen din). Du kan tilpasse butikkfronten din på en rekke måter: du kan kontrollere topptekster og bunntekster, knytte alternativer til visse produkter (for eksempel hvis besøkende velger en T-skjorte, vil du ha en måte for dem å velge T-skjorten størrelse), legg til bilder, legg til statiske lenker, etc. De besøkende kan også søke etter et bestemt produkt.

Andover, Massachusetts, 19. november 2003

The Commerce Group, Inc. (NYSE: CGI), den største forfatteren av privat personbilforsikring i Massachusetts og CGI Group Inc. (CGI) (TSX: GIB.A; NYSE: GIB;), en ledende leverandør av informasjonsteknologi og forretningsbehandlingstjenester, kunngjorde i dag signeringen av en seksårig kontraktsfornyelse av forretningsprosesser outsourcing (BPO) til en verdi av USD 35 millioner. CGI vil tilby full policybehandlingstjenester for Massachusetts private passasjer- og kommersielle billinjer, samt tilby CGIs CollaborativeEdge-byrågrensesnittverktøy, applikasjonsstøtte og vedlikehold, regulatorisk støtte, systemrådgivning og dokumenthåndteringstjenester.

Gerald Fels, Commerce Groups konserndirektør og finansdirektør, uttalte: "Som den ledende leverandøren av private passasjerbiler i Massachusetts, er målet vårt å gi våre agenter og ansatte tjenester som hjelper dem å prestere på sitt høyeste nivå. Gjennom årene har vi fostret et sterkt forhold til CGI. Systemet deres er robust og nøyaktig, og teamet deres er godt kjent med våre interne prosesseringssystemer. Det er viktig for oss."

Serge LaPalme, president, forsikringsforretningstjenester for CGI la til: "Vi er veldig glade for å fortsette vårt forhold til Commerce Group, et som strekker seg over 30 år. Commerce Group fortsetter å være en av våre verdsatte forretningspartnere og er strategisk for å vår suksess Når vi hjelper kunden vår med å fokusere ytterligere på deres kjernevirksomhet, drar vi nytte av nye teknologier når og hvor det er fornuftig å tilpasse eksisterende løsninger til denne sektoren i stadig utvikling."

Om The Commerce Group, Inc.

The Commerce Group, Inc., et forsikringsholdingselskap, har hovedkontor i Webster, Massachusetts. Commerce Groups datterselskaper for eiendoms- og skadeforsikring inkluderer The Commerce Insurance Company og Citation Insurance Company i Massachusetts, Commerce West Insurance Company i California og American Commerce Insurance Company i Ohio. Gjennom datterselskapenes kombinerte forsikringsaktiviteter er Commerce Group rangert som den 22. største personlige bilforsikringsgruppe i landet av A.M. Best, basert på direkte skriftlig premieinformasjon fra 2002.

Om CGI
Grunnlagt i 1976, er CGI det femte største uavhengige infoi Nord-Amerika, basert på antall ansatte. CGI og dets tilknyttede selskaper sysselsetter 20 000 fagfolk. CGIs årlige inntektsløpsrate er for tiden 2,8 milliarder CDN (1,9 milliarder USD) og 30. september 2003 var CGIs ordrereserve på 12,3 milliarder USD (9,1 milliarder USD). CGI leverer ende-til-ende IT- og forretningsprosesstjenester til kunder over hele verden fra kontorer i Canada, USA og Europa. CGIs aksjer er notert på TSX (GIB.A) og NYSE (GIB) og er inkludert i TSX 100 Composite Index samt S&P/TSX Canadian Information Technology og Canadian MidCap-indekser: .

Eiere av nettbutikker er kjent med konseptet "elektronisk handel" de vet allerede svaret på spørsmålet "e-handel - hva er det?" Men hvis du kommer til bunns i det, dukker det opp mange nyanser og dette begrepet får en bredere betydning.

E-handel: hva er det?

Det generelle konseptet er som følger: e-handel forstås som en viss tilnærming til å drive forretning, som innebærer inkludering av en rekke operasjoner som bruker digital dataoverføring i levering av varer eller levering av tjenester/arbeid, inkludert bruk av Internett.

Det er altså enhver kommersiell transaksjon som utføres ved hjelp av et elektronisk kommunikasjonsmiddel.

Arbeidsordningen er innrettet som følger:

  • hvem som helst kan være blogger eller en annen eier av sin egen internettside) registrerer seg i dette systemet;
  • får sin egen lenke;
  • plasserer en spesiell kode på nettsiden sin - en annonse for den valgte offisielle partneren til e-Commerce Partners Network vises;
  • overvåker nettstedkonvertering;
  • tjener en viss prosentandel for hvert kjøp av en besøkende på nettstedet ditt som følger en tilknyttet lenke.

WP e-handel

Et stort antall mennesker brenner nå for e-handel, først og fremst på grunn av ønsket om å lage sin egen nettside, en unik nettbutikk for å selge sine egne produkter. For å møte denne økende etterspørselen har utviklere fokusert på å lage e-handelsmaler. La oss se på hva dette er neste.

Et slikt eksempel på mal er WordPress e-handel. Det er en handlekurv-plugin for WordPress (et av de mest kjente webressursstyringssystemene), først og fremst beregnet på å lage og organisere blogger). Den tilbys helt gratis og lar besøkende på nettstedet foreta kjøp på nettstedet.

Med andre ord lar denne plugin deg lage en nettbutikk (basert på WordPress). Denne e-handelspluginen har alle nødvendige verktøy, innstillinger og alternativer for å dekke moderne behov.