Wat u moet weten over .htaccess. MAIN()-functieargumenten

Het komt voor dat gegevens vanaf de opdrachtregel naar een programma worden overgebracht wanneer het wordt aangeroepen. Dergelijke gegevens worden opdrachtregelargumenten genoemd. Het ziet er bijvoorbeeld zo uit:

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

Hier worden de programma's a.out (uit de huidige map) en ls (uit dezelfde map die is opgegeven in de omgevingsvariabele PATH) aangeroepen. Het eerste programma vanaf de opdrachtregel ontvangt één woord - test.txt, het tweede - twee: -lt en /home/peter/.

Als het programma in C is geschreven, wordt de besturing bij het starten onmiddellijk overgedragen naar de functie main(). Daarom is het de functie die de opdrachtregelargumenten ontvangt die zijn toegewezen aan de parametervariabelen.

Eerder hebben we de functie main() gedefinieerd alsof deze geen parameters nodig heeft en niets retourneert. In feite retourneert elke functie in de C-taal standaard (als er niets anders is gedefinieerd) een geheel getal. Hier kunt u zeker van zijn. Als je de code op deze manier schrijft:

main() ( printf ("Hallo \N");

retour 0;

)

  1. Er zal dan geen waarschuwing of fout optreden tijdens het compileren. Hetzelfde gebeurt als je int main() schrijft. Dit bewijst dat de functie standaard een geheel getal retourneert en niet niets (void). Hoewel wat een functie retourneert altijd kan worden “overschreven”, bijvoorbeeld voidmain() of float main() . Wanneer u een programma vanaf de opdrachtregel aanroept, worden er altijd de volgende gegevens in doorgegeven:
  2. geheel getal, waarmee het aantal woorden (elementen gescheiden door spaties) op de opdrachtregel wordt aangegeven wanneer deze wordt aangeroepen, verwijzing naar een array van strings, waar elke regel is

apart woord

vanaf de opdrachtregel.

Houd er rekening mee dat de programmanaam zelf ook telt. Als de oproep er bijvoorbeeld zo uitziet:

./a.uit 12 thema 2
Dan heeft het eerste argument van het programma de waarde 4, en de reeks strings wordt gedefinieerd als ("./a.out", "12", "theme", "2").

Het feit dat gegevens in het programma worden doorgegeven, betekent niet dat de functie main() deze moet accepteren. Als de functie main() zonder parameters is gedefinieerd, is het niet mogelijk om toegang te krijgen tot de argumenten op de opdrachtregel. Hoewel niets je ervan weerhoudt ze door te geven. Er zal geen fout zijn.

Om toegang te krijgen tot de gegevens die aan het programma worden doorgegeven, moeten deze aan variabelen worden toegewezen. Omdat de argumenten onmiddellijk worden doorgegeven aan main() , zou de header er als volgt uit moeten zien:
hoofd (int n, char *arr)

De eerste variabele (n) bevat het aantal woorden en de tweede variabele bevat een verwijzing naar een array van strings. Vaak wordt de tweede parameter geschreven als **arr . Het is echter hetzelfde. Bedenk dat de array met strings zelf verwijzingen naar strings als elementen bevat. En we geven een verwijzing door naar het eerste element van de array naar de functie. Het blijkt dat we een aanwijzer doorgeven aan een aanwijzer, d.w.z. ** arr.

Oefening
Schrijf een programma als dit:

#erbij betrekken int main(int argc, char ** argv) ( int i; printf ("%d \N", argc);< argc; i++ ) puts (argv[ i] ) ; }

