Block > Goto

 7 min (1451 Wörter, 9282 Zeichen)

Inhaltsverzeichnis
Taschencomputer Sharp PC-1500A
Taschencomputer Sharp PC-1500A

Mit dem Taschenrechner Taschencomputer Sharp PC-1500 von meinem Vater habe ich vor Dekaden (ca. 2) angefangen zu programmieren. Ganz simpel in Basic. Haengen geblieben ist auf jeden Fall das “goto” *in Nostalgie schwelg*


Einen Weiterleitungsservice (bzw. Kurz-URL-Dienst ) wie bitly wollte ich schon lange selbst hosten. Open Source Varianten gibt es ja einige .

Aber warum noch eine weitere Software einsetzen, wenn es auch einfach™ mit Hugo geht, was ich sowieso schon nutze?

Im Folgenden stelle ich 3 Varianten vor, einmal die native Version mit Aliases (wenigster Aufwand, aber auch Voraussetzung fuer die beiden anderen Varianten), dann via einem Apache Webserver und .htaccess-Dateien (mittlerer Aufwand, Apache muss natuerlich eingesetzt werden) und zuletzt via einem nginx Webserver und inkludierten Dateien (hoechster Aufwand, nginx muss natuerlich eingesetzt werden).

Aliases #

Das folgende ist abgeguckt von Dan North (von dort kam auch die Inspiration fuer das alles hier) und nutzt das Hugo Alias Template .

Im Prinzip nutze ich dafuer eine eigene Sektion unter content namens goto.

Fuer die goto-Uebersichtsseite nutze ich dazu ein list.html Template:

 layouts/goto/list.html

1
2
3
4
5
{{ define "main" }}
  {{ partial "title.html" . }}
  {{ .Content }}
  {{ partial "goto-list.html" . }}
{{ end }}

title.html enthaelt quasi nur die Ueberschrift und .Content den Text auf dieser Uebersichtsseite. Spannend ist das Partial goto-list.html:

 layouts/partials/goto-list.html

1
2
3
4
5
6
7
<ul>
{{- range where .Pages "Params.public" "eq" true -}}
<li><a href="{{ .Permalink }}">{{ with .File }}{{ .BaseFileName }}{{ end }}</a> (kurz fuer &bdquo;{{ .Title }}&ldquo;) leitet weiter zu
  {{ with print "[" .Params.target "](" .Params.target ")" }}{{ $.Page.RenderString . }}{{ end }}
</li>
{{- end -}}
</ul>

Hierdurch werden nur die Shortlinks in der Uebersicht angezeigt, die den Parameter public auf true gesetzt haben. Eine Beispieldatei ist z.B. diese hier, die dann dort auch angezeigt wird:

 content/goto/ls.md

1
2
3
4
5
---
title: "Linkshrubbery"
public: true
target: https://ls.uxg.ch
---

Der Rest der Magic passiert dann auf der Detailseite, hier wird die Markdowndatei via des Alias Templates in eine kleine HTML-Datei umgewandelt, die dann mit Hilfe von dem <meta> http-equiv Attribut eine Weiterleitung auf das target macht:

 layouts/goto/single.html

1
2
{{- /* https://dannorth.net/hugo-redirects/ */ -}}
{{- template "_internal/alias.html" (dict "Permalink" .Params.target) -}}

Soweit so gut, dieses “Feature” nutze ich auch in vielen alten Eintraegen, damit auch weiterhin Weiterleitungen funktionieren.

Leider hat das einen Nachteil, denn es ist keine “richtige” Weiterleitung. Z.B. wird curl es nicht als Weiterleitung erkennen , da der Status-Code keine 3xy ist.

Apache #

Diese Variante habe ich mir von Til Seiffert abgeguckt . Dort wird eine .htaccess-Datei genutzt, um alle Hugo Aliases in einer Datei zu sammeln und damit eine “richtige” und schnellere Weiterleitung zu bekommen.

In meinem Anwendungsfall brauche ich das nicht fuer alle Aliases, sondern eben nur fuer die in der Sektion goto, aber die Vorgehensweise ist aehnlich.

Zur Nutzung muss die hugo.toml , genauer outputFormats und mediaTypes erweitert werden:

[outputFormats.htaccess]
  baseName       = ".htaccess"
  isPlainText    = true
  mediaType      = "text/htaccess"
  notAlternative = true

