Argumentide edastamine programmile. Peamised funktsiooni parameetrid (argc, argv)

Htaccess on valikuline konfiguratsioonifail Apache, mis võimaldab seadistada veebiserveri iga üksiku kataloogi jaoks ilma globaalseid katalooge mõjutamata Apache seaded. Kohalik analoogia httpd.conf. Tavaliselt vastutab ta ümbersuunamiste ja kataloogidele juurdepääsu juhtimise eest.

Nimi algab punktiga. Võime öelda, et see on pealkirjata fail htaccess-laiendiga.

Htaccessi sätted mõjutavad kataloogi, kus see asub, ja kõiki alamkatalooge. Looge fail ja asetage see vajalikku kataloogi. Näiteks projekti juurteni.

Nüüd peate selle täitma. Vaatame, mida .htaccess suudab, kuid kõigepealt uurime lihtsa ümbersuunamise näidet.

mod_rewrite ja ümbersuunamised

Kontrollige seda oma Apache konfiguratsioonifailis httpd.conf aktiveeritud mod_rewrite. See tähendab, et vastav rida on kommenteerimata:

LoadModule rewrite_module modules/mod_rewrite.so

Või kui te ei soovi sisse avada tekstiredaktor faili, saate terminalis kasutada käsku:

Sudo a2enmod ümberkirjutamine

mod_rewrite on Apache moodul, mis on mõeldud URL-ide muutmiseks. Vaatame selle toimimise näidet. Oletame, et kasutaja sisestab järgmise aadressi:

Kasutades mod_rewrite'i, saate saata sisu teiselt URL-ilt, näiteks järgmiselt:

Http://www.example.com/public/src/view/page.html

Miks me seda vajame? Lihtne on arvata, mida kirjutada täis tee lehele jõudmine on pikk ja lihtsalt ebamugav. Veebisaidi külastajad ei pea sellele mõtlema sisemine struktuur sait – on oluline, et nad jõuaksid võimalikult kiiresti otsitavale lehele.

IN aadressiriba kasutaja näeb endiselt, mida ta sisestas:

http://www.example.com/page.html

See on näide kõige lihtsamast ümbersuunamisest.

Otse harjutama

Analüüsime ühes meie projektis kasutatud konfiguratsioonifaili. Nii saame aru, millist rida probleemide ilmnemisel muuta.

Php_value short_open_tag 1 php_value upload_max_file size 10M php_value post_max_size 10M RewriteEngine On RewriteBase / RewriteRule ^(rakendus|moodulid|süsteem) - RewriteCond %(REQUEST_FILENAME) Rewrite_NAME) Rewrite_NAME. * index.php/$0

  • php_value seadistusstring ja arvväärtusi
  • php_lipp määrab tõeväärtused (jah/ei)

Ülddirektiiv süntaks

Php_väärtus/php_lipp direktiivi_nimi php lipp/väärtus

direktiiv short_open_tag võimaldab PHP-koodi vormindamiseks kasutada lühikest süntaksit:

Php_value short_open_tag 1

üleslaadimise_maksimaalne_failisuurus määratleb maksimaalne suurus allalaaditud fail.

Php_value upload_max_file size 10M

A posti_maksimaalne_suurus määrab saadetavate andmete maksimaalse lubatud suuruse POST meetod.

Php_value post_max_size 10M

RewriteEngine

Lülitab mehhanismi sisse/välja mod_rewrite.

RewriteEngine sees

RewriteRule

RewriteRule muudab stringi lihtsalt regulaaravaldiste järgi.

Süntaks: RewriteRule regulaaravaldis

# Sisend RewriteRule "index.php" RewriteRule ^index.php main.php [R] # Väljund: "index.php" -> "main.php"

Teisendasime index.php failiks main.php ja teostasime ümbersuunamise.

Tähtis: RewriteRule kasutab tavaliselt kahte argumenti: Mida tuleb välja vahetada ja milleks vaja välja vahetada. Kui me ei pea asendust teostama, saame selle kirjutada kujul:

Sümbol "-" tähendab "ärge teisenda"

RewriteBase

Pärast kõiki RewriteRules jõustub RewriteBase. Kui pärast teisendusi saadud päring on suhteline ja erineb algsest, taastab RewriteBase selle, muutes selle absoluutseks. RewriteBase lihtsalt lisab end vasakul olevale päringule. Kuna RewriteBase'i väärtus on tee saidi juurest .htaccess'i. Meie puhul asub .htaccess otse juurtes, seega:

Süntaks: RewriteBase URL-path-from-.htaccess-file-to-site-root

Näiteks:

# .htaccess asub kaustas /dir/ # Tee saidi juurest .htaccess'i /dir/ RewriteBase /dir/ # Päring http://example.com/dir/logo.gif # RewriteRule'i sisend on "logo.gif" RewriteRule ^ logo.gif$ logo-orange.gif # Pärast RewriteRule'i: "logo.gif" -> "logo-orange.gif" # Pärast RewriteBase'i: "logo-orange.gif" -> "/dir/logo-orange. gif"

Regulaaravaldised

Regulaaravaldised, mida failis .htaccess võib kohata.

Sümbol Tähendus Näide
. Ükskõik milline sümbol c.t on kass, võrevoodi, lõigatud jne.
+ Üks või mitu identsed tegelased a+ on a, aa, aaa jne.
* Null või mitu identsed tegelased a* töötab samamoodi nagu a+, kuid a* puhul on ka tingimus täidetud tühi rida
? Sobivus on valikuline colou?r sobib nii värvi kui ka värviga.
^ Sümbol, millest algab rida ^a vastab stringile, mis algab tähega a
$ Sümbol, mis lõpeb rida a$ vastab stringile, mis lõpeb tähega .
() Leiab ja jätab vasted meelde rühmad tegelased.

Võib kasutada ka Tagasi-viide(vaata näidet)

(ab)+ rahuldab abababi

Tagasiviite näide:

Ümberkirjutamise reegel ^/ (+) /(.*) $ /home?page= $1 &id= $2

/album/123 → /home?page= album&id= 123

Üks neist võimalikud tegelased ct sobib lõige , võrevoodi või kass.

Rohkem regulaaravaldisi

Lipud