voor (i= 0; ik Het toont het aantal woorden op de opdrachtregel wanneer deze wordt aangeroepen en elk woord met nieuwe lijn

. Noem het zonder opdrachtregelargumenten en met argumenten.

In het programma gebruikten we de parametervariabelen argc en argv. Het is gebruikelijk om deze namen te gebruiken, maar in feite kunnen ze van alles zijn. Het is beter om je aan deze standaard te houden, zodat je programma's niet alleen voor jou, maar ook voor andere programmeurs begrijpelijker zijn.

De praktische betekenis van het overbrengen van gegevens naar het programma

Als je enige ervaring hebt met de GNU/Linux-opdrachtregel, weet je dat de meeste opdrachten schakelaars en argumenten hebben. Wanneer u bijvoorbeeld de inhoud van mappen bekijkt, kopieert of verplaatst, worden de bestandssysteemobjecten waarop de opdracht wordt uitgevoerd, opgegeven als argumenten. De kenmerken van de implementatie ervan worden bepaald met behulp van sleutels. In een team bijvoorbeeld

Cp -r ../les_1 ../les_101

cp is de opdrachtnaam, -r is de switch, en ../les_1 en ../les_101 zijn de opdrachtargumenten.

Over het algemeen worden bestandsadressen en "modifiers" (dit zijn sleutels) van het programma-uitvoeringsproces meestal overgedragen naar programma's wanneer ze worden gestart. Laten we een programma schrijven dat wordt geopend opgegeven door de gebruiker

#erbij betrekken op de opdrachtregel, bestanden om te schrijven of toe te voegen en schrijft (voegt) daar dezelfde informatie toe die de gebruiker invoert vanaf het toetsenbord tijdens de uitvoering van het programma: #erbij betrekken< 3 || argc >main (int argc, char ** argv) ( int i, ch; BESTAND * f[ 5 ] ; if (argc 7) (zet (); retour 1;) if (strcmp (argv[ 1 ] , "-w" ) != 0 && strcmp (argv[ 1 ] , "-a" ) != 0 ) ( zet (< argc- 2 ; i++ ) { f[ i] = fopen (argv[ i+ 2 ] , argv[ 1 ] + 1 ) ; if (f[ i] == NULL) { printf ("De eerste parameter kan -w of -a zijn");< argc- 2 ; i++ ) putc (ch, f[ i] ) ; for (i= 0 ; i < argc- 2 ; i++ ) fclose (f[ i] ) ; return 0 ; }

retour 2;

  1. ) voor (i= 0; ik
  2. "Het bestand %s kan niet worden geopend\n "
  3. , argv[ i+ 2 ] ) ; retour 3;) ) terwijl ((ch = getchar () ) != EOF) voor (i= 0; ik
  4. Uitleg voor de code: Er wordt een array van vijf bestandsaanwijzers gemaakt. Daarom kunt u niet meer dan vijf bestanden tegelijk openen. De bestandsaanwijzer van het eerste bestand wordt opgeslagen in arrayelement f, de tweede in f, enz. Het aantal opdrachtregelargumenten wordt gecontroleerd. Het zouden er minstens drie moeten zijn, want... de eerste is de programmanaam, de tweede is de bestandsopeningsmodus, de derde is het eerste of enige bestand waarnaar wordt geschreven. Omdat u met het programma slechts vijf bestanden kunt openen, kan het totale aantal opdrachtregelargumenten niet meer dan zeven zijn. Als het aantal argumenten minder dan 3 of meer dan 7 is, eindigt het programma omdat De return-instructie zorgt ervoor dat de functie wordt afgesloten, zelfs als er nog meer code achter zit. Een waarde die wordt geretourneerd door een functie die niet gelijk is aan 0, kan door het bovenliggende proces worden geïnterpreteerd als een bericht dat het programma met een fout is beëindigd. Controleert de geldigheid van het tweede opdrachtregelargument. Als het noch "-w" noch "-a" is, dan voorwaardelijke expressie
  5. in de tweede retourneert if 1 (waar). Met de functie strcmp() kunt u tekenreeksen vergelijken en retourneert 0 als ze gelijk zijn.
  6. IN
  7. voor lus
  8. bestanden worden geopend door

opgegeven adressen , die beginnen vanaf het derde element van de argv-array. Dit is de reden waarom 2 aan i wordt toegevoegd om de elementen van de argv-array te krijgen, beginnend bij de derde. De argc-2-expressie geeft het aantal doorgegeven bestandsnamen aan; omdat argc slaat het totale aantal opdrachtregelargumenten op, waarvan de eerste twee geen bestandsnamen zijn. werken met mod_rewrite. De praktijk heeft uitgewezen dat ondersteuningsteams, na bestudering van het grote aantal beschikbare schoolboeken in het Russisch, goed zijn in het oplossen van sjabloonproblemen, maar dat onafhankelijke compilatie van regels met vallen en opstaan ​​gebeurt. grote hoeveelheid fouten. Het probleem is dat een goed begrip van hoe mod_rewrite werkt het bestuderen van de originele Engelse documentatie vereist, gevolgd door aanvullende uitleg of urenlang experimenteren met RewriteLog.

Het artikel beschrijft hoe mod_rewrite werkt. Als u de principes van de werking ervan begrijpt, kunt u het effect van elke richtlijn duidelijk begrijpen en u duidelijk voorstellen wat er op een of ander moment gebeurt binnen mod_rewrite bij het verwerken van richtlijnen.

Ik neem aan dat de lezer al bekend is met wat mod_rewrite is, en ik zal de basisprincipes ervan niet beschrijven, die gemakkelijk op internet te vinden zijn. Er moet ook worden opgemerkt dat het artikel het werk van mod_rewrite behandelt bij het gebruik van de richtlijnen in het .htaccess-bestand. Verschillen bij het werken in context uiteengezet in.

Dus je hebt mod_rewrite bestudeerd, verschillende RewriteRules gecompileerd en bent erin geslaagd eindeloze omleidingen tegen te komen, het geval waarin een regel om de een of andere reden je verzoek niet opvangt, evenals de onvoorspelbare werking van een groep regels wanneer volgende regel verandert onverwacht het verzoek, nauwgezet voorbereid door de vorige regels.

Waarmee werkt RewriteRule?

De eerste RewriteRule krijgt het pad doorgegeven van waar .htaccess zich bevindt naar het opgevraagde bestand. Deze regel begint nooit met "/". Daaropvolgende RewriteRules verzenden het resultaat van eerdere transformaties.

Om goed te begrijpen hoe RewriteRule werkt, moet u eerst definiëren waarmee het werkt. Laten we eens kijken hoe Apache de string ontvangt die aanvankelijk wordt doorgegeven aan de RewriteRule in .htaccess voor verwerking.

Wanneer je voor het eerst met mod_rewrite gaat werken, ga je er logischerwijs van uit dat het met links werkt. Dit is echter niet het geval bij gebruik van mod_rewrite in .htaccess. In feite is het geen link die naar RewriteRule wordt gestuurd, maar het pad naar het opgevraagde bestand.

Vanwege de interne architectuur van Apache kan mod_rewrite, op het moment dat .htaccess in het spel komt, alleen werken op het pad naar het bestand dat moet worden verwerkt. Dit komt door het feit dat voordat het verzoek naar mod_rewrite werd verzonden, het verzoek al door andere modules (bijvoorbeeld mod_alias) had kunnen worden gewijzigd en dat het uiteindelijke pad naar het bestand op de site mogelijk niet langer samenvalt met de oorspronkelijke link. Als mod_rewrite aan de originele referentie zou werken, zou het de actie verbreken van modules die het verzoek daarvoor hadden gewijzigd.

Daarom wordt aan mod_rewrite het absolute pad doorgegeven aan het bestand dat moet worden verwerkt. Mod_rewrite kent ook het pad naar .htaccess, waar de RewriteRule-regels zich bevinden. Om het pad naar het bestand vergelijkbaar te maken met de link waarmee de site-ontwikkelaar wil werken, snijdt mod_rewrite het gedeelte naar het .htaccess-bestand af van het absolute pad.

Het is dus dit pad, waarvan het pad naar .htaccess wordt afgesneden, dat wordt doorgegeven aan de eerste RewriteRule. Bijvoorbeeld:

Verzoek: http://example.com/templates/silver/images/logo.gif DocumentRoot: /var/www/example.com Pad naar bestand: /var/www/example.com/templates/silver/images/logo. gif .htaccess bevindt zich in: /var/www/example.com/templates/.htaccess

De eerste RewriteRule krijgt: silver/images/logo.gif Let op: “templates/” is ook afgekapt. hoe RewriteRule werkt Het pad naar .htaccess wordt samen met de schuine streep afgesneden. Hieruit volgt een gevolg: de regel die aanvankelijk wordt doorgegeven aan de RewriteRule-verwerking begint nooit met "/".

Het is belangrijk om te onthouden wat RewriteRule niet doet. Het verwerkt niet de sitenaam, de argumenten die aan het script worden doorgegeven, en het verwerkt niet de volledige link als de .htaccess zich niet in de hoofdmap van de site bevindt. Dit alles wordt gedaan door RewriteCond, waar we later kort op zullen ingaan. Dus:

# werkt niet - de regel begint met / RewriteRule ^/index.php$ /my-index.php # werkt niet - de sitenaam wordt niet geanalyseerd RewriteRule RewriteRule ^example.com/.* http://www.example .com # zal niet werken - de linkargumenten vallen niet in de RewriteRule RewriteRule index.php\?newspage=(+) news.php?page=$1 # Werkt alleen als .htaccess zich op dezelfde plaats bevindt als de sjablonen map # bijvoorbeeld in de hoofdmap van de site. Dat wil zeggen, als .htaccess in templates/.htaccess staat, zal de # regel NIET werken, omdat mod_rewrite het pad naar .htaccess zal afsnijden en de regel zal eindigen op de RewriteRule # invoer zonder "templates/" RewriteRule ^templates/ common/yandex-geld.gif$-sjablonen/shared/yad.gif

We hebben ontdekt waar RewriteRule mee werkt. Laten we nu kijken hoe het werkt.

Hoe RewriteRule werkt

RewriteRule transformeert eenvoudigweg de string volgens reguliere expressies en dat is alles. RewriteRule werkt op een string, niet op een link of pad naar een bestand.

Zoals we hierboven hebben ontdekt, bevat de RewriteRule-invoer het pad van .htaccess naar het gevraagde bestand. Het is nu het handigst om te abstraheren van paden en links en na te denken over hoe RewriteRule werkt reguliere string. Deze tekenreeks wordt doorgegeven van RewriteRule naar RewriteRule, gewijzigd als een van de RewriteRules werkte.

Uitleg voor de code: algemeen beeld Afgezien van de complexiteit van het gebruik van vlaggen (waarvan we er enkele hieronder zullen bekijken) en de complexiteit van het schrijven van reguliere expressies (waar we in dit artikel niet veel op zullen ingaan), werkt RewriteRule ZEER eenvoudig. Wij hebben de lijn overgenomen. Vergelijk met de reguliere expressie in het eerste argument. Als er een overeenkomst is, vervangt u de gehele tekenreeks door de waarde van het tweede argument. De tekenreeks doorgegeven aan de volgende RewriteRule. Dat is eigenlijk alles. Om duidelijk te illustreren dat RewriteRule specifiek met een string werkt, kun je het volgende fantastische voorbeeld overwegen:

# Verzoek: http://mysite.com/info.html # De eerste RewriteRule zal "info.html" bevatten # Converteer het verzoek naar een willekeurige string. RewriteRule ^info.html$ "Ik zag een schildpad in het hol. En hij danste rock-'n-roll. En hij glimlachte. Al met al was het een heel grappige pop." # "info.html" -> "Ik zag een schildpad..." # Vervang deze regel door externe link. RewriteRule schildpad https://example.com/information/index.html # "Ik zag een schildpad..." -> "https://example.com/information/index.html" # Vervang de sitenaam! RewriteRule ^(.*)example.com(.*)$ $1example.org$2 # "https://example.com/information/index.html" -> "https://example.org/information/index. html" # Vervang het protocol! RewriteRule ^https:(.*)$ ftp:$1 # "https://example.org/information/index.html" -> "ftp://example.org/information/index.html" # Vervang de laatste link . RewriteRule ^(.*)/index.html$ $1/main.php # "ftp://example.org/information/index.html" -> "ftp://example.org/information/main.php"

Zoals u kunt zien, maakt het RewriteRule niet uit waarmee het werkt; het transformeert eenvoudigweg de string volgens de argumenten die eraan worden gegeven. Als je wilt, kun je alle data-arrays in een string opslaan, als je dat wilt, persistentie en goede kennis Voor reguliere expressies kun je zelfs boter-kaas-en-eieren schrijven op RewriteRule.

Hierbij moet wel een kanttekening worden gemaakt: hoewel RewriteRule met een pure string werkt, is het nog steeds gericht op het werken met links. Daarom zal het anders reageren op lijnen die beginnen met

https://

of analogen (het zal onthouden dat we een externe omleiding wilden maken) en naar de "?" (beschouwt de volgende tekens als argumenten die moeten worden vervangen door het verzoek). Daar zijn we op dit moment echter niet in geïnteresseerd - het is belangrijk om te begrijpen dat er geen magie zit in RewriteRule - er is gewoon een string voor nodig en deze verandert op de manier waarop jij het vertelt. We zullen later in het artikel kijken naar externe omleidingen en argumenten; daar is ook iets om over te praten;

Nadat alle transformaties zijn voltooid en de laatste RewriteRule is uitgevoerd, treedt RewriteBase in werking.

Waar wordt RewriteBase voor gebruikt?

Als de resulterende query relatief is en verschilt van de oorspronkelijke query, zal RewriteBase zichzelf links ervan toevoegen. Het is noodzakelijk om RewriteBase op te geven in .htaccess. De waarde ervan is het pad van de siteroot naar .htaccess. RewriteBase wordt alleen uitgevoerd na alle RewriteRules, niet ertussenin.

We hebben hierboven al gezegd dat mod_rewrite, dat werkt in .htaccess, het absolute pad naar het opgevraagde bestand bevat. Om het door te geven aan de RewriteRule, snijdt mod_rewrite het pad naar .htaccess af. Vervolgens wijzigen de RewriteRules de aanvraag één voor één. En nu, nadat het verzoek is gewijzigd, moet Apache het absolute pad herstellen naar het bestand dat het uiteindelijk moet verwerken. RewriteBase is eigenlijk een hack die helpt het oorspronkelijke pad van een bestand te herstellen.

RewriteBase wordt na alle transformaties uitgevoerd. Dit betekent dat het verzoek tussen RewriteRules niet wordt gewijzigd, maar pas van kracht wordt als alle RewriteRules zijn voltooid.

Na alle transformaties kijkt RewriteBase of het resulterende pad relatief of absoluut is. In de context van Apache betekent dit een relatief of absoluut pad, beginnend bij de hoofdmap van de site: images/logo.gif - relatief. /images/logo.gif - absoluut (schuine streep aan het begin). http://example.com/images/logo.gif - de meest absolute van allemaal. Als het pad absoluut is, doet RewriteBase niets. En als het relatief is, voegt RewriteBase zichzelf aan de linkerkant toe. Dit werkt voor zowel interne als externe omleidingen:

# .htaccess bevindt zich in /images/ # RewriteBase is gespecificeerd /images/ RewriteBase /images/ # Verzoek http://example.com/images/logo.gif # De RewriteRule-invoer is "logo.gif" RewriteRule ^logo.gif $ logo -orange.gif # Na RewriteRule: "logo.gif" -> "logo-orange.gif" # Na RewriteBase: "logo-orange.gif" -> "/images/logo-orange.gif" # http aanvragen :/ /example.com/images/header.png # De RewriteRule-invoer is "header.png" RewriteRule ^header.png$ /templates/rebranding/header.png # Na de RewriteRule: "header.png" -> "/ templates/rebranding /header.png" # Na RewriteBase: er verandert niets, dus het eindresultaat van de transformatie begint met "/". # Verzoek http://example.com/images/director.tiff # De RewriteRule-invoer is "director.tiff" # We gebruiken een externe relatieve omleiding RewriteRule ^director.tiff$ staff/manager/director.tiff # Na de RewriteRule: "director.tiff" -> "staff/manager/director.tiff" # + mod_rewrite onthoudt dat er een externe omleiding zal zijn # Na RewriteBase: "staff/manager/director.tiff" -> "/images/staff/manager/ director.tiff" # mod_rewrite onthouden over de externe omleiding: # "/images/staff/manager/director.tiff" -> http://example.com/images/staff/manager/director.tiff

Meestal ontwikkelt zich na enige bekendheid met mod_rewrite de volgende gewoonte:

    voeg “RewriteBase /” toe aan elke .htaccess

    Alle omleidingen beginnen met een schuine streep: “RewriteRule news.php /index.php?act=news”. Dit helpt om artefacten uit RewriteBase te verwijderen, maar het is verkeerd om dit te doen. Nu we weten wat RewriteBase doet, kunnen we de volgende correcte regels formuleren:

RewriteBase moet overeenkomen met het pad van de siteroot naar .htaccess. U hoeft omleidingen alleen te starten met "/" als u het absolute pad van de hoofdmap van de site naar het bestand moet opgeven.

Wat gebeurt er als u RewriteBase niet opgeeft? Standaard maakt Apache het gelijk absoluut pad op bestandssysteem naar.htaccess (bijvoorbeeld /var/www/example.com/templates/). De onjuistheid van deze aanname van Apache komt tot uiting in externe relatieve omleidingen:

# Verzoek http://example.com/index.php # DocumentRoot: /var/www/example.com/ # .htaccess bevindt zich in de root van de site en er is GEEN RewriteBase gespecificeerd. # Daarom is RewriteBase standaard gelijk aan het absolute pad naar.htaccess: /var/www/example.com/ # De invoer RewriteRule is "index.php" RewriteRule ^index.php main.php [R] # De uitvoer is "index.php" " -> "main.php" # mod_rewrite onthoudt dat een externe redirect nodig is # RewriteRule is op # mod_rewrite voert nog steeds RewriteBase uit, omdat het een standaardwaarde heeft. # Het blijkt: "main.php" -> "/var/www/example.com/main.php" # Hier onthoudt mod_rewrite dat er een externe omleiding was: # "/var/www/example.com/main. php" -> http://example.com/var/www/example.com/main.php # Het bleek helemaal niet wat ze in gedachten hadden.

Het verzoek heeft dus alle RewriteRules doorlopen, waarna er indien nodig een RewriteBase aan is toegevoegd. Moet Apache nu het bestand weergeven waarnaar het resulterende pad verwijst? Nee. Nu wordt het resulterende verzoek opnieuw verwerkt.

Hoe mod_rewrite werkt. Vlag [L]

mod_rewrite begint het verzoek keer op keer te verwerken totdat het niet meer verandert. En de vlag [L] kan het niet stoppen.

Bij het maken van min of meer complexe mod_rewrite-configuraties is het belangrijk om dat te begrijpen de wijziging van de query eindigt niet bij de laatste RewriteRule. Nadat het werkte laatste regel RewriteRule en RewriteBase zijn toegevoegd, mod_rewrite kijkt of het verzoek is gewijzigd of niet. Als het verzoek is gewijzigd, begint de verwerking opnieuw vanaf het begin.htaccess.

Apache doet dit omdat het verzoek tijdens het wijzigen mogelijk naar een andere map is omgeleid. Het kan zijn eigen .htaccess hebben die niet betrokken was bij de eerdere verwerking van verzoeken. Deze nieuwe .htaccess kan regels bevatten die de verwerking van verzoeken beïnvloeden - zowel mod_rewrite-regels als regels van andere modules. Om deze situatie correct af te handelen, moet Apache de gehele verwerkingslus opnieuw starten.

Wacht, maar er is een vlag [L], die stopt met het verwerken van het mod_rewrite-verzoek!

Niet echt. Vlag [L] stopt de huidige iteratie van de aanvraagverwerking. Als het verzoek echter werd gewijzigd door de RewriteRules die er nog steeds in slaagden het te verwerken, zal Apache de verzoekverwerkingscyclus opnieuw starten vanaf de eerste RewriteRule.

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

Het bovenstaande voorbeeld resulteert in een oneindige lus van omleidingen en "Internal Serverfout"op het einde. In dit voorbeeld is de oneindige lus duidelijk zichtbaar, maar in complexere configuraties moet u mogelijk in de regels duiken om te bepalen welke query's heen en weer lopen.

Om dergelijke situaties te voorkomen, wordt aanbevolen om de vlag [L] alleen te gebruiken als dat nodig is. De behoefte kan van twee soorten zijn: Wanneer een externe omleiding wordt gebruikt - of . Bij een externe redirect is verdere verwerking van het verzoek ongewenst (zie hieronder over de vlag [R]), en het is beter om ermee te stoppen. Wanneer er een lus in .htaccess zit die niet kan worden geëlimineerd, en de verwerking van het verzoek door mod_rewrite met geweld moet worden gestopt. In dit geval wordt een speciale constructie gebruikt - zie het einde van het artikel voor tips over dit onderwerp.

Maar het onderstaande voorbeeld zal niet in een lus verschijnen. Probeer te bepalen waarom en welk bestand uiteindelijk aan Apache wordt gegeven.

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

Oplossing: Als gevolg van het uitvoeren van alle RewriteRules wordt de aanvraag zodanig gewijzigd dat het eindresultaat gelijk is aan het origineel. Apache ziet dit en verwerkt het verzoek niet opnieuw. Het a.html-bestand wordt geretourneerd.

Hoe mod_rewrite werkt. Vlag [R]

    Vlag [R] stopt de verwerking van verzoeken niet en retourneert onmiddellijk een externe omleiding. In plaats daarvan onthoudt het de noodzaak van een externe omleiding, en gaat de verwerking van het verzoek verder met de volgende RewriteRule. Het wordt aanbevolen om altijd met de vlag te gebruiken [L].

    Vlag [R] vertelt Apache dat het geen interne, maar een externe omleiding moet uitvoeren. Wat is het verschil tussen een externe omleiding en een interne omleiding? Een interne omleiding verandert simpelweg het pad naar het bestand dat aan de gebruiker wordt gegeven, terwijl de gebruiker denkt dat hij het bestand ontvangt waar hij oorspronkelijk om heeft gevraagd. Bij een externe omleiding retourneert Apache de antwoordstatus 301 of 302 aan de gebruiker in plaats van de inhoud van het bestand en informeert de gebruiker over de link die de browser moet gebruiken om het bestand op te halen.

Het lijkt erop dat bij het verwerken van de vlag [R] Apache moet onmiddellijk stoppen met het verwerken van de RewriteRule en de externe omleiding naar de gebruiker retourneren. Laten we echter het fantastische voorbeeld uit de sectie Hoe RewriteRule werkt onthouden. Daarin hebben we eerst de vlag aangegeven [R], wat de noodzaak van een externe redirect aangeeft, waarna ze de link verder gingen wijzigen met de volgende RewriteRule.

Dit is precies hoe Apache werkt bij het opgeven van een externe omleiding. Het “merkt” eenvoudigweg bij zichzelf op dat het na het uitvoeren van alle regels nodig is om de status 302 (standaard) terug te geven, maar gaat tegelijkertijd door met het uitvoeren van alle RewriteRules verderop in de lijst. We kunnen het verzoek blijven wijzigen als dat nodig is, het enige dat niet werkt is het weer intern maken van de omleiding.

Het is echter onwaarschijnlijk dat u dit op enigerlei wijze wilt wijzigen nadat u een externe omleiding heeft verzonden. Daarom wordt het aanbevolen bij het gebruik van de vlag [R] geef het samen met aan [L]:

# BlackJack is verhuisd naar de mooie naam RewriteRule ^bj/(.*) blackjack/$1 # Je kunt gewoon de externe link RewriteRule ^bj/(.*) gebruiken http://blackjack.example.com/$1 [L]

In plaats van een vlag te gebruiken [R] U kunt eenvoudigweg een externe link opgeven. In dit geval zal Apache zelf raden dat het nodig is om een ​​externe omleiding te maken. Hier, zoals in het geval van het expliciet specificeren van de vlag [R], wordt aanbevolen om de vlag te gebruiken [L]. Als een externe omleiding naar dezelfde site leidt, is het beter om de vlag te gebruiken [R] zonder indicatie volledige koppeling(met andere woorden, gebruik een relatieve externe omleiding). Hierdoor wordt de regel onafhankelijk van de sitenaam. Indien een externe redirect naar een andere site leidt, kan dit niet anders dan door een volledige externe link op te geven.

Hoe mod_rewrite werkt. Verzoekparameters en vlag opgeven

Het wijzigen van de queryparameters in een RewriteRule verandert niets aan de rij waarop de volgende RewriteRule werkt. Als u de parameters wijzigt, verandert echter de %(QUERY_STRING) variabele waarmee RewriteCond kan werken.

Gebruikte terminologie: “parameters” - verzoekparameters, “argumenten” - RewriteRule-argumenten.

Met RewriteRule kunt u niet alleen het pad naar het bestand dat wordt verwerkt, maar ook de parameters wijzigen KRIJG verzoek die aan hem zal worden doorgegeven. Dit wordt vaak gebruikt om NC-verwerking over te dragen naar een generiek handlerscript, bijvoorbeeld: RewriteBase /

# Verzoek: http://example.com/news/2010/07/12/grand-opening.html # Invoer: "news/2010/07/12/grand-opening.html" RewriteRule ^news/(.* ) $ index.php?act=news&what=$1 # Na RewriteRule: "news/2010/07/12/grand-opening.html" -> "index.php" # %(QUERY_STRING): "" -> "act= news&what =2010/07/12/grote opening.html"

Op het moment dat de RewriteRule een vraagteken tegenkomt in zijn tweede argument, weet hij dat de parameters in het verzoek worden gewijzigd. Wat er gebeurt is dat RewriteRule de string waarmee het werkt vervangt door het deel van het tweede argument vóór het vraagteken. Houd er rekening mee dat de nieuwe aanvraagparameters niet in de tekenreeks terechtkomen waarop volgende RewriteRules zullen werken. Het deel van het tweede argument na het vraagteken komt terecht in de %(QUERY_STRING) variabele. Als er een vlag is opgegeven , worden de queryparameters toegevoegd aan het begin van %(QUERY_STRING). Als de vlag niet is opgegeven, wordt %(QUERY_STRING) volledig vervangen door de queryparameters uit de RewriteRule. Nog een paar voorbeelden:

RewriteBase / # Verzoek: http://example.com/news/2010/?page=2 # Voer RewriteRule in: "news/2010/" RewriteRule ^news/(.*)$ index.php?act=news&what=$1 # Na conversie: "news/2010/" -> "index.php" # Waarde %(QUERY_STRING): "page=2" -> "act=news&what=2010/" Hoogstwaarschijnlijk werkt de bovenstaande regel niet correct, omdat het is een verloren argumentpagina. Laten we dit oplossen: RewriteBase / # Request: http://example.com/news/2010/?page=2 # Input RewriteRule: "news/2010/" RewriteRule ^news/(.*)$ index.php?act= news&what=$1 # Na conversie: "news/2010/" -> "index.php" # Waarde %(QUERY_STRING): "page=2" -> "act=news&what=2010/&page=2"

Het is belangrijk om te begrijpen dat het wijzigen van de queryparameters de %(QUERY_STRING) verandert, die later in RewriteCond kan worden gebruikt. Hiermee moet rekening worden gehouden bij het schrijven van volgende regels die argumenten controleren.

Natuurlijk verandert het, omdat het verzoek voor herverwerking door Apache wordt verzonden!

Nee, %(QUERY_STRING) verandert onmiddellijk. Ik zal geen bewijs geven - er is al meer over parameters geschreven dan interessant is om te lezen :)

