[ Jump to content ]

arne.xyz

delivered in beta


#webdev

ClassicPress 1.5.0 was released a few days ago with support for PHP 8. And this solves a lot of problems I had on this blog in the last few month: On the homepage was the title „Archive“ visible, which should not be visible; and on my archive page nothing was shown at all—except for the title; and all I’ve got was mysterious error messages in the logs … Guess I should have better looked at the requirements (which are now, btw, a bit outdated), than I would have seen that I was using the wrong PHP version. Lesson learned.

So now I can start tinkering on this blog again and not try to hunt this weird behavior of ClassicPress.

A lot has changed over the last decade on the web—and so has WordPress: WordPress has started as a simple blogging tool and has grown into a widely used CMS with a simple interface for (new) users and a huge ecosystem of extensions, themes and developers. That’s great—and a reason why I still use it for other projects and at work—but WordPress has outgrown my needs for a simple blogging tool that I want for my blog. And now, with WordPress 6.0 around the corner, it’s time to switch to ClassicPress. ClassicPress is a fork of WordPress 4.9—or: the pre-Gutenberg era—and so exactly what I want my blogging tool to be: simple.

Lately I had a tough time to figure out how to serve a Unity3D WebGL export via AWS CloudFront from an AWS S3 origin after updating to Unity3D 2020.01 with it’s new WebGL loader. I don’t describe how to connect AWS CloudFront to serve files from AWS S3—Andrew Welch does this neatly in his tutorial (one can skip the last step about Craft CMS, though)—I focus on the special configuration the Unity3D files need.

The new WebGL loader

The new WebGL loader requires that certain files are served in a specific way, contrary to the default web-server configurations.
From the forums:

When hosting such a build on a server, the following http headers should be added to the server responses in order to make the build load correctly:

  • .gz files should be served with a Content-Encoding: gzip response header.
  • .br files should be served with a Content-Encoding: br response header.
  • .wasm, .wasm.gz or .wasm.br files should be served with a Content-Type: application/wasm response header.
  • .js, .js.gz or .js.br files should be served with a Content-Type: application/javascript response header.

The Apache configuration example makes it even clearer:

<IfModule mod_mime.c>
# The following lines are required for builds without decompression fallback, compressed with gzip
RemoveType .gz
AddEncoding gzip .gz
AddType application/octet-stream .data.gz
AddType application/wasm .wasm.gz
AddType application/javascript .js.gz
AddType application/octet-stream .symbols.json.gz

# The following lines are required for builds without decompression fallback, compressed with brotli
RemoveType .br
RemoveLanguage .br
AddEncoding br .br
AddType application/octet-stream .data.br
AddType application/wasm .wasm.br
AddType application/javascript .js.br
AddType application/octet-stream .symbols.json.br

# The following line improves loading performance for uncompressed builds
AddType application/wasm .wasm
</IfModule>

On AWS

The easiest way to serve the Unity3D WebGL files via AWS CloudFront from an AWS S3 origin with the correct configuration is to set the correct Content-Type and Content-Encoding in the S3 bucket. Then CloudFront serves them to the user with the correct configuration directly.

To achieve this, one can set the correct metadata of the files via the AWS S3 management console: Select the file, open the “Actions” menu, select “Change metadata”, set the metadata in the opening pop-over on the right-hand side.

Screenshot: AWS S3 console with opened edit view for file metadata

At one point I wrote a small helper script in Python, using boto3, to set the correct metadata after I uploaded the files manually:


Finally, the next step—that I didn’t took, because it worked for me at this point—would be to upload the files with this script and set the correct metadata directly.

Heute gab es auf einer von mir betreuten Website mit MODX ein merkwürdiges Problem: Die Startseite sowie alle weiteren Unterseiten waren plötzlich weiß und zeigten keine Inhalte mehr an – der Zugang zum Backend lief aber zum Glück noch.

Auf der Suche nach der Ursache wollte ich zunächst ins Fehlerprotokoll gucken, aber die Seite im Backend lud sich endlos selbst neu, da das Error-Log zu groß war: 1,1 GB!

Per FTP auf dem Server angemeldet, das Fehlerprotokoll, /core/cache/logs/error.log, heruntergeladen und auf dem Server gelöscht.
Die Startseite und alle Unterseiten waren daraufhin wieder erreichbar – Symptom behoben, aber die Ursache noch nicht.

Beim Surfen durch die Seite füllte sich das Fehlerprotokoll innerhalb weniger Minuten wieder, je nach Unterseite mit vielen Bildern sogar um einige MB pro Seitenaufruf, sodass das Log schon nach kurzer Zeit wieder bei 10, 30 und 80 MB war.

Die Ursache für das große Error-Log war das Modul phpThumb(), das reihenweise Fehlermeldungen wie folgende generierte:

[2018-03-15 13:20:18] (ERROR @ /mnt/web###/##/##/########/htdocs/project/website/core/components/phpthumbof/model/phpthumbof.class.php : 156) [pThumb] Resource: 1 || Image: /home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg  
Could not generate thumbnail
phpThumb debug output:
	[0] => phpThumb() v1.7.14-201608101311 in file "phpthumb.class.php" on line 229
	[1] => setSourceFilename(/home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg) set $this->sourceFilename to "/home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg" in file "phpthumb.class.php" on line 294
	[2] => $AvailableImageOutputFormats = array(text;ico;bmp;wbmp;gif;png;jpeg) in file "phpthumb.class.php" on line 969
	[3] => $this->thumbnailFormat set to $this->config_output_format "jpeg" in file "phpthumb.class.php" on line 980
	[4] => $this->thumbnailFormat set to $this->f "jpeg" in file "phpthumb.class.php" on line 987
	[5] => $this->thumbnailQuality set to "75" in file "phpthumb.class.php" on line 997
	[6] => resolvePath: /home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg (allowed_dirs: Array
(
)
) in file "phpthumb.class.php" on line 1140
	[7] => resolvePath: iteration, path=/home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg, base path = /mnt/web###/##/##/########/htdocs/project/website in file "phpthumb.class.php" on line 1159
	[8] => resolvePath: stop at component 4 in file "phpthumb.class.php" on line 1175
	[9] => resolvePath: stop at path=/home/strato/http/premium in file "phpthumb.class.php" on line 1178
	[10] => resolvePath: no match, returning null in file "phpthumb.class.php" on line 1180
	[11] => !$this->config_allow_src_above_docroot therefore setting "" (outside "/mnt/web###/##/##/########/htdocs/project/website") to null in file "phpthumb.class.php" on line 1344
	[12] => $this->sourceFilename set to "" in file "phpthumb.class.php" on line 894
	[13] => phpThumb() v1.7.14-201608101311
http://phpthumb.sourceforge.net

Error messages disabled.

edit phpThumb.config.php and (temporarily) set
$PHPTHUMB_CONFIG['disable_debug'] = false;
to view the details of this error in file "phpthumb.class.php" on line 4126
	[14] => resolvePath: /home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg (allowed_dirs: Array
(
)
) in file "phpthumb.class.php" on line 1140
	[15] => resolvePath: iteration, path=/home/strato/http/premium/rid/##/##/########/htdocs/project/website/assets/gallery/12/126.jpg, base path = /mnt/web###/##/##/########/htdocs/project/website in file "phpthumb.class.php" on line 1159
	[16] => resolvePath: stop at component 4 in file "phpthumb.class.php" on line 1175
	[17] => resolvePath: stop at path=/home/strato/http/premium in file "phpthumb.class.php" on line 1178
	[18] => resolvePath: no match, returning null in file "phpthumb.class.php" on line 1180
	[19] => !$this->config_allow_src_above_docroot therefore setting "" (outside "/mnt/web###/##/##/########/htdocs/project/website") to null in file "phpthumb.class.php" on line 1344
	[20] => SetCacheFilename() _src set from md5($this->sourceFilename) "" = "d41d8cd98f00b204e9800998ecf8427e" in file "phpthumb.class.php" on line 3520
	[21] => SetCacheFilename() _par set from md5(_farC_w970_dpi150_q75) in file "phpthumb.class.php" on line 3553
	[22] => starting ExtractEXIFgetImageSize() in file "phpthumb.class.php" on line 3314
	[23] => skipping getimagesize() because $this->sourceFilename is empty in file "phpthumb.class.php" on line 3326
	[24] => getimagesize("") failed in file "phpthumb.class.php" on line 3357
	[25] => $this->useRawIMoutput=true after checking $UnAllowedParameters in file "phpthumb.class.php" on line 1595
	[26] => ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty in file "phpthumb.class.php" on line 1640
	[27] => ImageMagickThumbnailToGD() failed in file "phpthumb.class.php" on line 3364
	[28] => SetOrientationDependantWidthHeight() starting with ""x"" in file "phpthumb.class.php" on line 3293
	[29] => SetOrientationDependantWidthHeight() setting w="970", h="0" in file "phpthumb.class.php" on line 3309
	[30] => EXIF thumbnail extraction: (size=0; type=""; 0x0) in file "phpthumb.class.php" on line 3421
	[31] => starting SourceImageToGD() in file "phpthumb.class.php" on line 3679
	[32] => Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty in file "phpthumb.class.php" on line 3751
	[33] => $this->gdimg_source is still empty in file "phpthumb.class.php" on line 3803
	[34] => ImageMagickThumbnailToGD() failed in file "phpthumb.class.php" on line 3805
	[35] => phpThumb() v1.7.14-201608101311
http://phpthumb.sourceforge.net

Error messages disabled.

edit phpThumb.config.php and (temporarily) set
$PHPTHUMB_CONFIG['disable_debug'] = false;
to view the details of this error in file "phpthumb.class.php" on line 4126
	[36] => SourceImageToGD() failed in file "phpthumb.class.php" on line 374
----------------------

»Could not generate thumbnail« war zunächst das Offensichtlichste und Verständlichste an der Fehlermeldung. Eine Google-Suche danach brachte nur ein Ergebnis, dass leider keine Lösung aber einen wichtigen Hinweis lieferte: Irgendetwas stimmt mit den Pfaden zu den Bild-Dateien nicht.

In der Haupt-Konfigurationsdatei /core/config/config.inc.php fiel mir bereits auf, dass es zwei absolute Pfade gibt (Zahlen/IDs durch »#« ersetzt):

  1. /home/strato/http/premium/rid/##/##/########/htdocs/project/website/
  2. /mnt/web###/##/##/########/htdocs/project/website/

Diese waren verschiedenen Einstellungen zugeordnet; jedoch ohne erkennbaren Grund, warum die erste Variante bei der einen Einstellung und die zweite Variante bei einer anderen. Bei anderen MODX-Websites bei anderen Hostern, wie All-Inkl.com oder Uberspace, sind die Pfade bei allen Einstellungen identisch.

Strato nutzt zwei absolute Pfade für Websites. Einmal den, ich nenne es mal, »offiziellen« /home/strato/http/premium/rid/##/##/########/htdocs/; und den »inoffiziellen« (wahrscheinlich physischen) Pfad /mnt/web###/##/##/########/htdocs/.
Ein Blick in die PHP-Konfiguration zeigt auch: der erste Pfad steht auch in den üblichen Server-Variablen wie _SERVER["DOCUMENT_ROOT"]; der zweite Pfad tauch in – für mich bisher ungewöhnlichen – Server-Variablen wie _SERVER["RZ_path"] auf.

Nach einigen Versuchen und wiederholtem Lesen jeder Zeile der Fehlermeldung, war schließlich klar was genau die Ursache für die Fehler-Tirade ist: phpThumb arbeitet mit dem zweiten, »inoffiziellen« Pfad, bekommt aber von MODX die Pfade zu den Bild-Dateien in der ersten, »offiziellen« Variante. Und dann, beim »auflösen« der Pfade passiert das, was in den Zeilen 7–11 bzw. 15–19 der Fehlermeldung steht: phpThumb verlässt den Bereich, den es lesen darf (docroot also Document Root) und findet die Bild-Datei nicht – denn für phpThumb sind diese beiden Pfade nicht identisch und kann sie nicht, wie anscheinend Strato, synonym verwenden.

Die Lösung ist also, die Pfade an phpThumb anpassen: in der /core/config/config.php und der /connectors/config.core.php alle Pfade auf die zweite Pfad-Variante umstellen, schon findet phpThumb die Bild-Dateien und die Fehlermeldungen hören auf.

wp-blank ist ein einfaches Starter-Theme für WordPress mit dem Fokus auf die wichtigsten Funktionen von WordPress und gutes Markup, also sauberes und logisches HTML.

Nachdem ich nun seit einigen Jahren für Blogs und Websites individuelle Themes für WordPress baue, und diese Themes in gewisserweise immer aufeinander aufgebaut haben, wurde es Zeit die für mich wichtigsten Funktionen in einem Starter-Theme für den schnellen Start in die Entwicklungs zu bündeln.

Im Gegensatz zu den Standard-Themes von WordPress, die Twenty-Reihe (»Twenty Eleven«, »Twenty Twelve«, etc.), soll wp-blank im Quellcode übersichtlicher und verständlicher sein; und im Gegensatz zu anderen Starter-Themes nutzt wp-blank nicht jede verfügbare WordPress-Funktion und hängt auch nicht von einem Frontend-Framework wie Bootstrap ab.

Screenshot des WordPress-Themes wp-blank 1.0

wp-blank soll einen schnellen Start in die Theme-Entwicklung bieten und gutes, sauberes Markup generieren, zudem man dann sein eigenes CSS für sein Design hinzugeben muss. Außerdem nimmt wp-blank die Best-Practice-Ansätze aus der Webentwicklung auf, u.a. für Barrierefreiheit (Accessibility), Mikro-Daten nach Schema.org zur Suchmaschinen-Optimierung, Platzhalter-Grafiken mit Verknüpfungen für iOS- und Windows-Lesezeichen und viele weitere Details. Ein vollständige Liste der Features findet sich in der README.

Wie gesagt ist wp-blank nur ein Ausgangspunkt für sein einges Theme: Jede Funktionalität, die über den Standard hinausgeht, muss in das eigene Theme eingebaut werden und jedes zusätzliche, individuelle Seiten- oder Post-Template muss ebenfalls selbst angelegt werden. Aber genau das ist der Sinn bei wp-blank: ein minimaler aber optimaler Start-Punkt für ein individuelles WordPress-Theme.

Über Fragen, Anmerkungen oder Fehler-Hinweise freue ich mich sehr – wenn möglich am Besten als Issue auf GitHub einreichen.

Download und Code bei GitHub.