Süntaks: RewriteRule regulaaravaldis [lipp1,lipp2,lipp3]

Lipp Kirjeldus
[F] Keelatud- tagastab vea 403 Keelatud.
[L] Viimane- peatage sellel hetkel teisendusprotsess ja ärge rakendage enam teisendusreegleid.
Päring String Lisa- see lipp näitab teisendusmehhanismi lisada, mitte asendada,päringu stringid URL-ist olemasolevasse asendusstringis.
Läbi pääsema- peatab teisendusprotsessi ja edastab vastuvõetud uus link ahelas edasi.
[R] Ümbersuunamine- peatab teisendusprotsessi ja tagastab tulemuse kliendibrauserisse ümbersuunamisena uuele lehele.
[S] Vahele jätma- igatseb järgmine reegel, kui praegune reegel toimis. Saate määrata järgnevate reeglite arvu, mida ignoreerida.

Juhtub, et andmed kantakse programmi käsurealt selle väljakutsumisel. Selliseid andmeid nimetatakse käsurea argumentideks. See näeb välja näiteks selline:

./a.out test.txt ls -lt /home/peter/

Siin kutsutakse programme a.out (alates praegune kataloog) ja ls (samast kataloogist, mis on määratud keskkonnamuutujas PATH). Esimene programm käsurealt saab ühe sõna - test.txt, teine ​​- kaks: -lt ja /home/peter/.

Kui programm on kirjutatud C-keeles, siis selle käivitamisel kantakse juhtimine kohe üle funktsioonile main(), seetõttu saab just funktsioon käsurea argumendid, mis on määratud selle parameetrimuutujatele.

Varem defineerisime funktsiooni main() nii, et see ei võta parameetreid ega tagasta midagi. Tegelikult tagastab C-keeles iga funktsioon vaikimisi (kui midagi muud pole määratletud) täisarvu. Võite selles kindel olla. Kui kirjutate koodi järgmiselt:

main() ( printf ("Tere \n") ; tagasi 0 ; )

Siis ei teki kompileerimise ajal hoiatust ega viga. Sama juhtub ka siis, kui kirjutad int main() . See tõestab, et funktsioon tagastab vaikimisi täisarvu, mitte midagi (tühine). Kuigi selle, mida funktsioon tagastab, saab alati “üle kirjutada”, näiteks voidmain() või float main() .

Programmi käsurealt kutsudes edastatakse sellele alati järgmine andmepaar:

  1. täisarv, mis näitab sõnade arvu (tühikutega eraldatud elemendid) käsureal, kui seda kutsutakse,
  2. osuti stringide massiivile, kus on iga rida eraldi sõna käsurealt.

Pidage meeles, et ka programmi nimi ise loeb. Näiteks kui kõne näeb välja selline:

./a.out 12 2. teema