Wat kunt u doen om in RewriteCond precies die verzoekparameters in te checken die door de gebruiker zijn doorgegeven, en niet de parameters die zijn gewijzigd door RewriteRules? Zie de tips aan het einde van het artikel.

HerschrijfCond en prestaties

Eerst wordt de overeenkomst van het verzoek met de RewriteRule gecontroleerd, en pas daarna worden de aanvullende voorwaarden van RewriteCond gecontroleerd.

Er moeten een paar woorden worden gezegd over de volgorde waarin mod_rewrite richtlijnen uitvoert. Omdat .htaccess eerst met RewriteCond en daarna met RewriteRule wordt geleverd, lijkt het erop dat mod_rewrite eerst alle voorwaarden controleert en dan begint met het uitvoeren van de RewriteRule.

Eigenlijk gebeurt alles andersom. Eerst controleert mod_rewrite of de huidige verzoekwaarde overeenkomt met de reguliere expressie RewriteRule, en alleen dan controleert het alle voorwaarden die zijn vermeld in RewriteCond.

Dus als u een reguliere expressie van twee pagina's in uw RewriteRule heeft en, denkend aan de prestaties, besluit u de uitvoering van deze regel te beperken tot extra RewriteConds, dan moet u weten dat niets zal werken. In dit geval is het beter om de RewriteRule-vlaggen [C] of [S] te gebruiken om meer over te slaan complexe regel, indien meer eenvoudige controles werkte niet.