[mediaTypes."text/htaccess"]
  suffixes = ""

Zudem muss noch im Front matter der content/goto/_index.md festgelegt werden, dass fuer diese Sektion “html” und “htaccess” ausgegeben werden soll, aber kein “rss”, was erstmal der Standard fuer Sektionen ist:

---
title: "goto"
# no rss here please, but html and htaccess
outputs:
- html
- htaccess
---

Die eigentliche .htaccess fuer die Sektion goto sieht dann wie folgt aus (hier wird eine Hugo Page Methode namens File genutzt):

 layouts/goto/section.htaccess

1
2
3
4
RewriteEngine On
{{ range .Pages -}}
Redirect 302 ./{{ with .File }}{{ .BaseFileName }}{{ end }}(\/?)$ {{ .Params.target }}
{{ end -}}

Ich habe hier den HTTP-Statuscode 302 gewaehlt, da sich die Ziele theoretisch aendern koennen (und nginx diesen Code auch nutzt fuer die temporaere Weiterleitung). 307 waere auch eine Moeglichkeit.

Da ich nicht Apache als Webserver einsetze, kann ich nicht garantieren, dass das auch alles so klappt. Aber mit der .htaccess in einem Verzeichnis sollte™ das gehen. Wenn nicht, gerne Bescheid geben.

nginx #

Da ich als Webserver nginx einsetze und hierbei die Nutzung von .htaccess-Dateien keine gute Idee ist, habe ich mir was anderes ueberlegt.

Die Vorgehensweise aehnelt hier sehr der Apache-Variante, denn auch hier muessen outputFormats und mediaTypes in der hugo_toml hinzugefuegt werden:

[outputFormats.nginx]
  baseName       = "nginx"
  isPlainText    = true
  mediaType      = "text/conf"
  notAlternative = true

[mediaTypes."text/conf"]
  suffixes = ["conf"]

Wie bei Apache auch wollen wir diese Datei ja nur in der Sektion goto haben, daher tragen wir auch nur im Front matter der content/goto/_index.md folgendes ein:

---
title: "goto"
# no rss here please, but html, htaccess and nginx
outputs:
- html
- htaccess
- nginx
---

Und definieren zu guter Letzt noch eine nginx.conf (Doku ):

 layouts/goto/section.nginx.conf

1
2
3
{{- range .Pages -}}
rewrite ./{{ with .File }}{{ .BaseFileName }}{{ end }}(\/?)$ {{ .Params.target }} redirect;
{{ end -}}

So, jetzt wird es spannend. Wie bekommt nginx jetzt diese Regeln mit? Eine .htaccess koennen wir ja nicht einsetzen.
Aber wir koennen include nutzen ! Das geht auch, wenn die Datei leer ist, allerdings leider nicht, wenn die Datei nicht vorhanden ist.

Entweder wird also der Ordner goto und eine leere nginx.conf angelegt, oder wir passen die nginx Config erst an, wenn die Website mit hugo gebaut wurde.

Jedenfalls sieht meine nginx Config in etwa so aus:

server {
  # [...]
  server_name uxg.ch;
  location / {
    include /path/to/goto/nginx.conf;
  }
}

Nice!

Weiteres #

Hier noch ein paar weitere Anpassungsmoeglichkeiten bzw. Ideen.

Public vs. private #

Im Prinzip koennen auch alle Weiterleitungen oeffentlich sein, dann kann sich der Aufwand mit dem Parameter “public” auch gespart werden.

Allerdings verwende ich den nun und muss sich daher auch drum kuemmern, dass nicht aus Versehen was in den RSS Feeds, der Sitemap oder sonst wo auftaucht.

RSS #

Fuer die Sektion goto habe ich ja im Front matter schon keine RSS-Feeds erlaubt (und damit den Default ueberschrieben ), siehe Apache-Variante bzw nginx-Variante.

Sitemap #