Siis on programmi esimese argumendi väärtus 4 ja stringide massiiv on määratletud kui (./a.out", "12", "theme", "2").

Pange tähele terminoloogiat, programmi argumente on ainult kaks (arv ja massiiv), kuid käsurea argumente nii palju kui soovite. Käsurea argumendid "teisendatakse" programmi argumentideks (funktsiooni main() argumentideks).
Need andmed (number ja osuti) edastatakse programmile ka siis, kui seda lihtsalt nimepidi kutsutakse, ilma et sellele midagi edastataks: ./a.out. Sel juhul on esimese argumendi väärtus 1 ja teine ​​osutab massiivile, mis koosneb ainult ühest reast (./a.out").

See, et andmed edastatakse programmi, ei tähenda, et funktsioon main() peab neid aktsepteerima. Kui funktsioon main() on defineeritud ilma parameetriteta, ei pääse käsurea argumentidele juurde. Kuigi miski ei takista neid edastamast. Viga ei tule.

Programmile edastatud andmetele ligipääsemiseks tuleb need määrata muutujatele. Kuna argumendid edastatakse kohe main()-le, peaks selle päis välja nägema järgmine:
peamine (int n, char *arr)

Esimene muutuja (n) sisaldab sõnade arvu ja teine ​​muutuja sisaldab osutit stringide massiivile. Sageli kirjutatakse teine ​​parameeter kujul **arr . Siiski on see sama asi. Tuletame meelde, et stringide massiiv ise sisaldab stringide elementidena viiteid. Ja me edastame funktsioonile massiivi esimese elemendi osuti. Selgub, et me anname kursorit osutajale, st. **arr.

Harjutus
Kirjutage selline programm:

#kaasa int main(int argc, char ** argv) ( int i; printf ("%d \n", argc) ; jaoks (i = 0 ; i< argc; i++ ) puts (argv[ i] ) ; }

See kuvab sõnade arvu käsureal, kui seda kutsutakse, ja iga sõna koos uus rida. Kutsuge seda ilma käsurea argumentideta ja argumentidega.

Programmis kasutasime parameetrimuutujaid argc ja argv. Neid nimesid on kombeks kasutada, kuid tegelikult võivad need olla mida iganes. Parem on sellest standardist kinni pidada, et teie programmid oleksid paremini arusaadavad mitte ainult teile, vaid ka teistele programmeerijatele.

Andmete programmile edastamise praktiline tähendus

Kui teil on GNU/Linuxi käsureaga kogemusi, teate, et enamikul käskudel on lülitid ja argumendid. Näiteks kataloogide sisu vaatamisel, kopeerimisel, teisaldamisel määratakse argumentidena failisüsteemi objektid, millel käsk täidetakse. Selle rakendamise omadused määratakse võtmete abil. Näiteks meeskonnas

Cp -r ../les_1 ../les_101

cp on käsu nimi, -r on lüliti ning ../les_1 ja ../les_101 on käsu argumendid.

Üldiselt kantakse programmide käivitamisel programmidele kõige sagedamini failiaadressid ja programmi täitmisprotsessi "muutjad" (need on võtmed).

Kirjutame programmi, mis avaneb kasutaja määratud käsureal kirjutatavad või lisatavad failid ja kirjutab (lisab) sinna sama teabe, mille kasutaja sisestab programmi täitmise ajal klaviatuurilt:

#kaasa #kaasa main (int argc, char ** argv) ( int i, ch; FAIL * f[ 5 ] ; if (argc< 3 || argc >7) (paneb ( "Vale parameetrite arv") ; tagastus 1 ; ) if (strcmp (argv[ 1 ] , "-w" ) != 0 && strcmp (argv[ 1 ] , "-a" ) != 0 ) ( paneb ( "Esimene parameeter võib olla -w või -a") ; tagastus 2 ; ) jaoks (i= 0 ; i< argc- 2 ; i++ ) { f[ i] = fopen (argv[ i+ 2 ] , argv[ 1 ] + 1 ) ; if (f[ i] == NULL) { printf ("Faili %s ei saa avada\n ", argv[ i+ 2 ] ) ; tagastus 3 ; ) ) while ((ch = getchar () ) != EOF) jaoks (i= 0 ; i< argc- 2 ; i++ ) putc (ch, f[ i] ) ; for (i= 0 ; i < argc- 2 ; i++ ) fclose (f[ i] ) ; return 0 ; }

Koodi selgitused:

  1. Luuakse viiest failiviidist koosnev massiiv. Seetõttu saate korraga avada mitte rohkem kui viis faili. Esimese faili failikursor salvestatakse massiivi elemendis f, teise failis f jne.
  2. Kontrollitakse käsurea argumentide arvu. Neid peaks olema vähemalt kolm, sest... esimene on programmi nimi, teine ​​on faili avamise režiim, kolmas on esimene või ainus fail, kuhu kirjutatakse. Kuna programm võimaldab avada ainult viis faili, ei tohi käsurea argumentide koguarv olla üle seitsme. Seega, kui argumentide arv on alla 3 või rohkem kui 7, siis programm lõpetab, kuna Tagastuslause põhjustab funktsiooni väljumise, isegi kui selle järel on rohkem koodi. Funktsioonilt tagastatud väärtust, mis ei võrdu 0-ga, saab ülemprotsess tõlgendada teatena, et programm lõpetas vea.
  3. Kontrollib teise käsurea argumendi kehtivust. Kui see pole ei "-w" ega "-a", tagastab tingimusavaldis teises ifis 1 (tõene). Funktsioon strcmp () võimaldab teil stringe võrrelda ja tagastab 0, kui need on võrdsed.
  4. IN silmuse jaoks failid avab määratud aadressid, mis algavad argv massiivi kolmandast elemendist. Seetõttu lisatakse i-le 2, et saada argv massiivi elemendid, alustades kolmandast. Avaldis argc-2 näitab edastatud failinimede arvu; sest argc salvestab käsurea argumentide koguarvu, millest kaks esimest ei ole failinimed.
  5. Avaldis argv+1 võimaldab teil "lõigata" alamstringi "w" (või "a") stringist "-w" (või "-a"), kuna argv on sisuliselt osuti stringi esimesele elemendile. Lisades ühe kursorile, liigutame selle massiivi järgmisele elemendile.
  6. Kui faili ei saa avada, tagastab funktsioon fopen() NULL. Sel juhul programm lõpeb.
  7. Iga kasutaja poolt klaviatuuril sisestatud märk kirjutatakse kõikidesse avatud failidesse.
  8. Lõpuks failid suletakse.

See artikkel kasvas välja ideest korraldada meie töötajate täiendkoolitus tehniline abi töötab mod_rewrite-ga. Praktika on näidanud, et pärast suure hulga venekeelsete õpikute uurimist oskavad tugimeeskonnad malliprobleeme hästi lahendada, kuid iseseisev reeglite koostamine toimub katse-eksituse meetodil. suured hulgad vead. Probleem on selles, et mod_rewrite toimimise hea mõistmine nõuab algse ingliskeelse dokumentatsiooni uurimist, millele järgneb kas täiendavad selgitused või tundidepikkune katsetamine rakendusega RewriteLog.

Artiklis kirjeldatakse mod_rewrite toimimist. Selle tööpõhimõtete mõistmine võimaldab teil selgelt mõista iga direktiivi mõju ja selgelt ette kujutada, mis toimub korraga mod_rewrite sees direktiivide töötlemisel.

Eeldan, et lugejale on juba tuttav, mis on mod_rewrite ja ma ei hakka kirjeldama selle põhitõdesid, mida on Internetist lihtne leida. Samuti tuleb märkida, et artikkel hõlmab mod_rewrite tööd selle direktiivide kasutamisel .htaccess-failis. Erinevused kontekstis töötamisel aastal välja toodud.

Niisiis, olete uurinud mod_rewrite reeglit, kompileerinud mitu RewriteRule'i ja teil on õnnestunud kohata lõputuid ümbersuunamisi, juhtumeid, kui reegel mingil põhjusel teie päringut ei taba, samuti reeglite rühma ettearvamatut toimimist, kui järgnev reegel muudab ootamatult reeglit. taotlus, mis oli eelmiste reeglitega hoolikalt ette valmistatud.

Millega RewriteRule töötab?

Esimene RewriteRule edastatakse tee, kust .htaccess asub, soovitud failini. See rida ei alga kunagi tähega "/". Järgmised ümberkirjutamise reeglid edastavad eelmiste teisenduste tulemused.

Et põhjalikult mõista, kuidas RewriteRule töötab, peate esmalt määratlema, millega see töötab. Vaatame, kuidas Apache võtab vastu stringi, mis algselt edastatakse .htaccessis RewriteRule'ile töötlemiseks.

Kui hakkate esimest korda mod_rewrite-ga töötama, eeldate loogiliselt, et see töötab linkidega. See aga ei kehti juhul, kui failis .htaccess kasutatakse mod_rewrite'i. Tegelikult ei saadeta RewriteRule'ile linki, vaid soovitud faili tee.

Apache sisearhitektuuri tõttu saab mod_rewrite toimida hetkel, kui .htaccess mängu tuleb, ainult töödeldava faili teel. Selle põhjuseks on asjaolu, et enne faili mod_rewrite saatmist võisid päringut juba muuta teised moodulid (näiteks mod_alias) ja saidil oleva faili lõplik tee ei pruugi enam algse lingiga kokku langeda. Kui mod_rewrite töötaks algse viitega, katkestaks see moodulite tegevuse, mis muutsid päringut enne seda.

Seetõttu edastatakse mod_rewrite töödeldava faili absoluutne tee. Mod_rewrite teab ka teed .htaccess-ile, kus asuvad RewriteRule reeglid. Faili tee sarnaseks lingiga, millega saidi arendaja kavatseb töötada, lõikab mod_rewrite ära .htaccess-faili osa absoluutsest teest.

Niisiis, see tee, millelt .htaccess-i tee on ära lõigatud, edastatakse esimesele ümberkirjutamisreeglile. Näiteks:

Taotlus: http://example.com/templates/silver/images/logo.gif DocumentRoot: /var/www/example.com Faili tee: /var/www/example.com/templates/silver/images/logo. gif .htaccess asub aadressil /var/www/example.com/templates/.htaccess

Esimene RewriteRule saab: silver/images/logo.gif Pange tähele: "templates/" on samuti ära lõigatud. kuidas RewriteRule töötab? Htaccess-i tee lõigatakse koos kaldkriipsuga ära. Sellel on tagajärg: rida, mis algselt RewriteRule'i töötlemisele edastatakse, ei alga kunagi tähega "/".

Oluline on meeles pidada, mida RewriteRule ei tee. See ei töötle saidi nime, skriptile edastatavaid argumente ega kogu linki, kui .htaccess ei asu saidi juurtes. Seda kõike teeb RewriteCond, mida puudutame põgusalt veidi hiljem. Niisiis:

# ei tööta - reegel algab / RewriteRule ^/index.php$ /my-index.php # ei tööta - saidi nime ei analüüsita RewriteRule RewriteRule ^example.com/.* http://www.example .com # ei tööta - lingi argumendid ei kuulu RewriteRule'i RewriteRule'i index.php\?newspage=(+) news.php?page=$1 # Töötab ainult siis, kui .htaccess asub mallidega samas kohas kaust, # näiteks saidi juuraknas . See tähendab, et kui .htaccess on templates/.htaccess , siis reegel # EI TÖÖTA, sest mod_rewrite lõikab ära tee .htaccess-ile ja rida jõuab RewriteRule # sisendisse ilma "templates/" RewriteRule ^templates/ common/yandex-money gif$ templates/shared/yad.gif

Saime aru, millega RewriteRule töötab. Nüüd vaatame, kuidas see töötab.

Kuidas RewriteRule töötab

RewriteRule muudab stringi lihtsalt regulaaravaldiste järgi ja ongi kõik. RewriteRule toimib stringi, mitte faili lingi või tee alusel.

Nagu ülalpool teada saime, sisaldab sisend RewriteRule teed .htaccess-ist soovitud failini. Nüüd on kõige mugavam võtta teedest ja linkidest abstraktne ning mõelda, millega RewriteRule töötab tavaline string. See string edastatakse RewriteRule'ist RewriteRule'ile, mida muudetakse, kui mõni RewriteRules töötas.

IN üldine vaade Peale lippude kasutamise keerukuse (mõnda neist vaatleme allpool) ja regulaaravaldiste kirjutamise keerukust (mida me selles artiklis palju ei puuduta), töötab RewriteRule VÄGA lihtsalt. Võtsime liini. Võrrelge esimese argumendi regulaaravaldisega. Kui on vaste, asendage kogu string teise argumendi väärtusega. Andis stringi edasi järgmisele RewriteRule'ile. See on põhimõtteliselt kõik. Et selgelt illustreerida, et RewriteRule töötab konkreetselt stringiga, vaadake järgmist fantastilist näidet:

# Taotlus: http://mysite.com/info.html # Esimene RewriteRule sisaldab "info.html" # Teisenda taotlus suvaliseks stringiks. RewriteRule ^info.html$ "Ma nägin augus kilpkonna. Ja see tantsis rock-n-rolli. Ja see naeratas. Kokkuvõttes oli see väga naljakas nukk." # "info.html" -> "Ma nägin kilpkonna..." # Asenda see rida väline link. RewriteRule kilpkonn https://example.com/information/index.html # "Ma nägin kilpkonna..." -> "https://example.com/information/index.html" # Asenda saidi nimi! RewriteRule ^(.*)example.com(.*)$ $1example.org$2 # "https://example.com/information/index.html" -> "https://example.org/information/index. html" # Asendage protokoll! RewriteRule ^https:(.*)$ ftp:$1 # "https://example.org/information/index.html" -> "ftp://example.org/information/index.html" # Asenda viimane link . RewriteRule ^(.*)/index.html$ $1/main.php # "ftp://example.org/information/index.html" -> "ftp://example.org/information/main.php"

Nagu näete, ei huvita RewriteRule, millega see töötab – see lihtsalt muudab stringi vastavalt sellele antud argumentidele. Soovi korral saate stringina salvestada mis tahes andmemassiivid, soovi korral püsivust ja head teadmised Regulaaravaldiste jaoks saate RewriteRule'ile kirjutada isegi tic-tac-toe.

Siinkohal tuleb märkida: kuigi RewriteRule töötab puhta stringiga, on see siiski keskendunud linkidega töötamisele. Seetõttu reageerib see erinevalt joontele, mis algavad tähega

https://

või analooge (see mäletab, et tahtsime teha välise ümbersuunamise) ja "?" (peab järgmisi märke argumentidena, mis tuleb päringu asemel asendada). Meid see aga praegu ei huvita – on oluline mõista, et RewriteRule’is pole maagiat – see võtab lihtsalt stringi ja muudab seda nii, nagu sa seda ütled. Väliseid ümbersuunamisi ja argumente käsitleme artiklis hiljem, ka seal on millest rääkida.

Kui kõik teisendused on lõpule viidud ja viimane RewriteRule on täidetud, jõustub RewriteBase.

Milleks RewriteBase'i kasutatakse?

Kui saadud päring on suhteline ja erineb algsest päringust, lisab RewriteBase end sellest vasakule. Lahtris .htaccess on vaja määrata RewriteBase. Selle väärtus on tee saidi juurest .htaccess-i. RewriteBase käivitatakse ainult pärast kõiki RewriteRules, mitte nende vahel.

Oleme juba eespool öelnud, et mod_rewrite, mis töötab .htaccessis, sisaldab soovitud faili absoluutset teed. Selle edastamiseks reeglile RewriteRule lõikab mod_rewrite ära tee .htaccess-ile. Seejärel muudavad RewriteRules taotlust järjestikku ükshaaval. Ja nüüd, pärast taotluse muutmist, peab Apache taastama faili absoluutse tee, mida ta peab lõpuks töötlema. RewriteBase on tegelikult häkkimine, mis aitab taastada faili algse tee.

RewriteBase käivitatakse pärast kõiki teisendusi. See tähendab, et see ei muuda taotlust RewriteRules'i vahel, vaid jõustub alles siis, kui kõik RewriteRules on täidetud.

Pärast kõiki teisendusi vaatab RewriteBase, kas saadud tee on suhteline või absoluutne. Apache kontekstis tähendab see suhtelist või absoluutset teed, mis algab saidi juurtest: images/logo.gif - suhteline. /images/logo.gif - absoluutne (alguses kaldkriips). http://example.com/images/logo.gif – kõige absoluutsem. Kui tee on absoluutne, ei tee RewriteBase midagi. Ja kui see on suhteline, lisab RewriteBase end vasakule. See toimib nii sisemiste kui ka väliste ümbersuunamiste puhul:

# .htaccess asub asukohas /images/ # RewriteBase on määratud /images/ RewriteBase /images/ # Päring http://example.com/images/logo.gif # RewriteRule sisend on "logo.gif" RewriteRule ^logo.gif $ logo -orange.gif # Pärast RewriteRule'i: "logo.gif" -> "logo-orange.gif" # Pärast RewriteBase'i: "logo-orange.gif" -> "/images/logo-orange.gif" # Taotle http :/ /example.com/images/header.png # RewriteRule sisend on "header.png" RewriteRule ^header.png$ /templates/rebranding/header.png # Pärast RewriteRule'i: "header.png" -> "/ templates/rebranding /header.png" # Pärast RewriteBase'i: midagi ei muutu, nii et teisenduse lõpptulemus algab tähega "/". # Taotle http://example.com/images/director.tiff # RewriteRule'i sisend on "director.tiff" # Kasutame välist suhtelist ümbersuunamist RewriteRule ^director.tiff$ staff/manager/director.tiff # Pärast RewriteRule'i: "director. tiff" -> "staff/manager/director.tiff" # + mod_rewrite tuli meelde, et tuleb väline ümbersuunamine # Pärast RewriteBase'i: "staff/manager/director.tiff" -> "/images/staff/manager/ director.tiff" # mod_rewrite jäi välise ümbersuunamise kohta meelde: # "/images/staff/manager/director.tiff" -> http://example.com/images/staff/manager/director.tiff

Tavaliselt tekib pärast mod_rewrite tundmist järgmine harjumus:

    lisage igale .htaccessile "RewriteBase /".

    Kõik ümbersuunamised algavad kaldkriipsuga: "RewriteRule news.php /index.php?act=news". See aitab RewriteBase'i artefaktidest lahti saada, kuid see on vale. Nüüd, kui teame, mida RewriteBase teeb, saame sõnastada järgmised õiged reeglid:

RewriteBase peab vastama saidi juurte teele .htaccess-i. Peate ümbersuunamisi alustama ainult märgiga "/", kui peate määrama absoluutse tee saidi juurest failini.

Mis juhtub, kui te ei määra RewriteBase'i? Vaikimisi muudab Apache selle võrdseks absoluutne tee peal failisüsteem to.htaccess (näiteks /var/www/example.com/templates/). Selle Apache'i eelduse ebaõigsus väljendub välistes suhtelistes ümbersuunamistes:

# Taotle http://example.com/index.php # DocumentRoot: /var/www/example.com/ # .htaccess asub saidi juurtes ja sellel EI ole määratud RewriteBase'i. # Seetõttu on RewriteBase vaikimisi võrdne aadressi.htaccess absoluutse teega: /var/www/example.com/ # Sisend RewriteRule on "index.php" RewriteRule ^index.php main.php [R] # Väljund on "index.php" " -> "main.php" # mod_rewrite mäletas, et on vaja välist ümbersuunamist # RewriteRule sai otsa # mod_rewrite täidab endiselt RewriteBase'i, kuna sellel on vaikeväärtus. # Selgub: "main.php" -> "/var/www/example.com/main.php" # Siin mod_rewrite mäletab, et oli väline ümbersuunamine: # "/var/www/example.com/main. php" - > http://example.com/var/www/example.com/main.php # Selgus, et see ei olnud üldse see, mida nad silmas pidasid.

Niisiis läbis päring kõik RewriteRules, misjärel lisati sellele vajadusel RewriteBase. Kas Apache peaks nüüd esitama faili, millele tulemuseks olev tee osutab? Ei. Nüüd töödeldakse saadud taotlust uuesti.

Kuidas mod_rewrite töötab. Lipp [L]

mod_rewrite alustab päringu töötlemist ikka ja jälle, kuni see ei muutu. Ja lipp [L] ei saa seda peatada.

Rohkem või vähem keerukate mod_rewrite konfiguratsioonide loomisel on oluline seda mõista päringu muutmine ei lõpe viimase RewriteRule'iga. Pärast seda, kui see töötas viimane reegel RewriteRule ja RewriteBase on lisatud, mod_rewrite vaatab, kas taotlus on muutunud või mitte. Kui päring on muutunud, algab selle töötlemine uuesti algusest.htaccess.

Apache teeb seda seetõttu, et päringu muutmise käigus võidi see teise kataloogi ümber suunata. Sellel võib olla oma .htaccess, mis ei olnud eelmise päringu töötlemisega seotud. See uus .htaccess võib sisaldada reegleid, mis mõjutavad päringu töötlemist – nii mod_rewrite reegleid kui ka teiste moodulite reegleid. Selle olukorra õigeks lahendamiseks peab Apache kogu töötlemistsükli taaskäivitama.

Oota, aga seal on lipp [L], mis peatab mod_rewrite taotluse töötlemise!

Kindlasti mitte sel viisil. Lipp [L] peatab taotluse töötlemise praeguse iteratsiooni. Kui aga taotlust muutsid need ümberkirjutamisreeglid, mida siiski õnnestus töödelda, alustab Apache päringu töötlemise tsüklit uuesti alates esimesest ümberkirjutamise reeglist.

# Taotlus: http://example.com/a.html RewriteBase / RewriteRule ^a.html$ b.html [L] RewriteRule ^b.html$ a.html [L]

Ülaltoodud näide toob kaasa lõputu ümbersuunamiste tsükli ja „Sisemine Serveri viga"lõpuks. Selles näites on lõpmatu silmus ilmne, kuid keerukamate konfiguratsioonide puhul peate võib-olla reeglitesse süvenema, et teha kindlaks, millised päringud üksteise vahel silmustuvad.

Selliste olukordade vältimiseks on soovitatav kasutada [L] lippu ainult vajaduse korral. Vajadus võib olla kahte tüüpi: kui kasutatakse välist ümbersuunamist – või . Välise ümbersuunamise korral on päringu edasine töötlemine ebasoovitav (vt lipu kohta allpool [R]) ja parem on see lõpetada. Kui failis .htaccess on silmus, mida ei saa kõrvaldada, ja päringu töötlemine mod_rewrite abil tuleb sunniviisiliselt peatada. Sel juhul kasutatakse spetsiaalset konstruktsiooni – vt selleteemalisi näpunäiteid artikli lõpus.

Kuid allolev näide ei loo silmust. Proovige kindlaks teha, miks ja milline fail Apache'ile lõpuks antakse.

# Taotlus: http://example.com/a.html # Start.htaccess RewriteBase / RewriteRule ^a.html$ b.html RewriteRule ^b.html$ a.html # End.htaccess

Lahendus: Kõikide RewriteRules'ide täitmise tulemusena muudetakse taotlust selliselt, et lõpptulemus on võrdne algse tulemusega. Apache näeb seda ega töötle taotlust uuesti. Fail a.html tagastatakse.

Kuidas mod_rewrite töötab. Lipp [R]

    Lipp [R] ei peata taotluse töötlemist, tagastades kohe välise ümbersuunamise. Selle asemel jätab see meelde välise ümbersuunamise vajaduse ja päringu töötlemine jätkub järgmise RewriteRule'iga. Soovitatav on kasutada alati koos lipuga [L].

    Lipp [R]ütleb Apache'ile, et see ei pea sooritama sisemist, vaid välist ümbersuunamist. Mis vahe on välisel ja sisemisel ümbersuunamisel? Sisemine ümbersuunamine muudab lihtsalt kasutajale antava faili teed, samal ajal kui kasutaja usub, et saab algselt taotletud faili. Välise ümbersuunamise korral tagastab Apache kasutajale faili sisu asemel vastuse oleku 301 või 302 ja teavitab kasutajat lingist, mida brauser peaks faili hankimiseks kasutama.

Näib, et lipu töötlemisel [R] Apache peaks viivitamatult lõpetama RewriteRule'i töötlemise ja tagastama kasutajale välise ümbersuunamise. Kuid meenutagem fantastilist näidet jaotisest Kuidas ümberkirjutamise reegel töötab. Selles märkisime kõigepealt lipu [R], mis viitab vajadusele välise ümbersuunamise järele, misjärel jätkasid nad lingi muutmist järgmise RewriteRule'iga.

Täpselt nii töötab Apache välise ümbersuunamise määramisel. See lihtsalt märgib endale, et pärast kõigi reeglite täitmist on vaja tagastada olek 302 (vaikimisi), kuid jätkab samal ajal kõigi loendis allpool olevate RewriteRules'ide täitmist. Saame taotlust vastavalt vajadusele muuta. Ainus asi, mis ei tööta, on ümbersuunamine tagasi sisemiseks.

Siiski on ebatõenäoline, et soovite pärast välise ümbersuunamise saatmist seda kuidagi muuta. Seetõttu on see lipu kasutamisel soovitatav [R] märkige see koos [L]:

# BlackJack on üle läinud kaunile nimele RewriteRule ^bj/(.*) blackjack/$1 # Võite kasutada lihtsalt välist linki RewriteRule ^bj/(.*) http://blackjack.example.com/$1 [L]

Lipu kasutamise asemel [R] Saate lihtsalt lisada välise lingi. Sel juhul arvab Apache ise, et on vaja teha väline ümbersuunamine. Siin nagu lipu selgesõnalise täpsustamise puhul [R], on soovitatav kasutada lippu [L]. Kui väline ümbersuunamine viib samale saidile, on parem kasutada lippu [R] ilma näidustuseta täielik link(teisisõnu kasutage suhtelist välist ümbersuunamist). See muudab reegli saidi nimest sõltumatuks. Kui väline ümbersuunamine suunab teisele saidile, ei saa seda teha teisiti kui täieliku välislingi määramisega.

Kuidas mod_rewrite töötab. Taotluse parameetrite ja lipu määramine

Päringu parameetrite muutmine rewriteRule'is ei muuda rida, millel järgmine RewriteRule töötab. Parameetrite muutmine muudab aga muutujat %(QUERY_STRING), millega RewriteCond töötada saab.

Kasutatud terminoloogia: "parameetrid" - päringu parameetrid, "argumendid" - RewriteRule'i argumendid.

RewriteRule'i abil saate muuta mitte ainult töödeldava faili teed, vaid ka parameetreid HANGI taotlus mis talle edastatakse. Seda kasutatakse sageli NC-töötluse ülekandmiseks üldisesse töötleja skripti, nt: RewriteBase /

# Taotlus: http://example.com/news/2010/07/12/grand-opening.html # Sisend: "news/2010/07/12/grand-opening.html" RewriteRule ^news/(.* ) $ index.php?act=news&what=$1 # Pärast RewriteRule'i: "news/2010/07/12/grand-opening.html" -> "index.php" # %(QUERY_STRING): "" -> "act= uudised&what =2010/07/12/grand-opening.html"

Hetkel, kui RewriteRule kohtab oma teises argumendis küsimärki, teab ta, et päringu parameetreid muudetakse. Tulemuseks on see, et RewriteRule asendab stringi, millega see töötab, osaga teisest argumendist enne küsimärk. Pange tähele, et uued päringu parameetrid ei satu stringi, mille kallal järgmised RewriteRules töötavad. Teise argumendi osa pärast küsimärki jõuab muutujasse %(QUERY_STRING). Kui määrati lipp , lisatakse päringu parameetrid päringu %(QUERY_STRING) algusesse. Kui lippu pole määratud, asendatakse %(QUERY_STRING) täielikult RewriteRule'i päringuparameetritega. Paar näidet veel:

RewriteBase / # Request: http://example.com/news/2010/?page=2 # Sisend RewriteRule: "news/2010/" RewriteRule ^news/(.*)$ index.php?act=news&what=$1 # Pärast teisendamist: "news/2010/" -> "index.php" # Väärtus %(QUERY_STRING): "page=2" -> "act=news&what=2010/" Tõenäoliselt ei tööta ülaltoodud reegel õigesti, kuna see on kadunud argumentide leht. Parandame selle: RewriteBase / # Request: http://example.com/news/2010/?page=2 # Sisend RewriteRule: "news/2010/" RewriteRule ^news/(.*)$ index.php?act= news&what=$1 # Pärast teisendamist: "news/2010/" -> "index.php" # Väärtus %(QUERY_STRING): "page=2" -> "act=news&what=2010/&page=2"

Oluline on mõista, et päringu parameetrite muutmine muudab %(QUERY_STRING), mida saab hiljem rakenduses RewriteCond kasutada. Seda tuleb arvestada järgnevate argumente kontrollivate reeglite kirjutamisel.

Loomulikult see muutub, sest päringu saadab Apache uuesti töötlemiseks!

Ei, %(QUERY_STRING) muutub kohe. Ma ei hakka tõestama - parameetritest on juba rohkem kirjutatud, kui huvitav lugeda :)

Mida saate teha, et kontrollida RewriteCondis täpselt neid päringu parameetreid, mille kasutaja edastas, mitte neid, mida RewriteRules muutis. Vaadake artikli lõpus olevaid näpunäiteid?

RewriteCond ja jõudlus

Esiteks kontrollitakse päringu vastavust RewriteRule'iga ja alles siis - lisatingimused RewriteCond.

Paar sõna tuleks öelda selle kohta, millises järjekorras mod_rewrite käskkirju täidab. Kuna .htaccess sisaldab esmalt RewriteCond ja seejärel RewriteRule, siis tundub, et mod_rewrite kontrollib kõigepealt kõiki tingimusi ja seejärel alustab RewriteRule'i täitmist.

Tegelikult juhtub kõik vastupidi. Esiteks kontrollib mod_rewrite, kas praegune päringu väärtus vastab regulaaravaldisele RewriteRule, ja alles siis kontrollib kõiki RewriteCond loetletud tingimusi.

Nii et kui teie RewriteRule'is on kaheleheküljeline regulaaravaldis ja jõudlusele mõeldes otsustate piirata selle reegli täitmist täiendavate RewriteCondidega, peaksite teadma, et miski ei tööta. Sel juhul on parem kasutada lippe RewriteRule [C] või [S], et rohkem vahele jätta keeruline reegel, kui rohkem lihtsad kontrollid ei töötanud.

RewriteCond muutujad ja lipud, muud RewriteRule lipud jne.

Lugege dokumentatsiooni.

Tutvusime RewriteRule’i, RewriteBase’i, lippude tööpõhimõtetega [L], [R] Ja ja analüüsis ka päringu töötlemise mehhanismi sees mod_rewrite. Järgmist ei mõjutanud: muud RewriteRule lipud, RewriteCond ja RewriteMap direktiivid.

Õnneks ei ole need direktiivid ja lipud tulvil mingeid saladusi ja töötavad täpselt nii, nagu enamikus õpetustes kirjeldatud. Nende mõistmiseks lugege lihtsalt ametlik dokumentatsioon. Kõigepealt soovitan uurida muutujate loendit, mida saab RewriteCondis kontrollida - %(QUERY_STING), %(THE_REQUEST), %(REMOTE_ADDR), %(HTTP_HOST), %(HTTP:header) jne)