RewriteCond-variabelen en -vlaggen, andere RewriteRule-vlaggen, enz.

Lees de documentatie.

We maakten kennis met de werkingsprincipes van RewriteRule, RewriteBase, vlaggen [L], [R] En , en analyseerde ook het verzoekverwerkingsmechanisme binnen mod_rewrite. Het volgende bleef onaangetast: andere RewriteRule-vlaggen, RewriteCond- en RewriteMap-richtlijnen.

Gelukkig zijn deze richtlijnen en vlaggen niet mysterieus en werken ze precies zoals beschreven in de meeste tutorials. Om ze te begrijpen, hoeft u alleen maar de officiële documentatie te lezen. Allereerst raad ik aan om de lijst met variabelen te bestuderen die kunnen worden gecontroleerd in RewriteCond - %(QUERY_STING), %(THE_REQUEST), %(REMOTE_ADDR), %(HTTP_HOST), %(HTTP:header), etc.)

Verschil in hoe mod_rewrite werkt in de .htaccess-context en in de VirtualHost-context

In context mod_rewrite werkt precies het tegenovergestelde.

Zoals ik aan het begin van het artikel zei, heeft alles wat hierboven is beschreven betrekking op het gebruik van mod_rewrite in de .htaccess-context. Als mod_rewrite wordt gebruikt in , zal het anders werken: In de RewriteRule omvat het volledige verzoekpad, beginnend bij de eerste schuine streep en eindigend met het begin GET-parameters: "http://example.com/some/news/category/post.html?comments_page=3" → "/news/category/post.html". Deze regel begint altijd met /. Het tweede argument voor RewriteRule moet ook beginnen met /, anders is het "Bad Request". RewriteBase heeft geen zin. Het passeren van de regels gebeurt slechts één keer. Vlag [L] voltooit daadwerkelijk het verwerken van alle regels die worden beschreven in , zonder verdere iteraties.

