Maximale URL-Länge bei HTTP

Der Uniform Resource Locator, oder in der Kurzform die URL, wird sicherlich jedem schon begegnet sein. Die URL setzt sich aus einem Schema und einem für das Schema spezifischen Part zusammen. Getrennt werden die beiden Bestandteile durch einen Doppelpunkt. Bei HTTP wäre die Angabe des Schemas (http) und dem anschließenden spezifischen Teil mit dem Host, eventuellen Informationen über den Port, Kennwörter und ähnliches und anschließend der Pfad zur gewünschten Ressource. Interessant ist allerdings die Frage, wie lang darf eine solche URL sein? Kurze URLs wie:

http://api.example.com

machen keinerlei Probleme. In der RFC 2616 finden sich erste Anhaltspunkte dazu. Die RFC trägt den Namen Hypertext Transfer Protocol — HTTP/1.1 und definiert eben dieses Protokoll. Im Abschnitt 3.2, der sich um Uniform Resource Identifiers dreht, findet sich im Unterpunkt 3.2.1 folgender Abschnitt:

The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET-based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).

Aus diesem Abschnitt ergibt sich das URLs so lang wie benötigt sein dürfen und das HTTP-Protokoll keinerlei Beschränkung vornimmt. Sollte der Server eine lange URL nicht verarbeiten können, so soll dieser mit dem Statuscode 414 (URI Too Long) antworten. Gleich danach finden sich ein weiterer Hinweis in der RFC:

Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.

Dort wird darauf hingewiesen das es Probleme geben kann, wenn die URL länger als 255 Byte ist. Je nach Kodierung und Sprache (wie z.B. Deutsch oder Japanisch), lassen sich eine unterschiedliche Menge an Informationen in diesen 255 Byte kodieren. Allerdings wurde die RFC 2616 durch die RFC 7230 für obsolet erklärt. In dieser RFC findet sich folgender Absatz:

Various ad hoc limitations on request-line length are found in practice. It is RECOMMENDED that all HTTP senders and recipients support, at a minimum, request-line lengths of 8000 octets.

Mit diesem Absatz wird definiert das HTTP-Clients und Server eine Mindestlänge von 8000 Byte unterstützen sollen. In der Praxis stellt sich nun die Frage was wirklich funktioniert. Es existieren durchaus längere URLs, z.B. sogenannte Data-URLs, allerdings sind dies keine HTTP-URLs, sondern definierten ein eigenes Schema. Daneben existieren alte Untersuchungen zu dem Thema. Unabhängig von der theoretischen Machbarkeit existieren weitere Kriterien, wie die maximale Länge die von Suchmaschinen indiziert werden. Hier schwanken die Zahlen zwischen knapp 1800 Byte bis zu 2048 Byte.

Damit lässt sich die Frage nach der maximalen URL-Länge nicht pauschal beantworten. Mit aktueller Software auf Server- und Client-Seite, sollten 1024 Byte für die URL kein Problem sein. Längere URLs sollten mit Vorsicht genossen werden und ihre Sinnhaftigkeit noch einmal hinterfragt werden.

Services unter systemd einrichten

Das Init-System systemd ist mittlerweile in vielen Linux-Distributionen angekommen. Auch unter Ubuntu ist es seit Version 15.04 integriert. Ein Vorteil des neuen Systems ist, das Services, im Gegensatz zum alten Init-System, relativ unkompliziert erstellt werden können. Dazu muss eine sogenannte Unit erstellt werden. Bei einer Unit handelt es sich um eine Textdatei mit einer entsprechenden Konfiguration. Neben den Units für die Konfiguration eines Services existieren weitere Unit-Typen wie z.B. die Typen mit der Endung .path oder .network. In diesem Artikel soll es allerdings nur um die Units vom Typ Service gehen.

Die Units liegen in unterschiedlichen Orten im Dateisystem. Die vom System vorinstallierten Units sind im Ordner /lib/systemd/system/ zu finden. Eigene Services werden im Ordner /etc/systemd/system/ hinterlegt. Hier können allerdings nur Nutzer mit administrativen Rechten entsprechende Service hinterlegen. Soll ein nicht privilegierter Nutzer eine Unit angelegen, so muss er diese im Verzeichnis ~/.config/systemd/user/ hinterlegen. In den meisten Fällen werden Units für Services im Dateisystem unter dem Pfad /etc/systemd/system/ angelegt. In diesem Ordner soll nun eine Datei für die Unit angelegt werden:

nano languagetool.service

Beispielhaft könnte eine solche Unit wie folgt aussehen:

[Unit]
Description=LanguageTool
After=syslog.target
After=network.target

[Service]
Type=simple
User=languagetool
Group=languagetool
WorkingDirectory=/home/languagetool/server
ExecStart=/usr/bin/java -cp /home/languagetool/server/languagetool-server.jar org.languagetool.server.HTTPServer --config languagetool.cfg --port 3001 --allow-origin "*"
Restart=always
Environment=USER=git HOME=/home/languagetool

[Install]
WantedBy=multi-user.target

Die Unit unterteilt sich in unterschiedliche Bereiche, in diesem Beispiel sind dies Unit, Service und Install. Der Bereich Service ist hierbei nur in Units vom Typ Service zu finden. Im Bereich Unit sind eine kurze Beschreibung des Services und die Abhängigkeiten der Unit hinterlegt. Dabei wird definiert, welche Systeme bereits gestartet sein müssen, bevor der Service gestartet wird. Ein Target entspricht dabei einer Gruppe von Diensten, meist mit einer bestimmten Bedeutung, wie z.B. das Target für die Herstellung der Netzwerkkonnektivität (network-online.target).

In der Service-Gruppe wird der Typ des Services und der Nutzer und die Gruppe definiert, mit welchem bzw. welcher er starten soll. Daneben wird das Arbeitsverzeichnis und die Kommandozeile zur Ausführung des Services definiert. Weiterhin kann das Verhalten des Service, über den Parameter Restart, weiter definiert werden. So kann angegeben werden, dass der Service nach seiner Beendigung wieder neugestartet wird.

In der Install-Sektion wird angeben, wann der Service gestartet werden soll. Das multi-user.target entspricht dem klassischen Start eines normalen Linux-Systems. Ist die Unit definiert, kann sie aktiviert und der Service gestartet werden:

systemctl enable languagetool
systemctl start languagetool

Die Option enable sorgt dafür das die entsprechende Unit aktiviert wird. Dies führt dazu das sie je nach Konfiguration z.B. automatisch beim Systemstart oder bei dem Anschluss bestimmter Hardware gestartet wird. Unter bestimmten Systemen wie Ubuntu, kann der Service auch über das service-Kommando gestartet werden:

service languagetool start

Neben den Optionen enable und start für systemctl, existieren weitere Optionen zur Steuerung der Units. Dies sind unter anderem stop, zum Stoppen des Services und disable zur Deaktivierung der Unit. Mit der Option status, kann der Status eines Service erfragt werden:

systemctl status languagetool

Anschließend erhält der Nutzer den aktuellen Status des Service. Eine weitere wichtige Option ist restart um einen Service manuell neuzustarten. Mithilfe der systemd-Units lassen sich somit schnell Services in ein Linux-System einbinden.

LanguageTool-Server unter Ubuntu aufsetzen

Für die freie Grammatik- und Rechtschreibprüfung LanguageTool existieren eine Reihe von Add-ons, unter anderem für den Browser Firefox.

Standardmäßig nutzen diese Add-ons den vom Projekt bereitgestellten Server unter languagetool.org. Nicht jeder möchte seine Daten zur Korrektur an Dritte schicken und so besteht die Möglichkeit einen eigenen Server aufzusetzen. Dieser kann lokal betrieben oder auf einem eigenen Server installiert werden. In diesem Artikel soll die Installation unter Ubuntu beschrieben werden. Im ersten Schritt muss sich auf dem Server eingeloggt und dort ein neuer Nutzer angelegt werden:

adduser languagetool
su languagetool
cd

Nachdem der Nutzer angelegt wurde und in das entsprechende Home-Verzeichnis des Nutzers gewechselt wurde, kann das LanguageTool heruntergeladen und entpackt werden:

wget https://languagetool.org/download/LanguageTool-4.5.zip
unzip LanguageTool-4.5.zip
mv LanguageTool-4.5 server
rm LanguageTool-4.5.zip

Neben dem LanguageTool, werden noch sogenannte N-Gramme heruntergeladen. Diese dienen der Verbesserung der Erkennungsleistung des LanguageTool. Sie belegen knapp 27 GiB auf der Festplatte, müssen aber nicht zwingend installiert werden:

mkdir ngrams

wget https://languagetool.org/download/ngram-data/ngrams-de-20150819.zip
wget https://languagetool.org/download/ngram-data/ngrams-en-20150817.zip
wget https://languagetool.org/download/ngram-data/ngrams-es-20150915.zip
wget https://languagetool.org/download/ngram-data/ngrams-fr-20150913.zip
wget https://languagetool.org/download/ngram-data/ngrams-nl-20181229.zip