Erinevused mod_rewrite toimimises .htaccessi ja VirtualHosti kontekstis

Kontekstis mod_rewrite töötab täpselt vastupidi.

Nagu ma artikli alguses ütlesin, puudutab kõik ülalkirjeldatud mod_rewrite kasutamist .htaccess kontekstis. Kui mod_rewrite on kasutusel , töötab see teisiti: In RewriteRule sisaldab kogu päringu teed, alustades esimesest kaldkriipsust ja lõpetades algusega GET parameetrid: "http://example.com/some/news/category/post.html?comments_page=3" → "/news/category/post.html". See rida algab alati tähega /. RewriteRule'i teine ​​argument peab samuti algama tähega /, vastasel juhul on see "Bad Request". RewriteBase'il pole mõtet. Reeglite läbimine toimub ainult üks kord. Lipp [L] tegelikult lõpetab kõigi punktis kirjeldatud reeglite töötlemise , ilma täiendavate iteratsioonideta.

Regulaaravaldiste kirjutamine

Püüdke koostada regulaaravaldisi nii, et need määratleksid kõige kitsamalt täpselt need päringud, mida soovite muuta – et RewriteRule reeglid kogemata mõne teise päringu puhul ei töötaks. Näiteks:

# Alusta kõiki regulaaravaldisi tähega "^" (rea algus) # ja lõpeta tähega "$" (rea lõpp): RewriteRule ^news.php$ index.php # Isegi kui see pole vajalik – mitmekülgsuse huvides ja konfiguratsiooni parem mõistmine: RewriteRule ^news/(.*)$ index.php # Kui mask peab sisaldama ainult numbreid, määra see selgesõnaliselt. # Kui mõned arvud on konstantsed, täpsustage need selgelt. # Kui ülejäänud päringus ei saa olla kaldkriipse, piirake nende olemasolu. # Ärge unustage põgeneda "." (punktid). # Järgmine reegel sihib selliseid päringuid nagu http://example.com/news/2009/07/28/b-effect.html RewriteRule ^news/20(2)/(2)/(2)/[^/]+ \.html index.php