Reguliere expressies schrijven

Probeer reguliere expressies zo samen te stellen dat ze precies die query's definiëren die u wilt wijzigen, zodat de RewriteRule-regels niet per ongeluk voor een andere query werken. Bijvoorbeeld:

# Begin alle reguliere expressies met "^" (het begin van een regel) # en eindig met "$" (het einde van een regel): RewriteRule ^news.php$ index.php # Zelfs als dit niet nodig is - voor veelzijdigheid en een beter begrip van de configuratie: RewriteRule ^news/(.*)$ index.php # Als er alleen cijfers in het masker moeten worden opgenomen, specificeer dit dan expliciet. # Als sommige getallen constant zijn, specificeer ze dan expliciet. # Als er in de rest van het verzoek geen schuine strepen aanwezig kunnen zijn, beperk dan de aanwezigheid ervan. # Vergeet niet te ontsnappen "." (punten). # De volgende regel is gericht op verzoeken zoals http://example.com/news/2009/07/28/b-effect.html RewriteRule ^news/20(2)/(2)/(2)/[^/]+ \.html index.php

Er is echter een hele sectie over reguliere expressies op een bekende website.

Externe omleidingen wijzigen

Ondanks het feit dat je met mod_rewrite zelfs externe omleidingen kunt wijzigen met RewriteRule, tot en met het protocol, raad ik je ten zeerste af dit te doen. In het artikel wordt het voorbeeld van het wijzigen van externe omleidingen alleen gebruikt om concepten als “links” en “bestanden” te verwijderen en duidelijker aan te tonen dat RewriteRule met een eenvoudige string werkt.

