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

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

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

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

``` bash
apt install libnginx-mod-http-xslt-filter
```

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

``` /etc/nginx/default
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`:

``` /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>
```
* TITLE, DESCRIPTION - ваші значення
* значення `xsl:param` - перекидаються з відповідних змінних оточення `/etc/nginx/default`
* фільтр `select="list/*[not(contains(., '.partial'))]"` в `xsl:for-each` - виключає з фіду розширення `.partial` (бо наш скрипт відвантаження реалізовано з `rclone` і RSS таким чином може сповіщати про недовантажені аудіо-файли)
* в прикладі також не вказано `<guid>` - можливо його варто вказати на прикладі патерну `<link>`

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

``` bash
sudo systemctl reload nginx
```

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

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

=> fancyindex-for-nginx.gmi Fancyindex: кастомізований список файлів для Nginx