Siiski oh regulaaravaldisedÜhel tuntud veebisaidil on terve jaotis.

Väliste ümbersuunamiste muutmine

Hoolimata asjaolust, et mod_rewrite võimaldab teil muuta isegi väliseid ümbersuunamisi, kasutades RewriteRule'i, kuni protokollini välja, ei soovita ma tungivalt seda teha. Artiklis kasutatakse väliste ümbersuunamiste muutmise näidet ainult selleks, et vabaneda sellistest mõistetest nagu "lingid" ja "failid" ning näidata selgemalt, et RewriteRule töötab lihtsa stringiga.

Ma ei usu, et mod_rewrite arendajad kavatsesid seda teha, nii et igasugused artefaktid on võimalikud. Ära tee seda palun.

Kuidas peatada lõpmatu silmus

Mõnikord on saidil ümbersuunamiste loogika selline, et ilma eritoimingud mod_rewrite käsitleb neid kui lõputut ümbersuunamistsüklit. Võtame järgmise näite.

Saidil oli leht /info.html. SEO spetsialist otsustas nii otsingumootorid indekseerib seda lehte paremini, kui selle nimi on /information.html ja palub välist ümbersuunamist saidilt info.html lehele information.html. Kuid millegipärast ei saa saidi arendaja lihtsalt info.html ümber nimetada info.html-ks ja teha ümbersuunamist – ta vajab andmete saatmist otse failist info.html. Ta kirjutab järgmise reegli: # tee väline ümbersuunamine RewriteRule ^info.html information.html # kuid soovi korral anna /information.html siiski info.html RewriteRule ^information.html info.html

