Конвертація Nginx autoindex в RSS


В нашій спільноті є сервер IceCast, де віднедавна з'явилась рубрика Подкасти. Вона являє собою звичайну теку `ramfs`, куди скриптом `ytd` збираються аудіо-доріжки новин з Youtube:

https://codeberg.org/YGGverse/ytd


Штатний `autoindex=on` в Nginx - доволі зручний і поширений інструмент, але він не відрізняється широтою опцій. Спочатку, я відкрив для себе модуль "fancyindex", який дозволяє вказувати для списків файлів свою шапку і футер, а звідти - кастомізувати оформлення (зокрема робити тему адаптивною до темного середовища). Згодом, в контексті тих же Подкастів, з'явилась ідея організувати підписки по RSS, але стандартний `autoindex` вміє тільки формати XML і JSON.


Не довго шукаючи рішення і майже випадково не написавши свій проксі-сервер-велосипед, дізнався про ще один готовий модуль Nginx:


apt install libnginx-mod-http-xslt-filter

Для його роботи, потрібно створити віртуальний шлях:


server {
    # ...
    location ~ ^/podcast/([A-z0-9_\-/]+)/rss/?$ {
        alias /mnt/icecast/podcast/$1/;

        autoindex on;
        autoindex_format xml;

        xslt_param host "'$host'";
        xslt_param proto "'$scheme'";
        xslt_param port "'$server_port'";
        xslt_param path "'/podcast/$1/'";

        xslt_types application/xml;
        xslt_stylesheet /etc/nginx/xslt/rss.xsl;

        add_header Content-Type "application/rss+xml";
    }
}

Тепер потрібно створити сам шаблон перетворення штатного `autoindex_format xml`, згідно `xslt_stylesheet /etc/nginx/xslt/rss.xsl`:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <xsl:param name="host" />
    <xsl:param name="proto" />
    <xsl:param name="port" />
    <xsl:param name="path" />
    <xsl:template match="/">
        <rss version="2.0">
            <channel>
                <title>TITLE</title>
                <description>DESCRIPTION</description>
                <link><xsl:value-of select="concat($proto, '://', $host, ':', $port, $path)" /></link>
                <xsl:for-each select="list/*[not(contains(., '.partial'))]">
                    <item>
                        <title><xsl:value-of select="."/></title>
                        <link><xsl:value-of select="concat($proto, '://', $host, ':', $port, $path, .)" /></link>
                        <pubDate><xsl:value-of select="@mtime"/></pubDate>
                    </item>
                </xsl:for-each>
            </channel>
        </rss>
    </xsl:template>
</xsl:stylesheet>

Тепер перезавантажуємо налаштування Nginx:


sudo systemctl reload nginx

І підписуємось на стрічку за адресою `http://host/podcast/name/rss`


Дивіться також


Fancyindex: кастомізований список файлів для Nginx



/uk/