unzip ngrams-de-20150819.zip
unzip ngrams-en-20150817.zip
unzip ngrams-es-20150915.zip
unzip ngrams-fr-20150913.zip
unzip ngrams-nl-20181229.zip

rm ngrams-de-20150819.zip
rm ngrams-en-20150817.zip
rm ngrams-es-20150915.zip
rm ngrams-fr-20150913.zip
rm ngrams-nl-20181229.zip

Damit ist das LanguageTool installiert. Ein erster Test kann erfolgen, indem der Server mittels:

java -cp languagetool-server.jar org.languagetool.server.HTTPServer --port 8081

gestartet wird. Über Curl können erste Testdaten an den Server gesendet werden:

curl --data "language=en-US&text=a first test" http://localhost:8081/v2/check

In meinem Setup wird der Server auf dem Port 8081 (oder einem beliebigen anderen Port betrieben) und ist über einen Reverse Proxy, in diesem Fall Nginx, erreichbar. Dazu muss die Konfiguration angepasst werden:

nano /etc/nginx/sites-available/example

In der Nginx-Konfigurationsdatei wird nun folgende Konfiguration hinterlegt:

server {
        listen   443 ssl;
        listen [::]:443 ssl;

        ssl_certificate /etc/letsencrypt/live/api.example.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/api.example.org/privkey.pem;

        root /var/www/example/api;
        index index.php index.html index.htm;

        server_name api.example.org;

        # proxy for languagetool
        location /languagetool/ {
                proxy_pass http://localhost:8081/v2/;
        }
}

Nachdem die Konfiguration für Nginx hinterlegt wurde, wird Nginx neugestartet:

nginx restart

Über den Browser kann die API nun getestet werden:

https://api.example.org/languagetool/check?language=en-US&text=Wong wong wong

Damit ist die Konfiguration des LanguageTool allerdings noch nicht abgeschlossen. Für den produktiven Betrieb wird eine Konfigurationsdatei unter /home/languagetool/server/ erstellt:

nano languagetool.cfg

Diese Datei wird mit folgendem Inhalt befüllt:

languageModel=/home/languagetool/ngrams

Damit der Service automatisch startet, wird eine systemd-Unit angelegt:

nano /etc/systemd/system/languagetool.service

Diese Datei wird mit folgendem Inhalt befüllt:

[Unit]
Description=LanguageTool
After=syslog.target
After=network.target

[Service]
Type=simple
User=languagetool
Group=languagetool
WorkingDirectory=/home/languagetool/server
ExecStart=/usr/bin/java -cp /home/languagetool/server/languagetool-server.jar org.languagetool.server.HTTPServer --config languagetool.cfg --port 3001 --allow-origin "*"
Restart=always
Environment=USER=git HOME=/home/languagetool

[Install]
WantedBy=multi-user.target

Nachdem die Datei angelegt wurde, wird sie aktiviert und anschließend der Service gestartet:

systemctl enable languagetool
service languagetool start

Zum Test der N-Gramme kann folgende URL aufgerufen:

https://api.example.org/languagetool/check?language=en-US&text=I%20want%20to%20go%20their.

werden. Wenn keine N-Gramme installiert oder konfiguriert sind, kommt ein relativ kurzes JSON als Antwort zurück:

{“software”:{“name”:”LanguageTool”,”version”:”4.5″,”buildDate”:”2019-03-26 11:37″,”apiVersion”:1,”premium”:false,”premiumHint”:”You might be missing errors only the Premium version can find. Contact us at supportlanguagetoolplus.com.”,”status”:””},”warnings”:{“incompleteResults”:false},”language”:{“name”:”English (US)”,”code”:”en-US”,”detectedLanguage”:{“name”:”English (US)”,”code”:”en-US”,”confidence”:0.9999997}},”matches”:[]}

Sind die N-Gramme erfolgreich installiert und konfiguriert, wird das LanguageTool mit einem längeren Response antworten:

{“software”:{“name”:”LanguageTool”,”version”:”4.5″,”buildDate”:”2019-03-26 11:37″,”apiVersion”:1,”premium”:false,”premiumHint”:”You might be missing errors only the Premium version can find. Contact us at supportlanguagetoolplus.com.”,”status”:””},”warnings”:{“incompleteResults”:false},”language”:{“name”:”English (US)”,”code”:”en-US”,”detectedLanguage”:{“name”:”English (US)”,”code”:”en-US”,”confidence”:0.9999997}},”matches”:[{“message”:”Statistics suggests that ‘there’ (as in ‘Is there an answer?’) might be the correct word here, not ‘their’ (as in ‘It’s not their fault.’). Please check.”,”shortMessage”:””,”replacements”:[{“value”:”there”,”shortDescription”:”as in ‘Is there an answer?'”}],”offset”:13,”length”:5,”context”:{“text”:”I want to go their.”,”offset”:13,”length”:5},”sentence”:”I want to go their.”,”type”:{“typeName”:”Other”},”rule”:{“id”:”CONFUSION_RULE”,”description”:”Statistically detect wrong use of words that are easily confused”,”issueType”:”non-conformance”,”category”:{“id”:”TYPOS”,”name”:”Possible Typo”}},”ignoreForIncompleteSentence”:false,”contextForSureMatch”:3}]}

Damit ist der Server komplett eingerichtet. Nun kann der eigene Server bei entsprechenden Add-ons eingerichtet und genutzt werden.

Nachdem der Server aufgesetzt wurde, können entsprechende Add-ons umgestellt werden

Das gleiche Setup kann natürlich genutzt werden, einen solchen Server lokal auf dem eigenen Ubuntu-Rechner zu installieren.

Minecraft-Backup partiell einspielen

Ein Backup ist immer eine gute Idee. Vor allem dann, wenn es das Backup eines Minecraft-Servers ist. Immerhin, kann es dort durchaus einmal zu Unfällen kommen. In einem solchen Fall ist es sinnvoll das vorhandene Backup einzuspielen.

Unfälle passieren; ein Backup sichert so etwas ab

Natürlich soll in den meisten Fällen nicht ein komplettes Backup, sondern nur der betroffene Teil neu eingespielt werden. In diesem Fall sollte allerdings klar sein, wo sich die betroffenen Teile befinden. Die einzelnen Chunks der Minecraft-Welt werden in sogenannten Region-Dateien zusammengefasst. Diese Region-Dateien finden sich im Ordner region, in den Minecraft-Daten.

Mit den Coordinate Tools kann anhand der Koordinaten die entsprechende Region ermittelt werden

Um herauszufinden, welche Regionen neu eingespielt werden müssen, können die Coordinate-Tools des Entwicklers Dinnerbone genutzt werden. Dazu müssen die Koordinaten der beschädigten Region über den Debug-Screen (F3) im Spiel ermittelt werden. Diese Koordinaten werden in die Coordinate-Tools eingegeben. In der Sektion Region Information finden sich anschließend der Dateiname der entsprechenden Region. Diese Datei kann dann vom Backup in den region-Ordner eingespielt werden. Der Minecraft-Server sollte vor dem Einspielen des Backups heruntergefahren und anschließend wieder hochgefahren werden.

Nginx unter macOS mittels Homebrew installieren und nutzen

Nginx wird für gewöhnlich unter Linux genutzt. Für Entwicklungszwecke kann es interessant sein Nginx unter macOS zu betreiben. Zur Installation von Nginx wird Homebrew benötigt. Homebrew ist ein Paketmanager für macOS, mit welchem viele Open-Source-Projekte unter macOS installiert werden können. Ist Homebrew installiert kann Nginx auf dem Terminal mittels:

brew install nginx

installiert werden. Standardmäßig läuft Nginx bei der Installation über Homebrew auf dem Port 8080. Hintergrund ist das der Webserver somit ohne root-Rechte bzw. ohne sudo genutzt werden kann. Wird der Port auf 80 oder generell auf einen Port kleiner 1024 gestellt, werden wieder entsprechende administrative Rechte benötigt. Soll der verwendete Port geändert werden, muss die Konfigurationsdatei angepasst werden:

nano /usr/local/etc/nginx/nginx.conf

In dieser findet sich folgender Block:

server {
  listen       8080;
  server_name  localhost;

Dort kann anschließend der Port geändert werden. Neben dem Port kann dort die Default-Location geändert werden. Dazu wird der server-Block bzw. dessen Unterblock, der location-Block angepasst:

location / {
  root /Users/seeseekey/Web;
  autoindex on;

Die root-Direktive gibt den Pfad an, welcher über den Webserver ausgeliefert wird. Die Option autoindex sorgt für das entsprechende Directory-Listing, was für Entwicklungszwecke nützlich sein kann. Gestartet und gestoppt werden kann der Service mittels:

brew services start nginx

bzw.

brew services stop nginx

Natürlich kann dies mittels restart in einem Rutsch erledigt werden:

brew services restart nginx

Anschließend kann Nginx mit der veränderten Konfiguration genutzt werden.