... ja seisab silmitsi lõputu silmus. Iga /information.html päring saab välise ümbersuunamise tagasi aadressile /information.html.

Seda probleemi saab lahendada vähemalt kahel viisil. Ühte neist on Habrel juba kirjeldatud - peate selle installima keskkonna muutuja ja selle väärtuse alusel peatage ümbersuunamised. Kood näeb välja selline:

RewriteCond %(ENV:REDIRECT_FINISH) !^$ RewriteRule ^ - [L] RewriteRule ^info.html$ information.html RewriteRule ^information.html$ info.html

Pange tähele, et mod_rewrite lisab muutuja nimele "REDIRECT_".

Teine võimalus on kontrollida rakenduses THE_REQUEST, mida kasutaja täpselt taotles:

# Väline ümbersuunamine juhtub ainult siis, kui kasutaja küsis info.html. # Kui info.html on sisemise ümbersuunamise tulemus, siis reegel ei käivitu. RewriteCond %(THE_REQUEST) "^(GET|POST|HEAD) /info.html HTTP/+$" RewriteRule ^info.html$ information.html RewriteRule ^information.html$ info.html

Algse kasutaja taotluse analüüsimine – võitlus Apache lingi avalikustamise vastu

Päringu töötlemisel laiendab Apache algse päringu URL-i kodeeritud tähemärke. Mõnel juhul ei pruugi see olla soovitav – arendaja soovib kontrollida täpselt algset, muutmata kasutajataotlust. Seda saab teha, kontrollides RewriteCondis muutujat %(THE_REQUEST):