Ik denk niet dat de mod_rewrite-ontwikkelaars de bedoeling hadden dat iemand dit zou doen, dus allerlei artefacten zijn mogelijk. Doe dit niet alsjeblieft.

Hoe een oneindige lus te stoppen

Soms is de logica van omleidingen op een site zodanig dat mod_rewrite ze zonder speciale acties beschouwt als een eindeloze lus van omleidingen. Laten we het volgende voorbeeld nemen.

De site had een pagina /info.html. Dat heeft de SEO-specialist besloten zoekmachines zal deze pagina beter indexeren als deze /information.html heet en gevraagd wordt om een ​​externe redirect van info.html naar information.html. Om de een of andere reden kan de site-ontwikkelaar echter niet eenvoudigweg de naam info.html wijzigen in information.html en een omleiding maken - hij heeft de gegevens nodig die rechtstreeks vanuit het info.html-bestand worden verzonden. Hij schrijft de volgende regel: # maak een externe redirect RewriteRule ^info.html information.html # maar geef op verzoek /information.html nog steeds info.html RewriteRule ^information.html info.html

... en komt een oneindige lus tegen. Elk /information.html-verzoek krijgt een externe omleiding terug naar /information.html.

Dit probleem kan op ten minste twee manieren worden opgelost. Eén ervan is al beschreven op Habré - je moet deze installeren omgevingsvariabele en op basis van de waarde ervan, stop omleidingen. De code ziet er als volgt uit:

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