Die Standard sitemap.xml habe ich sowieso schon angepasst, falls ich Seiten habe, die ich mit dem Parameter “exclude” eben nicht in der Sitemap haben will (siehe GitHub Issue #653 dazu). Fuer die Sektion goto kam dann noch ein Zusatz dazu.

Komplett sieht das dann so aus:

 layouts/_default/sitemap.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{{- /* https://github.com/gohugoio/hugo/issues/653 */ -}}
{{- /* https://gohugo.io/templates/sitemap-template/#hugos-sitemapxml */ -}}
{{- /* https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/sitemap.xml */ -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:xhtml="http://www.w3.org/1999/xhtml">
  {{ $excluded := where .Data.Pages ".Params.exclude" "!=" true }}
  {{ range where $excluded "Section" "ne" "goto" }}
    {{- if .Permalink -}}
  <url>
    <loc>{{ .Permalink }}</loc>{{ if not .Lastmod.IsZero }}
    <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod>{{ end }}{{ with .Sitemap.ChangeFreq }}
    <changefreq>{{ . }}</changefreq>{{ end }}{{ if ge .Sitemap.Priority 0.0 }}
    <priority>{{ .Sitemap.Priority }}</priority>{{ end }}{{ if .IsTranslated }}{{ range .Translations }}
    <xhtml:link
                rel="alternate"
                hreflang="{{ .Language.LanguageCode }}"
                href="{{ .Permalink }}"
                />{{ end }}
    <xhtml:link
                rel="alternate"
                hreflang="{{ .Language.LanguageCode }}"
                href="{{ .Permalink }}"
                />{{ end }}
  </url>
    {{- end -}}
  {{ end }}
</urlset>

Cleanup #

Theoretisch brauchen wir mit Einsatz von Apache oder nginx die Alias-Dateien nicht mehr, also koennte die Datei layouts/goto/single.html auch geloescht werden.

“Anonym” weiterleiten #

Um “anonym”, also ohne Referrer auf andere Websites weiterzuleiten (auch Dereferrer genannt), kann das <meta> name Attribut genutzt werden.

Fuer ein Codebeispiel siehe redirect.html#L9 oder diesen curl-Aufruf:

$ curl -L "https://url.scriptsez.net?https://uxg.ch"
<html><head><meta name="referrer" content="no-referrer" /><meta http-equiv=refresh content="0;url='https://uxg.ch'"></head></html>

Entweder kann also im Prinzip das Alias-Template um diese Zeile erweitert werden oder im Webserver der entsprechende Parameter gesetzt werden.

QR-Code #

Als kleine™ Spielerei koennte jetzt noch an jeden “goto” ein QR-Code dran geklebt werden. Z.B. koennte neben der nginx Datei auch noch fuer jeden Link eine Textdatei erstellt werden, die den Link enthaelt. Ein Script koennte dann vor dem Bauen der Website mit hugo via find ueber all diese Textdateien drueberlaufen und mit einem Text-QR-Code ersetzen, die dann z.B. mit readfile eingebunden werden.

Ja, richtig gelesen, QR-Codes muessen nicht unbedingt Bilder sein, sondern koennen auch aus Text bestehen. qrencode bringt sowas auch schon mit:

qrencode -t UTF8i "https://uxg.ch" | sed 's/[ \t]*$//;/^$/d'

Ein kleiner Shortcode dazu:

 layouts/shortcodes/qr-code.html

1
2
3
4
5
6
7
<style>
  .qr-code {
    font-family: monospace;
    line-height: 1.0;
  }
</style>
<pre class="qr-code">{{- .Inner | safeHTML -}}</pre>

Und damit sieht das ganze dann so aus:

    █▀▀▀▀▀█  █▀█▀ █▀▀▀▀▀█
    █ ███ █ ▄█▄▄  █ ███ █
    █ ▀▀▀ █ ▀ █ █ █ ▀▀▀ █
    ▀▀▀▀▀▀▀ ▀▄█ █ ▀▀▀▀▀▀▀
    ▀█▄▄ ▀▀▀ ▀   ▄  ▀█▄▄
    ▀█▄▄▀ ▀▀█▄██▀█▀█▄▄█▀
    ▀ ▀   ▀▀▄▀ ▀▀▄  ▄▄▄▀▄
    █▀▀▀▀▀█ ██▀▀▀█▄▀ ▄█▀
    █ ███ █  █▀▀ ▀███▀▄▀▀
    █ ▀▀▀ █ ▄▀▄█▀█▀████▀▀
    ▀▀▀▀▀▀▀ ▀  ▀▀ ▀▀ ▀ ▀

Geil! Ausgelesen werden koennen diese z.B. mit einer meiner Lieblings-Android-Apps: Binary Eye


 Linkshrubbery

Beitraginfos

 2024-02-25, 16:21:57
 2024-02-25, 23:18:44
  hugo, linux, osbn, website
 Permalink

Ähnliche Beiträge