RewriteCond %(THE_REQUEST) ^GET[\ ]+/tag/([^/]+)/[\ ]+HTTP.*$ RewriteRule ^(.*)$ index.php?tag=%1 [L]

Konsoolirakenduse loomisel C++ programmeerimiskeeles luuakse automaatselt sellele väga sarnane rida:

Int main(int argc, char* argv) // funktsiooni main() parameetrid

See rida on päis põhifunktsioon main() , parameetrid argс ja argv on deklareeritud sulgudes. Seega, kui programm käivitatakse kaudu käsurida, siis on võimalik sellele programmile infot edastada, seetõttu on parameetrid argc ja argv olemas. argc parameeter omab tüüpi andmed int ja sisaldab põhifunktsioonile edastatud parameetrite arvu. Lisaks on argc alati vähemalt 1, isegi kui me ei edasta mingit teavet, kuna esimene parameeter on funktsiooni nimi. Argv parameeter on stringidele osutavate viidete massiiv. Käsurea kaudu saab edastada ainult andmeid stringi tüüp. Osutajad ja stringid on kaks suurt teemat, mille jaoks on loodud eraldi jaotised. Seega edastatakse kogu teave parameetri argv kaudu. Töötame välja programmi, mille käivitame käsurea kaudu Windowsi string ja andke talle teavet.