Merk op dat mod_rewrite "REDIRECT_" toevoegt aan de naam van de variabele.

De tweede manier is om in THE_REQUEST te controleren wat precies door de gebruiker is aangevraagd:

# Externe omleiding gebeurt alleen als de gebruiker info.html heeft aangevraagd. # Als info.html het resultaat is van een interne omleiding, wordt de regel niet geactiveerd. RewriteCond %(THE_REQUEST) "^(GET|POST|HEAD) /info.html HTTP/+$" RewriteRule ^info.html$ informatie.html RewriteRule ^informatie.html$ info.html

Het analyseren van het oorspronkelijke gebruikersverzoek - het bestrijden van het vrijgeven van Apache-links

Bij het verwerken van een verzoek breidt Apache de URL-gecodeerde tekens uit het oorspronkelijke verzoek uit. In sommige gevallen is dit misschien niet wenselijk: de ontwikkelaar wil precies het originele, ongewijzigde gebruikersverzoek controleren. Dit kan gedaan worden door de %(THE_REQUEST) variabele in RewriteCond te controleren:

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

Htaccess is optioneel configuratiebestand Apache, waarmee u de webserver voor elke afzonderlijke map kunt configureren zonder dat dit gevolgen heeft globale instellingen Apache. Lokale analogie httpd.conf. Normaal gesproken is hij verantwoordelijk voor omleidingen en directorytoegangscontrole.

De naam begint met een punt. We kunnen zeggen dat dit een naamloos bestand is met de htaccess-extensie.

De .htaccess-instellingen zijn van invloed op de map waarin deze zich bevindt en op alle onderliggende mappen. Maak een bestand en plaats het in de map die u nodig hebt. Bijvoorbeeld naar de root van het project.

Nu moet je het vullen. Laten we eens kijken wat .htaccess kan doen, maar laten we eerst een voorbeeld van een eenvoudige omleiding bestuderen.

mod_rewrite en omleidingen

Zorg ervoor dat dit in uw Apache-configuratiebestand staat httpd.conf geactiveerd mod_rewrite. Dat wil zeggen, de overeenkomstige regel is niet becommentarieerd:

LoadModule rewrite_module modules/mod_rewrite.so

Of, als je niet wilt openen teksteditor bestand, kunt u de opdracht in de terminal gebruiken:

Sudo a2enmod herschrijven

mod_rewrite is Apache-module, ontworpen om URL's te transformeren. Laten we eens kijken naar een voorbeeld van hoe het werkt. Stel dat de gebruiker het volgende adres invoert:

Met mod_rewrite kun je inhoud vanaf een andere URL verzenden, zoals deze:

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

Waarom hebben we dit nodig? Het is gemakkelijk om te raden wat je moet schrijven volledige pad het is lang en eenvoudigweg lastig om naar de pagina te gaan. Bezoekers van de site hoeven niet na te denken over de interne structuur van de site. Wat voor hen belangrijk is, is dat ze zo snel mogelijk op de pagina terechtkomen die ze zoeken.

Uitleg voor de code: adresbalk de gebruiker ziet nog steeds wat hij heeft ingevoerd:

http://www.voorbeeld.com/pagina.html

Dit is een voorbeeld van de eenvoudigste omleiding.

Direct naar de praktijk

Laten we het configuratiebestand analyseren dat in een van onze projecten wordt gebruikt. Op deze manier zullen we begrijpen welke regel we moeten bewerken als er zich problemen voordoen.

Php_value short_open_tag 1 php_value upload_max_filesize 10M php_value post_max_size 10M RewriteEngine op RewriteBase / RewriteRule ^(applicatie|modules|systeem) - RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php/$0

  • php_waarde tekenreeks- en numerieke waarden instellen
  • php_flag sets Booleaanse waarden(Niet echt)

Syntaxis van algemene richtlijnen

Php_value/php_flag richtlijn_naam php vlag/waarde

Richtlijn korte_open_tag staat het gebruik van een korte syntaxis toe voor het formatteren van PHP-code:

Php_waarde korte_open_tag 1

upload_max_bestandsgrootte definieert maximale grootte gedownload bestand.

Php_waarde upload_max_bestandsgrootte 10M

A post_max_size stelt maximaal in toegestane maat gegevens verzonden POST-methode.

Php_value post_max_size 10M

RewriteEngine

Schakelt het mechanisme in/uit mod_rewrite.

RewriteEngine Aan

Herschrijfregel

RewriteRule transformeert eenvoudigweg de string volgens reguliere expressies.

Syntaxis: RewriteRule reguliere_expressie

# Invoer RewriteRule "index.php" RewriteRule ^index.php main.php [R] # Uitvoer: "index.php" -> "main.php"

We hebben index.php geconverteerd naar main.php en de omleiding uitgevoerd.

Belangrijk: RewriteRule heeft meestal twee argumenten nodig: Wat moet worden vervangen en waarvoor moet vervangen worden. Als we de vervanging niet hoeven uit te voeren, kunnen we dit in de vorm schrijven:

Het "-" symbool betekent "niet converteren"

Herschrijfbasis

Na alle RewriteRules wordt RewriteBase van kracht. Als de resulterende vraag na transformaties relatief is en verschilt van de oorspronkelijke vraag, zal RewriteBase deze herstellen, waardoor deze absoluut wordt. RewriteBase voegt zichzelf eenvoudigweg toe aan het verzoek aan de linkerkant. Omdat de RewriteBase-waarde het pad is van de siteroot naar .htaccess. In ons geval bevindt .htaccess zich in de root, dus:

Syntaxis: RewriteBase URL-pad-van-.htaccess-bestand-naar-site-root

Bijvoorbeeld:

# .htaccess bevindt zich in /dir/ # Pad van de hoofdmap van de site naar .htaccess /dir/ RewriteBase /dir/ # Verzoek http://example.com/dir/logo.gif # De RewriteRule-invoer is "logo.gif" RewriteRule ^ logo.gif$ logo-orange.gif # Na RewriteRule: "logo.gif" -> "logo-orange.gif" # Na RewriteBase: "logo-orange.gif" -> "/dir/logo-orange. gif"

Reguliere expressies

Reguliere expressies, die je mogelijk tegenkomt in .htaccess.

Symbool Betekenis Voorbeeld
. Iedereen symbool c.t is kat, kinderbed, snit, enz.
+ Eén of meer identiek karakters a+ is a, aa, aaa, enz.
* Nul of meerdere identiek karakters a* werkt hetzelfde als a+, maar in het geval van a* wordt ook aan de voorwaarde voldaan lege tekenreeks
? Match optioneel kleur past bij zowel kleur als kleur.
^ Het symbool waarvan begint lijn ^a komt overeen met een string die begint met a
$ Het symbool dat eindigt lijn a$ komt overeen met een tekenreeks die eindigt op een .
() Vindt en onthoudt overeenkomsten groepen karakters.

Kan ook voor gebruikt worden Terug-referentie(zie voorbeeld)

(ab)+ zal ababab tevreden stellen

Terug-referentie voorbeeld:

Herschrijfregel ^/ (+) /(.*) $ /home?pagina= $1 &id= $2

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

Een van mogelijke karakters ct is geschikt gesneden, kinderbed of kat.

Meer reguliere expressies

Vlaggen

Syntaxis: RewriteRule reguliere_expressie [flag1,flag2,flag3]

Vlag Beschrijving
[F] Verboden- retourneert fout 403 Verboden.
[L] Laatst- stop op dit punt het transformatieproces en pas geen transformatieregels meer toe.
Queryreeks toevoegen- deze vlag geeft het conversiemechanisme aan toevoegen, niet vervangen,queryreeksen van URL naar bestaande,in de vervangingsreeks.
Doorgeven- stopt het conversieproces en verzendt het ontvangen bericht nieuwe koppeling verderop in de keten.
[R] Omleiden- stopt het conversieproces en stuurt het resultaat terug naar de clientbrowser als een omleiding naar een nieuwe pagina.
[S] Overslaan- slaat de volgende regel over als de huidige regel wordt geactiveerd. U kunt het aantal volgende regels opgeven dat u wilt negeren.

Bij het maken van een consoletoepassing in de programmeertaal C++ wordt automatisch een regel gemaakt die hier sterk op lijkt:

Int main(int argc, char* argv) // main() functieparameters

Deze regel is de kop belangrijkste functie main() , worden de parameters argс en argv tussen haakjes gedeclareerd. Dus als het programma wordt gestart via opdrachtregel, dan is het mogelijk om wat informatie aan dit programma door te geven; dit is de reden waarom de parameters argc en argv bestaan. De parameter argc is van het type gegevens int en bevat het aantal parameters dat aan de hoofdfunctie is doorgegeven. Bovendien is argc altijd minstens 1, zelfs als we geen informatie doorgeven, aangezien de eerste parameter de naam van de functie is. De parameter argv is een array van verwijzingen naar tekenreeksen. Alleen stringgegevens kunnen via de opdrachtregel worden doorgegeven. Pointers en strings zijn twee grote onderwerpen waarvoor aparte secties zijn gemaakt. Dus gewoon door argv-parameter en alle informatie wordt verzonden. Laten we een programma ontwikkelen dat we via de opdrachtregel zullen starten Windows-tekenreeks en geef haar wat informatie.

// argc_argv.cpp: definieert het toegangspunt voor de consoletoepassing. #include "stdafx.h" #include naamruimte std gebruiken; int main(int argc, char* argv) ( if (argc ><< argv<

// code Code::Blokken

// Dev-C++-code

// argc_argv.cpp: definieert het toegangspunt voor de consoletoepassing. #erbij betrekken naamruimte std gebruiken; int main(int argc, char* argv) ( if (argc > 1) // als we argumenten doorgeven, dan zal argc groter zijn dan 1 (afhankelijk van het aantal argumenten) ( cout<< argv<

Nadat we de fouten in het programma hebben opgelost, opent u de Windows-opdrachtregel en sleept u het uitvoerbare bestand van ons programma naar het opdrachtregelvenster. Het volledige pad naar het programma wordt weergegeven op de opdrachtregel (maar u kunt het pad naar het programma handmatig invoeren). ), waarna u kunt klikken BINNENKOMEN en het programma zal starten (zie figuur 1).

Figuur 1 - Belangrijkste functieparameters

Omdat we het programma gewoon hebben uitgevoerd en er geen argumenten aan hebben doorgegeven, verscheen het bericht Geen argumenten. Figuur 2 toont de lancering van hetzelfde programma via de opdrachtregel, maar geeft het Open-argument door.

Figuur 2 - Belangrijkste functieparameters

Het argument is het woord Open, zoals je kunt zien in de figuur, dit woord verscheen op het scherm. U kunt meerdere parameters tegelijk doorgeven, gescheiden door een komma. Als u een parameter moet doorgeven die uit meerdere woorden bestaat, moeten deze tussen dubbele aanhalingstekens worden geplaatst en worden deze woorden als één parameter beschouwd. De figuur toont bijvoorbeeld de lancering van een programma, waarbij een argument wordt doorgegeven dat uit twee woorden bestaat: het werkt.

Figuur 3 - Belangrijkste functieparameters

En als je de aanhalingstekens verwijdert. Dan zullen we alleen het woord Het zien. Als u niet van plan bent om informatie door te geven tijdens het uitvoeren van het programma, kunt u de argumenten in de functie main() verwijderen, en kunt u ook de namen van deze argumenten wijzigen. Soms worden er wijzigingen aan de parameters argc en argv aangetroffen, maar dit hangt allemaal af van het type applicatie dat wordt gemaakt of van de ontwikkelomgeving.