Vi undersöker hur vi kan konfigurera webbservrar för redirects. Vi fokuserar på att lösa mönster 4 från uppslagning av företeelser.
Vi vill konfigurera Apache och IIS för att stödja följande interaktion:
GET /id/x1
Host: m1.se
----
HTTP/1.1 303 See Other
Location: /api/x1
Link:
</api/x1>; rel="describedby",
<https://m4.se/lookup?uri=https%3A%2F%2Fm1.se%2Fid%2Fx1>; rel="alternate"
Obs. Lösningarna nedan är för enklare uppslagningar som kan lösas genom omskrivningar av pathen, inte mer komplicerade fall, (se t.ex. mönster 2). Undantaget är när vi endast har ett fåtal id:n som inte förändras ofta, i en sådan situation kan man hårdkoda uppslagning av varje id i konfigurationen. I alla andra situationer krävs en egen implementation som agerar webbserver. En sådan implementation fungerar oftast genom att den slår mot en databas som innehåller en översättning mellan id. Oftast servas sådana implementationer bakom en mer standardiserad webbserver som apache eller IIS som då agerar som "reverse proxy", ofta för att garantera skalbarhet, säkerhet eller bara för att förenkla driftsmiljön på en server.
Apache tillhandahåller ett rikt konfigurationsspråk, så det som beskrivs nedan är förslag på tillvägagångssätt. Vi använder oss av konfigurationsblocket Location
för att begränsa oss till endast adresser under /id/
. Vi använder sen RedirectMatch
direktivet för att genomföra 303 redirect och därefter sätter vi två link headrar via Header
direktivet. Notera att vi behöver escapa pathen som finns i REQUEST_URI
variabeln via escape
funktionen.
<Location "/id">
RedirectMatch 303 "^/id/(.+)" "/api/$1"
Header Set Link "<%{REQUEST_URI}>; rel=\"describedby\", <https://m4.se/lookup?uri=https%3A%2F%2Fm1.se%{escape:REQUEST_URI}; rel=\"alternate\""
</Location>
Läs mer om konfigurationsblock, redirect, headrar samt variabler, uttryck och funktioner.
Ett alternativ är att använda mod_rewrite, detta kan vara användbart om du behöver kombinera med mer komplicerade villkor, t.ex. för content negotiation (se sektion om detta längre ner).
RewriteEngine on
RewriteRule "^/id/(.+)" "/api/$1" [R=303]
<Location "/id">
Header Set Link "<%{REQUEST_URI}>; rel=\"describedby\", <https://m4.se/lookup?uri=https%3A%2F%2Fm1.se%{escape:REQUEST_URI}>; rel=\"alternate\""
</Location>
Läs mer på den officiella dokumentationen av mod_rewrite.
För att åstadkomma redirects i IIS behöver man använda URL Rewrite modulen. Du kan behöva installera modulen.
Följ instruktionerna för att skapa en rewrite regel.
Under rubriken "Creating a redirect rule" ska du ange följande:
- Ange ett regelnamn som passar dig.
- Som pattern anger du:
^id/(.+)
. - Som action type väljer du
Redirect
. - Som Redirect URL anger du:
api/{R:1}
. - Som redirect type anger du:
See other (303)
.
Resultatet bör se ut som följer i %SystemDrive%\inetpub\wwwroot\Web.config
:
<rewrite>
<rules>
<rule name="__ditt_regelnamn__">
<match url="^id/(.+)" />
<action type="Rewrite" url="api/{R:1}" redirectType="See other"/>
</rule>
</rules>
</rewrite>
För att lägga till link
headern behöver vi använda en outbound rewrite rule. Outbound rules har stor flexibilitet och det finns ingen perfekt guide att peka på, de närmaste guiderna skriver om hur man skriver om länkar inne i den HTML som leveras samt hur en existerande Location header skrivs om. Båda exemplena involverar mycket extra komplexitet som vi inte behöver, de kan dock fungera att titta på då de innehåller en del screenshoots. Det som behöver göras är:
- Skapa en ny
rule
genom att välja "blank rule" under "outbound rules". - Ge regeln ett namn.
- Under "Matching scope":
- välj
Server variable
- ange
RESPONSE_Link
som variabelnamn - Välj
Matches the value
för "variable value" - Välj
Regular expression
för "Using" - Skriver in uttrycket
^$^
för "pattern".
- välj
- Under "Condition" lägg in en rad:
{REQUEST_URI
under kolumnen "input"Matches the pattern
under kolumnen "type"^/id/(.*)$
under kolumnen "Pattern".
- Under action:
- ställ in "Action type" till
Rewrite
- ange
<{REQUEST_URI}>; rel=\"describedby\", <https://m4.se/lookup?uri={UrlEncode:https://m1.se{REQUEST_URI}}>; rel=\"alternate\"
som "value"
- ställ in "Action type" till
Efter att du sparat bör resultatet av detta att följande struktur har dykt upp i %SystemDrive%\inetpub\wwwroot\Web.config
.
<outboundRules>
<rule name="__ditt_regelnamn__">
<match serverVariable="RESPONSE_Link" pattern="^$" />
<conditions>
<add input="{REQUEST_URI}" pattern="^/id/(.*)$" />
</conditions>
<action type="Rewrite" value="<{REQUEST_URI}>; rel=\"describedby\", <https://m4.se/lookup?uri={UrlEncode:https://m1.se{REQUEST_URI}}>; rel=\"alternate\"" />
</rule>
</outboundRules>
Vi undersöker nu hur vi kan konfigurera webbservrar praktiskt för content negotiation. Vi fokuserar på att lösa mönster 3 från uppslagning av informationsresurser.
Det vill säga, vi vill konfigurera Apache och IIS för att stödja uppslagning av JSON-LD och XML respektive.
Anrop för att få application/ld+json
:
GET /api/x1 HTTP/1.1
Host: m1.se
Accept: application/ld+json,application/json;q=0.9
----
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: </api/x1>; rel="canonical"; type="application/ld+json",
</api/x1>; rel="alternate"; type="text/xml",
{
"@context": {
"namn": "http://purl.org/dc/title"
},
"@id": "https://m1.se/id/x1",
"namn": "En röd boll",
...
}
Anrop för att få text/xml
:
GET /api/x1 HTTP/1.1
Host: m1.se
Accept: text/xml;q=0.9
----
HTTP/1.1 200 OK
Content-type: text/xml
Link: </api/x1>; rel="canonical"; type="application/ld+json",
</api/x1>; rel="alternate"; type="text/xml",
<?xml version="1.0" encoding="UTF-8"?>
<Boll>
<name>En röd boll</name>
...
</Boll>
Om vi antar att JSON-LD och XML versionerna av resursen finns i samma katalog med olika filändelser, typiskt .jsonld
och .xml
. I detta scenario kan vi använda Apaches MultiType option och lägga till korrekt matchningar mellan mediatyper och filändelser.
ServerName m1.se
DocumentRoot /var/www/
<Directory "/api">
Options Multiviews
AddType text/xml .xml
AddType application/ld+json .jsonld
Header Set Link "<%{REQUEST_URI}>; rel=\"canonical\"; type="application/ld+json", <%{REQUEST_URI}>; rel=\"alternate\"; type=\"text/xml\""
</Directory>
I många fall finns inte de olika formaten sparade på disk, istället får man ut dem genom att ställa frågan vidare mot ett annat system. I detta fall agerar Apache som en reverse proxy och vi behöver förlita oss på mod_rewrite eftersom det blir mer komplicerat med villkor kring format. Nedan antar vi att det andra systemet är driftsatt på samma server och tar en parameter format
med den mediatyp som efterfrågas.
RewriteEngine on
RewriteCond %{HTTP_ACCEPT} ^application/ld+json
RewriteRule "^/api/(.+)" "http://localhost:8000/$1?format=application/ld+json" [P]
RewriteCond %{HTTP_ACCEPT} ^application/ld+json
RewriteRule "^/api/(.+)" "http://localhost:8000/$1?format=application/ld+json" [P]
<Location "/api">
Header Set Link "<%{REQUEST_URI}>; rel=\"canonical\"; type="application/ld+json", <%{REQUEST_URI}>; rel=\"alternate\"; type=\"text/xml\""
</Location>
Observera att tekniken ovan inte är begränsad till system som är driftsatta på samma server.
Oavsett om man använder metoden med filändelser eller slår mot ett annat system behöver man använda URL rewrite modulen för att skapa link headers. Se detaljerad dokumentation högre upp för detta. Resultatet bör bli ungefär detta:
<outboundRules>
<rule name="Set Link Header">
<match serverVariable="RESPONSE_Link" pattern="^$" />
<conditions>
<add input="{REQUEST_URI}" pattern="^/api/(.*)$" />
</conditions>
<action type="Rewrite" value="<{REQUEST_URI}>; rel=\"canonical\"; type="application/ld+json", <{REQUEST_URI}>; rel=\"alternate\"; type=\"text/xml\"" />
</rule>
</outboundRules>
Se dokumentation om hur man skapar en översättningstabell (mimeMap) mellan olika filändelser och mediatyper i IIS kongfiguration för statiskt innehåll.
Läs om hur man konfigurerar regler för reverse proxy funktionalitet i IIS.
Konfigurationen bör se ut ungefär som följer:
<rewrite>
<rules>
<rule name="Reverse proxy för JSON-LD" stopProcessing="true">
<match url="^api/(.*)" />
<conditions>
<add input="{ALL_HTTP}" pattern="HTTP_ACCEPT:application/ld\+json" />
</conditions>
<action type="Rewrite" url="http://localhost:8080/{R:1}?format=application/ld+json" />
</rule>
<rule name="Reverse proxy för JSON-LD" stopProcessing="true">
<match url="^api/(.*)" />
<conditions>
<add input="{ALL_HTTP}" pattern="HTTP_ACCEPT:text/xml" />
</conditions>
<action type="Rewrite" url="http://localhost:8080/{R:1}?format=text/xml" />
</rule>
</rules>
</rewrite>
Observera att tekniken inte är begränsad till system som är driftsatta på samma server.