// argc_argv.cpp: määrab konsoolirakenduse sisenemispunkti. #include "stdafx.h" #include kasutades nimeruumi std; int main(int argc, char* argv) ( if (argc ><< argv<

// kood Code::Blocks

// Dev-C++ kood

// argc_argv.cpp: määrab konsoolirakenduse sisenemispunkti. #kaasa kasutades nimeruumi std; int main(int argc, char* argv) ( if (argc > 1) // kui argumendid edastame, siis on argc suurem kui 1 (olenevalt argumentide arvust) ( cout<< argv<

Pärast programmi silumist avage Windowsi käsurida ja lohistage meie programmi käivitatav fail käsurea aknasse. Programmi täielik tee kuvatakse käsureal (kuid saate programmi tee käsitsi sisestada ), pärast mida saate klõpsata SISENEMA ja programm käivitub (vt joonis 1).

Joonis 1 – Põhifunktsiooni parameetrid

Kuna me lihtsalt käivitasime programmi ja ei edastanud sellele ühtegi argumenti, ilmus teade Not arguments. Joonis 2 näitab sama programmi käivitamist käsurea kaudu, kuid andes sellele Open argumendi.

Joonis 2 – Põhifunktsiooni parameetrid

Argumendiks on sõna Open, nagu jooniselt näha, ilmus see sõna ekraanile. Saate edastada mitu parameetrit korraga, eraldades need komaga. Kui peate edastama mitmest sõnast koosneva parameetri, tuleb need panna jutumärkidesse ja siis käsitletakse neid sõnu ühe parameetrina. Näiteks näitab joonis programmi käivitamist, edastades sellele kahest sõnast koosneva argumendi – See töötab.

Joonis 3 – Põhifunktsiooni parameetrid

Ja kui eemaldate jutumärgid. Siis näeme ainult sõna See. Kui programmi käivitamisel ei ole plaanis mingit infot edastada, saad argumendid eemaldada funktsioonis main() ning samuti saad muuta nende argumentide nimesid. Mõnikord tuleb ette argc ja argv parameetrite muudatusi, kuid see kõik sõltub loodava rakenduse tüübist või arenduskeskkonnast.