diff --git a/404.html b/404.html index fd225301a63c13e6951591d63f5d5691f5bfda0f..4d889b42e60d03f7e5687b74c204483254128d58 100644 --- a/404.html +++ b/404.html @@ -269,7 +269,7 @@ <li class="md-nav__item"> <a href="/rustus/hooks/" class="md-nav__link"> - Hooks + Setting up hooks </a> </li> diff --git a/configuration/index.html b/configuration/index.html index 8837a229e6da90426784a9b24aa0553b7746a6f4..b5afb11f774fa491a2552de60b340f5b1c0931eb 100644 --- a/configuration/index.html +++ b/configuration/index.html @@ -6,6 +6,8 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> + <meta name="description" content="How to configure Rusts"> + <link rel="canonical" href="https://s3rius.github.io/rustus/configuration/"> @@ -65,7 +67,7 @@ <div data-md-component="skip"> - <a href="#configuring-data-storage" class="md-skip"> + <a href="#configuring-server" class="md-skip"> Skip to content </a> @@ -274,6 +276,13 @@ </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> + <li class="md-nav__item"> + <a href="#configuring-server" class="md-nav__link"> + Configuring server + </a> + +</li> + <li class="md-nav__item"> <a href="#configuring-data-storage" class="md-nav__link"> Configuring data storage @@ -286,13 +295,33 @@ Configuring info storage </a> + <nav class="md-nav" aria-label="Configuring info storage"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#file-info-storage" class="md-nav__link"> + File info storage + </a> + </li> - - <li class="md-nav__item"> - <a href="#configuring-hooks-storage" class="md-nav__link"> - Configuring hooks storage + + <li class="md-nav__item"> + <a href="#redis-info-storage" class="md-nav__link"> + Redis info storage </a> +</li> + + <li class="md-nav__item"> + <a href="#db-info-storage" class="md-nav__link"> + DB info storage + </a> + +</li> + + </ul> + </nav> + </li> <li class="md-nav__item"> @@ -334,7 +363,7 @@ <li class="md-nav__item"> <a href="../hooks/" class="md-nav__link"> - Hooks + Setting up hooks </a> </li> @@ -364,6 +393,13 @@ </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> + <li class="md-nav__item"> + <a href="#configuring-server" class="md-nav__link"> + Configuring server + </a> + +</li> + <li class="md-nav__item"> <a href="#configuring-data-storage" class="md-nav__link"> Configuring data storage @@ -376,13 +412,33 @@ Configuring info storage </a> + <nav class="md-nav" aria-label="Configuring info storage"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#file-info-storage" class="md-nav__link"> + File info storage + </a> + </li> - - <li class="md-nav__item"> - <a href="#configuring-hooks-storage" class="md-nav__link"> - Configuring hooks storage + + <li class="md-nav__item"> + <a href="#redis-info-storage" class="md-nav__link"> + Redis info storage </a> +</li> + + <li class="md-nav__item"> + <a href="#db-info-storage" class="md-nav__link"> + DB info storage + </a> + +</li> + + </ul> + </nav> + </li> <li class="md-nav__item"> @@ -413,10 +469,212 @@ <p class="admonition-title">Info</p> <p>Some options can be passed only through as CLI parameters</p> </div> +<div class="admonition info"> +<p class="admonition-title">Info</p> +<p>Information about hooks you can find on <a href="../hooks">Hooks page</a>.</p> +</div> +<h2 id="configuring-server">Configuring server</h2> +<p>We use actix to run server. +You can configure on wich <code>host</code> and <code>port</code> rustus is listenging. +Also you can configure number of actix <code>workers</code> that handle connections.</p> +<p><code>--max-body-size</code> is the max number of bytes that users can send in request body.</p> +<p><code>--url</code> is a base URL for all tus requests.</p> +<p><code>--workers</code> by default is euqal to number of physical CPU cores. Edit it carefully.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">CLI</label><label for="__tabbed_1_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>rustus --host <span class="s2">"0.0.0.0"</span> <span class="se">\</span> +<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> --port <span class="m">1081</span> <span class="se">\</span> +<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a> --workers <span class="m">8</span> <span class="se">\</span> +<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> --max-body-size <span class="m">1000000</span> <span class="se">\</span> +<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> --url <span class="s2">"/files"</span> <span class="se">\</span> +<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> --log-level <span class="s2">"INFO"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_SERVER_HOST</span><span class="o">=</span><span class="s2">"0.0.0.0"</span> +<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_SERVER_PORT</span><span class="o">=</span><span class="s2">"1081"</span> +<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="nb">export</span> <span class="nv">RUSTUS_SERVER_WORKERS</span><span class="o">=</span><span class="s2">"8"</span> +<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="nb">export</span> <span class="nv">RUSTUS_MAX_BODY_SIZE</span><span class="o">=</span><span class="s2">"1000000"</span> +<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="nb">export</span> <span class="nv">RUSTUS_URL</span><span class="o">=</span><span class="s2">"/files"</span> +<a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="nb">export</span> <span class="nv">RUSTUS_LOG_LEVEL</span><span class="o">=</span><span class="s2">"INFO"</span> +<a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a> +<a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a>rustus +</code></pre></div> +</div> +</div> +</div> <h2 id="configuring-data-storage">Configuring data storage</h2> +<div class="admonition info"> +<p class="admonition-title">Info</p> +<p>Currently only file storage is available, +so if you pass to <code>--storage</code> parameter other than <code>file-storage</code> you will get an error.</p> +<p>Also you <strong>can not</strong> pass <code>--force-fsync</code> through environment variables.</p> +</div> +<p><code>--storage</code> is a type of data storage to be used.</p> +<p><code>--data-dir</code> is a path to the directory where all files are stored.</p> +<p><code>--dir-structure</code> is a pattern of a directory structure inside data dir. +You can use variables within the pattern.</p> +<p>Available variables:</p> +<ul> +<li><code>{year}</code> - current year;</li> +<li><code>{month}</code> - current month number from 1 to 12;</li> +<li><code>{day}</code> - current day number from 1 to 31;</li> +<li><code>{hour}</code> - hour number from 0 to 23;</li> +<li><code>{minute}</code> - minute number from 0 to 59;</li> +<li><code>{env[ENV_NAME]}</code> - environment variable where <code>ENV_NAME</code> is name of your variable.</li> +</ul> +<div class="admonition note"> +<p class="admonition-title">Note</p> +<p>All environment variables are saved in memory during rustus startup. +So you cannot change variable dynamically. Even if you change env used in +structure pattern it won't change.</p> +</div> +<p>For example if you use <code>{env[HOSTNAME]}/{year}/{month}/{day}</code> as your dir-structure, rustus stores files like:</p> +<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>$ tree data +<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>data +<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>└── rtus-68cb5b8746-5mgw9 +<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a> └── <span class="m">2022</span> +<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a> └── <span class="m">1</span> +<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a> └── <span class="m">8</span> +<a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a> ├── 0bd911d4054d41c6a3ad54be67ee3e66 +<a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a> └── 5bc9c62384494c439e2a064b82a39cc6 +</code></pre></div> +<div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">CLI</label><label for="__tabbed_2_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>rustus --force-fsync <span class="se">\</span> +<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a> --storage <span class="s2">"file-storage"</span> <span class="se">\</span> +<a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a> --data-dir <span class="s2">"./data/"</span> <span class="se">\</span> +<a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a> --dir-structure <span class="s2">"{year}/{month}/{day}"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_STORAGE</span><span class="o">=</span><span class="s2">"file-storage"</span> +<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_DATA_DIR</span><span class="o">=</span><span class="s2">"./data/"</span> +<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="nb">export</span> <span class="nv">RUSTUS_DIR_STRUCTURE</span><span class="o">=</span><span class="s2">"{year}/{month}/{day}"</span> +<a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a> +<a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a>rustus --force-fsync +</code></pre></div> +</div> +</div> +</div> <h2 id="configuring-info-storage">Configuring info storage</h2> -<h2 id="configuring-hooks-storage">Configuring hooks storage</h2> +<p>Info storages are used to store information +about file uploads. These storages <strong>must</strong> be persistent, +because every time chunk is uploaded rustus updates information +about upload. And when someone wants to download file, information +about it requested from storage to get actual path of an upload.</p> +<p>Available info storages:</p> +<ul> +<li><code>file-info-storage</code> - stores information in files on disk;</li> +<li><code>redis-info-storage</code> - information is stored in redis;</li> +<li><code>db-info-storage</code> - information is stored in database;</li> +</ul> +<h3 id="file-info-storage">File info storage</h3> +<p>file info storage stores information in files on disk. +It's default info storage. Every download has it's own associated file. +All .info files stored in flat structure so it's the least preferable way of +storing information about uploads. But if you don't plan to have many uploads, it may fit well.</p> +<p><code>--info-dir</code> - directory where all .info file will be stored (default is <code>./data</code>).</p> +<div class="tabbed-set tabbed-alternate" data-tabs="3:2"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">CLI</label><label for="__tabbed_3_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a>rustus --force-fsync <span class="se">\</span> +<a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> --storage <span class="s2">"file-info-storage"</span> <span class="se">\</span> +<a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a> --info-dir <span class="s2">"./data"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_STORAGE</span><span class="o">=</span><span class="s2">"file-info-storage"</span> +<a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_DIR</span><span class="o">=</span><span class="s2">"./data"</span> +<a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> +<a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<h3 id="redis-info-storage">Redis info storage</h3> +<p>Redis db is a good way to store information.</p> +<div class="admonition note"> +<p class="admonition-title">Note</p> +<p>If you're using redis as a cluster +you must provide connection string for master redis server. +Since rustus need to have latest information and it writes a lot.</p> +</div> +<p><code>--info-db-dsn</code> - connection string for your redis database. +It's required if redis-info-storage is chosen.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">CLI</label><label for="__tabbed_4_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>rustus --force-fsync <span class="se">\</span> +<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a> --storage <span class="s2">"redis-info-storage"</span> <span class="se">\</span> +<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a> --info-db-dsn <span class="s2">"redis://localhost/0"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_STORAGE</span><span class="o">=</span><span class="s2">"redis-info-storage"</span> +<a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_DB_DSN</span><span class="o">=</span><span class="s2">"redis://localhost"</span> +<a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a> +<a id="__codelineno-8-4" name="__codelineno-8-4" href="#__codelineno-8-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<h3 id="db-info-storage">DB info storage</h3> +<p>Rustus can store information about upload in database.</p> +<p>It's a good and reliable option. But rustus can't work +with replicas since it requires most recent information +about uploads.</p> +<p>You can use <code>postgresql</code>, <code>mysql</code> or even <code>sqlite</code> schemas to +connect to database.</p> +<p><code>--info-db-dsn</code> - connection string for your database.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="5:2"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">CLI</label><label for="__tabbed_5_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a>rustus --force-fsync <span class="se">\</span> +<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a> --storage <span class="s2">"db-info-storage"</span> <span class="se">\</span> +<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a> --info-db-dsn <span class="s2">"postgresql://user:password@localhost/db"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_STORAGE</span><span class="o">=</span><span class="s2">"redis-info-storage"</span> +<a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_INFO_DB_DSN</span><span class="o">=</span><span class="s2">"postgresql://user:password@localhost/db"</span> +<a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a> +<a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> <h2 id="configuring-tus">Configuring TUS</h2> +<p>Since tus protocol offers extensibility you can turn off some protocol extensions.</p> +<p>Available extensions:</p> +<ul> +<li><code>getting</code> - rustus specific extension that helps you download uploaded files with get request;</li> +<li><code>creation</code> - helps you to create files (It's like a core feature you better have this enabled);</li> +<li><code>termination</code> - allows you to delete uploads with DELETE request;</li> +<li><code>creation-with-upload</code> - allows you to write first bytes of a file while creating;</li> +<li><code>creation-defer-length</code> - allows you to create file without specifying file length;</li> +<li><code>concatenation</code> - allows you to concatenate finished partial uploads.</li> +<li><code>checksum</code> - allows you to verify checksum of every batch.</li> +</ul> +<p>You can read more about extensions on <a href="https://tus.io/protocols/resumable-upload.html#protocol-extensions">official web-site</a>.</p> +<p><code>--tus-extensions</code> - a list of enabled extensions.</p> +<p>By default all extensions are enabled.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="6:2"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">CLI</label><label for="__tabbed_6_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a>rustus --tus-extensions <span class="s2">"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_TUS_EXTENSIONS</span><span class="o">=</span><span class="s2">"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum"</span> +<a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a> +<a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a>rustus +</code></pre></div> +</div> +</div> +</div> </article> diff --git a/deploy/index.html b/deploy/index.html index 7117b4b55d0af6cb5dcbac011a0a794bf0913405..028bd45e294b9dce1cb8f111e30a1de1153ac050 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -360,7 +360,7 @@ <li class="md-nav__item"> <a href="../hooks/" class="md-nav__link"> - Hooks + Setting up hooks </a> </li> @@ -572,6 +572,16 @@ as you specified for data storage.</p> <li><a href="https://github.com/bitnami/charts/tree/master/bitnami/postgresql">Repo</a> for postgresql.</li> </ul> <p>In production you may ignore these subcharts to deploy your own redis or mysql or postgresql.</p> +<p>After you done editing <code>values.yml</code> you can apply the configuration like this:</p> +<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>helm upgrade <span class="se">\</span> +<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>--install <span class="se">\ </span><span class="c1"># Install chart if it's not installed</span> +<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a>--namespace rustus <span class="se">\ </span><span class="c1"># k8s namespace</span> +<a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a>--create-namespace <span class="se">\ </span><span class="c1"># Creates namespace if it doesn't exist</span> +<a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a>--atomic <span class="se">\ </span><span class="c1"># Ensures that everything is deployed correctly</span> +<a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a>--values <span class="s2">"values.yml"</span> <span class="se">\ </span><span class="c1"># Link to values.yml file</span> +<a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a><span class="s2">"rustus"</span> <span class="se">\ </span><span class="c1"># name of a release</span> +<a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="s2">"rustus/rustus"</span> <span class="c1"># Name of the chart</span> +</code></pre></div> </article> @@ -601,13 +611,13 @@ as you specified for data storage.</p> - <a href="../hooks/" class="md-footer__link md-footer__link--next" aria-label="Next: Hooks" rel="next"> + <a href="../hooks/" class="md-footer__link md-footer__link--next" aria-label="Next: Setting up hooks" rel="next"> <div class="md-footer__title"> <div class="md-ellipsis"> <span class="md-footer__direction"> Next </span> - Hooks + Setting up hooks </div> </div> <div class="md-footer__button md-icon"> diff --git a/hooks/index.html b/hooks/index.html index 29f7e2fda58d18d2e8233fc10b5b7407a73d5dad..fde84ced62d0a737da6546d4c9d920e66f8a9174 100644 --- a/hooks/index.html +++ b/hooks/index.html @@ -15,7 +15,7 @@ - <title>Hooks - rustus</title> + <title>Setting up hooks - rustus</title> @@ -64,6 +64,11 @@ <label class="md-overlay" for="__drawer"></label> <div data-md-component="skip"> + + <a href="#fomat" class="md-skip"> + Skip to content + </a> + </div> <div data-md-component="announce"> @@ -92,7 +97,7 @@ <div class="md-header__topic" data-md-component="header-topic"> <span class="md-ellipsis"> - Hooks + Setting up hooks </span> </div> @@ -277,10 +282,86 @@ + <label class="md-nav__link md-nav__link--active" for="__toc"> + Setting up hooks + <span class="md-nav__icon md-icon"></span> + </label> + <a href="./" class="md-nav__link md-nav__link--active"> - Hooks + Setting up hooks </a> + + +<nav class="md-nav md-nav--secondary" aria-label="Table of contents"> + + + + + <label class="md-nav__title" for="__toc"> + <span class="md-nav__icon md-icon"></span> + Table of contents + </label> + <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> + + <li class="md-nav__item"> + <a href="#fomat" class="md-nav__link"> + Fomat + </a> + +</li> + + <li class="md-nav__item"> + <a href="#hook-types" class="md-nav__link"> + Hook types + </a> + + <nav class="md-nav" aria-label="Hook types"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#file-hooks" class="md-nav__link"> + File hooks + </a> + +</li> + + <li class="md-nav__item"> + <a href="#http-hooks" class="md-nav__link"> + Http Hooks + </a> + + <nav class="md-nav" aria-label="Http Hooks"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#example-application" class="md-nav__link"> + Example application + </a> + +</li> + + </ul> + </nav> + +</li> + + <li class="md-nav__item"> + <a href="#amqp-hooks" class="md-nav__link"> + AMQP hooks + </a> + +</li> + + </ul> + </nav> + +</li> + + </ul> + +</nav> + </li> @@ -292,6 +373,84 @@ </div> + + <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > + <div class="md-sidebar__scrollwrap"> + <div class="md-sidebar__inner"> + + +<nav class="md-nav md-nav--secondary" aria-label="Table of contents"> + + + + + <label class="md-nav__title" for="__toc"> + <span class="md-nav__icon md-icon"></span> + Table of contents + </label> + <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> + + <li class="md-nav__item"> + <a href="#fomat" class="md-nav__link"> + Fomat + </a> + +</li> + + <li class="md-nav__item"> + <a href="#hook-types" class="md-nav__link"> + Hook types + </a> + + <nav class="md-nav" aria-label="Hook types"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#file-hooks" class="md-nav__link"> + File hooks + </a> + +</li> + + <li class="md-nav__item"> + <a href="#http-hooks" class="md-nav__link"> + Http Hooks + </a> + + <nav class="md-nav" aria-label="Http Hooks"> + <ul class="md-nav__list"> + + <li class="md-nav__item"> + <a href="#example-application" class="md-nav__link"> + Example application + </a> + +</li> + + </ul> + </nav> + +</li> + + <li class="md-nav__item"> + <a href="#amqp-hooks" class="md-nav__link"> + AMQP hooks + </a> + +</li> + + </ul> + </nav> + +</li> + + </ul> + +</nav> + </div> + </div> + </div> + <div class="md-content" data-md-component="content"> <article class="md-content__inner md-typeset"> @@ -299,9 +458,303 @@ - <h1>Hooks</h1> - + <h1>Setting up hooks</h1> +<p>Rustus can notify about uploads using hooks. +This is useful when you integrate rustus in your architecture. +Apps can keep track of every upload using this feature.</p> +<p>Rustus has different event types for different moments of an upload's lifecycle.</p> +<ul> +<li><code>pre-create</code> - This hook means that someone wants to create an upload;</li> +<li><code>post-create</code> - someone successfully created an upload;</li> +<li><code>post-receive</code> - someone uploaded a new part of an upload;</li> +<li><code>post-terminate</code> - someone deleted upload;</li> +<li><code>post-finish</code> - someone finished uploading file.</li> +</ul> +<div class="admonition note"> +<p class="admonition-title">Note</p> +<p>Pre-create hook is very important. +If at least one of hooks fails, upload is canceled.</p> +<p>But AMQP hooks won't cancel the upload, since it's non blocking type of hooks.</p> +</div> +<p>You can disable some hooks by using <code>--hooks</code> parameter.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">CLI</label><label for="__tabbed_1_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>rustus --hooks <span class="s2">"pre-create,post-create,post-receive,post-terminate,post-finish"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS</span><span class="o">=</span><span class="s2">"pre-create,post-create,post-receive,post-terminate,post-finish"</span> +<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a> +<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<h2 id="fomat">Fomat</h2> +<p>Information about every hook using <code>JSON</code> format. +Format can be configured using <code>--hooks-format</code> parameter or <code>RUSTUS_HOOKS_FORMAT</code> environment variable.</p> +<p>Available formats:</p> +<ul> +<li>default</li> +<li>tusd</li> +</ul> +<div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">default</label><label for="__tabbed_2_2">tusd</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="p">{</span><span class="w"></span> +<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="w"> </span><span class="nt">"upload"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="w"> </span><span class="nt">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="w"> </span><span class="nt">"offset"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="w"> </span><span class="nt">"length"</span><span class="p">:</span><span class="w"> </span><span class="mi">39729945</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a><span class="w"> </span><span class="nt">"path"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a><span class="w"> </span><span class="nt">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="mi">1641620821</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a><span class="w"> </span><span class="nt">"deferred_size"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-9" name="__codelineno-2-9" href="#__codelineno-2-9"></a><span class="w"> </span><span class="nt">"metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-2-10" name="__codelineno-2-10" href="#__codelineno-2-10"></a><span class="w"> </span><span class="nt">"filename"</span><span class="p">:</span><span class="w"> </span><span class="s2">"38MB_video.mp4"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-11" name="__codelineno-2-11" href="#__codelineno-2-11"></a><span class="w"> </span><span class="nt">"meme"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehe2"</span><span class="w"></span> +<a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a><span class="w"> </span><span class="p">},</span><span class="w"></span> +<a id="__codelineno-2-14" name="__codelineno-2-14" href="#__codelineno-2-14"></a><span class="w"> </span><span class="nt">"request"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-2-15" name="__codelineno-2-15" href="#__codelineno-2-15"></a><span class="w"> </span><span class="nt">"URI"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/files"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-16" name="__codelineno-2-16" href="#__codelineno-2-16"></a><span class="w"> </span><span class="nt">"method"</span><span class="p">:</span><span class="w"> </span><span class="s2">"POST"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-17" name="__codelineno-2-17" href="#__codelineno-2-17"></a><span class="w"> </span><span class="nt">"remote_addr"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-18" name="__codelineno-2-18" href="#__codelineno-2-18"></a><span class="w"> </span><span class="nt">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-2-19" name="__codelineno-2-19" href="#__codelineno-2-19"></a><span class="w"> </span><span class="nt">"accept-encoding"</span><span class="p">:</span><span class="w"> </span><span class="s2">"gzip, deflate"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-20" name="__codelineno-2-20" href="#__codelineno-2-20"></a><span class="w"> </span><span class="nt">"connection"</span><span class="p">:</span><span class="w"> </span><span class="s2">"keep-alive"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-21" name="__codelineno-2-21" href="#__codelineno-2-21"></a><span class="w"> </span><span class="nt">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">"localhost:1081"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-22" name="__codelineno-2-22" href="#__codelineno-2-22"></a><span class="w"> </span><span class="nt">"upload-metadata"</span><span class="p">:</span><span class="w"> </span><span class="s2">"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ="</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-23" name="__codelineno-2-23" href="#__codelineno-2-23"></a><span class="w"> </span><span class="nt">"tus-resumable"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-24" name="__codelineno-2-24" href="#__codelineno-2-24"></a><span class="w"> </span><span class="nt">"content-length"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-25" name="__codelineno-2-25" href="#__codelineno-2-25"></a><span class="w"> </span><span class="nt">"upload-length"</span><span class="p">:</span><span class="w"> </span><span class="s2">"39729945"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-26" name="__codelineno-2-26" href="#__codelineno-2-26"></a><span class="w"> </span><span class="nt">"user-agent"</span><span class="p">:</span><span class="w"> </span><span class="s2">"python-requests/2.26.0"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-2-27" name="__codelineno-2-27" href="#__codelineno-2-27"></a><span class="w"> </span><span class="nt">"accept"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*/*"</span><span class="w"></span> +<a id="__codelineno-2-28" name="__codelineno-2-28" href="#__codelineno-2-28"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-2-29" name="__codelineno-2-29" href="#__codelineno-2-29"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-2-30" name="__codelineno-2-30" href="#__codelineno-2-30"></a><span class="p">}</span><span class="w"></span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="w"> </span><span class="nt">"Upload"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="w"> </span><span class="nt">"ID"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="w"> </span><span class="nt">"Offset"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a><span class="w"> </span><span class="nt">"Size"</span><span class="p">:</span><span class="w"> </span><span class="mi">39729945</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a><span class="w"> </span><span class="nt">"IsFinal"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a><span class="w"> </span><span class="nt">"IsPartial"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a><span class="w"> </span><span class="nt">"PartialUploads"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a><span class="w"> </span><span class="nt">"SizeIsDeferred"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a><span class="w"> </span><span class="nt">"Metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a><span class="w"> </span><span class="nt">"filename"</span><span class="p">:</span><span class="w"> </span><span class="s2">"38MB_video.mp4"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a><span class="w"> </span><span class="nt">"meme"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehe2"</span><span class="w"></span> +<a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a><span class="w"> </span><span class="p">},</span><span class="w"></span> +<a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a><span class="w"> </span><span class="nt">"Storage"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a><span class="w"> </span><span class="nt">"Type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"filestore"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a><span class="w"> </span><span class="nt">"Path"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"></span> +<a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-3-18" name="__codelineno-3-18" href="#__codelineno-3-18"></a><span class="w"> </span><span class="p">},</span><span class="w"></span> +<a id="__codelineno-3-19" name="__codelineno-3-19" href="#__codelineno-3-19"></a><span class="w"> </span><span class="nt">"HTTPRequest"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-20" name="__codelineno-3-20" href="#__codelineno-3-20"></a><span class="w"> </span><span class="nt">"URI"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/files"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-21" name="__codelineno-3-21" href="#__codelineno-3-21"></a><span class="w"> </span><span class="nt">"Method"</span><span class="p">:</span><span class="w"> </span><span class="s2">"POST"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-22" name="__codelineno-3-22" href="#__codelineno-3-22"></a><span class="w"> </span><span class="nt">"RemoteAddr"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w"></span> +<a id="__codelineno-3-23" name="__codelineno-3-23" href="#__codelineno-3-23"></a><span class="w"> </span><span class="nt">"Header"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span> +<a id="__codelineno-3-24" name="__codelineno-3-24" href="#__codelineno-3-24"></a><span class="w"> </span><span class="nt">"host"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-25" name="__codelineno-3-25" href="#__codelineno-3-25"></a><span class="w"> </span><span class="s2">"localhost:1081"</span><span class="w"></span> +<a id="__codelineno-3-26" name="__codelineno-3-26" href="#__codelineno-3-26"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-27" name="__codelineno-3-27" href="#__codelineno-3-27"></a><span class="w"> </span><span class="nt">"user-agent"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-28" name="__codelineno-3-28" href="#__codelineno-3-28"></a><span class="w"> </span><span class="s2">"python-requests/2.26.0"</span><span class="w"></span> +<a id="__codelineno-3-29" name="__codelineno-3-29" href="#__codelineno-3-29"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-30" name="__codelineno-3-30" href="#__codelineno-3-30"></a><span class="w"> </span><span class="nt">"accept"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-31" name="__codelineno-3-31" href="#__codelineno-3-31"></a><span class="w"> </span><span class="s2">"*/*"</span><span class="w"></span> +<a id="__codelineno-3-32" name="__codelineno-3-32" href="#__codelineno-3-32"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-33" name="__codelineno-3-33" href="#__codelineno-3-33"></a><span class="w"> </span><span class="nt">"content-length"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-34" name="__codelineno-3-34" href="#__codelineno-3-34"></a><span class="w"> </span><span class="s2">"0"</span><span class="w"></span> +<a id="__codelineno-3-35" name="__codelineno-3-35" href="#__codelineno-3-35"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-36" name="__codelineno-3-36" href="#__codelineno-3-36"></a><span class="w"> </span><span class="nt">"upload-metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-37" name="__codelineno-3-37" href="#__codelineno-3-37"></a><span class="w"> </span><span class="s2">"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ="</span><span class="w"></span> +<a id="__codelineno-3-38" name="__codelineno-3-38" href="#__codelineno-3-38"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-39" name="__codelineno-3-39" href="#__codelineno-3-39"></a><span class="w"> </span><span class="nt">"connection"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-40" name="__codelineno-3-40" href="#__codelineno-3-40"></a><span class="w"> </span><span class="s2">"keep-alive"</span><span class="w"></span> +<a id="__codelineno-3-41" name="__codelineno-3-41" href="#__codelineno-3-41"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-42" name="__codelineno-3-42" href="#__codelineno-3-42"></a><span class="w"> </span><span class="nt">"tus-resumable"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-43" name="__codelineno-3-43" href="#__codelineno-3-43"></a><span class="w"> </span><span class="s2">"1.0.0"</span><span class="w"></span> +<a id="__codelineno-3-44" name="__codelineno-3-44" href="#__codelineno-3-44"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-45" name="__codelineno-3-45" href="#__codelineno-3-45"></a><span class="w"> </span><span class="nt">"upload-length"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-46" name="__codelineno-3-46" href="#__codelineno-3-46"></a><span class="w"> </span><span class="s2">"39729945"</span><span class="w"></span> +<a id="__codelineno-3-47" name="__codelineno-3-47" href="#__codelineno-3-47"></a><span class="w"> </span><span class="p">],</span><span class="w"></span> +<a id="__codelineno-3-48" name="__codelineno-3-48" href="#__codelineno-3-48"></a><span class="w"> </span><span class="nt">"accept-encoding"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span> +<a id="__codelineno-3-49" name="__codelineno-3-49" href="#__codelineno-3-49"></a><span class="w"> </span><span class="s2">"gzip, deflate"</span><span class="w"></span> +<a id="__codelineno-3-50" name="__codelineno-3-50" href="#__codelineno-3-50"></a><span class="w"> </span><span class="p">]</span><span class="w"></span> +<a id="__codelineno-3-51" name="__codelineno-3-51" href="#__codelineno-3-51"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-3-52" name="__codelineno-3-52" href="#__codelineno-3-52"></a><span class="w"> </span><span class="p">}</span><span class="w"></span> +<a id="__codelineno-3-53" name="__codelineno-3-53" href="#__codelineno-3-53"></a><span class="p">}</span><span class="w"></span> +</code></pre></div> +</div> +</div> +</div> +<h2 id="hook-types">Hook types</h2> +<p>Rustus offers multiple types of Hooks. We'll take a brief look on each type.</p> +<h3 id="file-hooks">File hooks</h3> +<p>Rustus can work with two types of file hooks.</p> +<ul> +<li>Single file hook</li> +<li>Hooks directory</li> +</ul> +<p>The main difference is that in case if use single file hook, hook name is passed as a command line argument +to an executable file, but if you use hooks directory then hook name is used to determine a file to call. Let's take a look at the examples.</p> +<p>Parameters: +* <code>--hooks-file</code> - path to an executable file; +* <code>--hooks-dir</code> - path to a directory with executable files.</p> +<div class="highlight"><span class="filename">single_file_hook.sh</span><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="ch">#!/bin/bash</span> +<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a> +<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="c1"># Hook name would be "pre-create", "post-create" and so on.</span> +<a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="nv">HOOK_NAME</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> +<a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="nv">HOOK_INFO</span><span class="o">=</span><span class="s2">"</span><span class="nv">$2</span><span class="s2">"</span> +<a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="nv">MEME</span><span class="o">=</span><span class="s2">"</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$HOOK_INFO</span><span class="s2">"</span> <span class="p">|</span> jq <span class="s2">".upload .metadata .meme"</span> <span class="p">|</span> xargs<span class="k">)</span><span class="s2">"</span> +<a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a> +<a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a><span class="c1"># Here we check if name in metadata is equal to pepe.</span> +<a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a><span class="k">if</span> <span class="o">[[</span> <span class="nv">$MEME</span> <span class="o">=</span> <span class="s2">"pepe"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span> +<a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a> <span class="nb">echo</span> <span class="s2">"This meme isn't allowed"</span> <span class="m">1</span>><span class="p">&</span><span class="m">2</span><span class="p">;</span> +<a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a> <span class="nb">exit</span> <span class="m">1</span> +<a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a><span class="k">fi</span> +</code></pre></div> +<p>As you can see it uses first CLI parameter as a hook name and all hook data is received from the second one. +Let's make it executable and make rustus use this hook.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="3:2"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">CLI</label><label for="__tabbed_3_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a>chmod +x <span class="s2">"hooks/single_file_hook.sh"</span> +<a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> +<a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a>rustus --hooks-file <span class="s2">"hooks/single_file_hook.sh"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>chmod +x <span class="s2">"hooks/single_file_hook.sh"</span> +<a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_FILE</span><span class="o">=</span><span class="s2">"hooks/single_file_hook.sh"</span> +<a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> +<a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<p>If you would like to use directory hooks you must create directory with the following structure:</p> +<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>hooks +<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>├── post-create +<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a>├── post-finish +<a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a>├── post-receive +<a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a>├── post-terminate +<a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a>└── pre-create +</code></pre></div> +<div class="admonition warning"> +<p class="admonition-title">Warning</p> +<p>If some hook file isn't found, rustus throws an error. +In case with <code>pre-create</code> hook it can be fatal.</p> +</div> +<h3 id="http-hooks">Http Hooks</h3> +<p>Http hooks use HTTP to send <code>POST</code> requests to some endpoint.</p> +<p>Configuration parameters:</p> +<ul> +<li><code>--hooks-http-proxy-headers</code> - list of headers to proxy (separated by commas) to listener's endpoint;</li> +<li><code>--hooks-http-urls</code> - list of absolute urls to send request to (separated by commas).</li> +</ul> +<div class="admonition note"> +<p class="admonition-title">Note</p> +<p>Hook names are passed as header called <code>Hook-Name</code>.</p> +</div> +<div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">CLI</label><label for="__tabbed_4_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a>rustus --hooks-http-urls <span class="s2">"https://httpbin.org/post"</span> <span class="se">\</span> +<a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a> --hooks-http-proxy-headers <span class="s2">"Authorization"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_HTTP_URLS</span><span class="o">=</span><span class="s2">"https://httpbin.org/post"</span> +<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_HTTP_PROXY_HEADERS</span><span class="o">=</span><span class="s2">"Authorization"</span> +<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a> +<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<h4 id="example-application">Example application</h4> +<p>To be more verbose let's create simple web server that +handles uploads using <a href="https://fastapi.tiangolo.com/">FastAPI</a>.</p> +<p>At first we need to install dependencies using pip.</p> +<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a>pip install fastapi uvicorn +</code></pre></div> +<div class="highlight"><span class="filename">server.py</span><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span><span class="p">,</span> <span class="n">Header</span><span class="p">,</span> <span class="n">HTTPException</span> +<a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span> +<a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a> +<a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span> +<a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a> +<a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a> +<a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/hooks"</span><span class="p">)</span> +<a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a><span class="k">def</span> <span class="nf">hook</span><span class="p">(</span> +<a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a> <span class="n">authorization</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="kc">None</span><span class="p">),</span> +<a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a> <span class="n">hook_name</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="n">Header</span><span class="p">(</span><span class="kc">None</span><span class="p">),</span> +<a id="__codelineno-11-11" name="__codelineno-11-11" href="#__codelineno-11-11"></a><span class="p">):</span> +<a id="__codelineno-11-12" name="__codelineno-11-12" href="#__codelineno-11-12"></a> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Received: </span><span class="si">{</span><span class="n">hook_name</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> +<a id="__codelineno-11-13" name="__codelineno-11-13" href="#__codelineno-11-13"></a> <span class="k">if</span> <span class="n">authorization</span> <span class="o">!=</span> <span class="s2">"Bearer jwt"</span><span class="p">:</span> +<a id="__codelineno-11-14" name="__codelineno-11-14" href="#__codelineno-11-14"></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="mi">401</span><span class="p">)</span> +<a id="__codelineno-11-15" name="__codelineno-11-15" href="#__codelineno-11-15"></a> <span class="k">return</span> <span class="kc">None</span> +</code></pre></div> +<p>Now we can run this server using uvicorn.</p> +<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a>uvicorn server:app --port <span class="m">8080</span> +</code></pre></div> +<p>Let's configure rustus to use this server as a hook reciever.</p> +<div class="tabbed-set tabbed-alternate" data-tabs="5:2"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">CLI</label><label for="__tabbed_5_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a>rustus --hooks-http-urls <span class="s2">"http://localhost:8000/hooks"</span> <span class="se">\</span> +<a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a> --hooks-http-proxy-headers <span class="s2">"Authorization"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_HTTP_URLS</span><span class="o">=</span><span class="s2">"http://localhost:8000/hooks"</span> +<a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_HTTP_PROXY_HEADERS</span><span class="o">=</span><span class="s2">"Authorization"</span> +<a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a> +<a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a>rustus +</code></pre></div> +</div> +</div> +</div> +<p>That's it.</p> +<h3 id="amqp-hooks">AMQP hooks</h3> +<p>AMQP hooks are used to store information about uploads using RabbitMQ.</p> +<p>Configuration parameters:</p> +<ul> +<li><code>--hooks-amqp-url</code> - connection string to RabbitMQ;</li> +<li><code>--hooks-amqp-queues-prefix</code> - prefix for queues for every event queue;</li> +<li><code>--hooks-amqp-exchange</code> - name of exchange to use.</li> +</ul> +<p>This hook will send every message in an exchange with routing keys +like queues names.</p> +<p>Queues are named like <code>{prefix}.{event type}</code>. Eg <code>rustus.pre-create</code> and so on.</p> +<div class="admonition warning"> +<p class="admonition-title">Warning</p> +<p>Since we can't really track message delivery and responses +Rustus doesn't stop in any case.</p> +</div> +<div class="tabbed-set tabbed-alternate" data-tabs="6:2"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">CLI</label><label for="__tabbed_6_2">ENV</label></div> +<div class="tabbed-content"> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a>rustus --hooks-amqp-url <span class="s2">"amqp://guest:guest@localhost:5672"</span> <span class="se">\</span> +<a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a> --hooks-amqp-queues-prefix <span class="s2">"rustus_queue"</span> <span class="se">\</span> +<a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a> --hooks-amqp-exchange <span class="s2">"rustus"</span> +</code></pre></div> +</div> +<div class="tabbed-block"> +<div class="highlight"><pre><span></span><code><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_AMQP_URL</span><span class="o">=</span><span class="s2">"amqp://guest:guest@localhost:5672"</span> +<a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_AMQP_QUEUES_PREFIX</span><span class="o">=</span><span class="s2">"rustus_queue"</span> +<a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a><span class="nb">export</span> <span class="nv">RUSTUS_HOOKS_AMQP_EXCHANGE</span><span class="o">=</span><span class="s2">"rustus"</span> +<a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a> +<a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a>rustus +</code></pre></div> +</div> +</div> +</div> </article> diff --git a/index.html b/index.html index fb1df3956b2ebbddb4ca7f95be6bf47b71909ca6..56d620af218c9640d9a2e35f9fc1896ae08acf00 100644 --- a/index.html +++ b/index.html @@ -349,7 +349,7 @@ <li class="md-nav__item"> <a href="hooks/" class="md-nav__link"> - Hooks + Setting up hooks </a> </li> diff --git a/search/search_index.json b/search/search_index.json index b43ffcb4be0333c828ecefb558afa56bc4563d76..f8db5d12216747ef369b67a2e84c2f386f245c4e 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Rustus is a TUS protocol implementation that helps you handle file uploads. This project has many features that makes it easy to integrate in your service. Installation You can install rustus by 4 different ways. From source To build it from source rust must be installed. Preferred version is 1.59.0. git clone https://github.com/s3rius/rustus.git cd rustus cargo install --path . --features = all Also you can speedup build by disabling some features. Available features: amqp_notifier - adds amqp protocol support for notifying about upload status; db_info_storage - adds support for storing information about upload in different databases (Postgres, MySQL, SQLite); http_notifier - adds support for notifying about upload status via http protocol; redis_info_storage - adds support for storing information about upload in redis database; hashers - adds support for checksum verification; all - enables all rustus features. All precompiled binaries have all features enabled. With cargo If you have cargo installed maybe it would be easier to install it directly from crates.io. cargo install rustus --features = all Binaries All precompiled binaries available on github releases page. You can download binaries from here , unpack it and run. ./rustus Make sure that you download version for your cpu and os. Using docker One of the most simple ways to run rustus is docker. Rustus has two containers for each version. 1. debian based image 2. alpine based image Alpine based images are more lightweight than debian To run rustus you just need to run this command docker run --rm -p \"1081:1081\" -d s3rius/rustus --log-level \"DEBUG\"","title":"Welcome page"},{"location":"#installation","text":"You can install rustus by 4 different ways.","title":"Installation"},{"location":"#from-source","text":"To build it from source rust must be installed. Preferred version is 1.59.0. git clone https://github.com/s3rius/rustus.git cd rustus cargo install --path . --features = all Also you can speedup build by disabling some features. Available features: amqp_notifier - adds amqp protocol support for notifying about upload status; db_info_storage - adds support for storing information about upload in different databases (Postgres, MySQL, SQLite); http_notifier - adds support for notifying about upload status via http protocol; redis_info_storage - adds support for storing information about upload in redis database; hashers - adds support for checksum verification; all - enables all rustus features. All precompiled binaries have all features enabled.","title":"From source"},{"location":"#with-cargo","text":"If you have cargo installed maybe it would be easier to install it directly from crates.io. cargo install rustus --features = all","title":"With cargo"},{"location":"#binaries","text":"All precompiled binaries available on github releases page. You can download binaries from here , unpack it and run. ./rustus Make sure that you download version for your cpu and os.","title":"Binaries"},{"location":"#using-docker","text":"One of the most simple ways to run rustus is docker. Rustus has two containers for each version. 1. debian based image 2. alpine based image Alpine based images are more lightweight than debian To run rustus you just need to run this command docker run --rm -p \"1081:1081\" -d s3rius/rustus --log-level \"DEBUG\"","title":"Using docker"},{"location":"configuration/","text":"Rustus is highly configurable you can configure rustus with CLI or you can use environment variables. Info Some options can be passed only through as CLI parameters Configuring data storage Configuring info storage Configuring hooks storage Configuring TUS","title":"Configuration"},{"location":"configuration/#configuring-data-storage","text":"","title":"Configuring data storage"},{"location":"configuration/#configuring-info-storage","text":"","title":"Configuring info storage"},{"location":"configuration/#configuring-hooks-storage","text":"","title":"Configuring hooks storage"},{"location":"configuration/#configuring-tus","text":"","title":"Configuring TUS"},{"location":"deploy/","text":"Deployment Deploying an application is always a challenge. Rustus was made to make deployment as easy as possible. Since this application works with files so if you want to scale number of rustus instances you have to somehow make different rustus instances to work with the same data or info directory. Docker compose docker-compose.yml # This is super simple configuration version : \"3.7\" services : rustus : image : s3rius/rustus volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data volumes : rustus_data_volume : After running docker compose up you will see rustus startup logs. If you want to deploy multiple rustus instances you can simply use config as this one: docker-compose.yml version : \"3.7\" services : proxy : image : jwilder/nginx-proxy:alpine container_name : proxy # Actual proxy ports. ports : - 8080:80 volumes : # This thing helps to locate containers # within this composition to generate nginx config. - /var/run/docker.sock:/tmp/docker.sock:ro rustus : image : s3rius/rustus ports : # Ports definition # To generate correct nginx config. - 1081 volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data environment : # Idk why but without this variable # load balancing with jwilder/nginx-proxy doesn't work. VIRTUAL_HOST : localhost volumes : rustus_data_volume : # This is named volume The main idea is that traffic that comes into nginx-proxy is routed in one of multiple rustus containers. Here I used jwilder/nginx-proxy but you can use other reverse-proxies such as raw nginx proxy or traefik . Now you can run multiple rustus instnaces like this. docker compose up --scale rustus = 3 After that you can upload files to http://localhost:8080/files Kubernetes Configuration for kubernetes is almost the same as docker. But the most preferable way is an official helm chart. Load balancing is done by kubernetes so you just have to create volume to mount data and info directories. Helm You can install rustus by running this set of commands: helm repo add \"rustus\" \"https://s3rius.github.io/rustus/helm_releases\" helm repo update helm repo install \"rustus/rustus\" Configuration But of course it can be configured. # You can download basic configuration by running helm show values \"rustus/rustus\" > values.yml By editing values.yml you can configure many different options. Warning For production use you must provide and mount PersistentVolumeClaim in order to scale rustus. This helm chart has only one replica by default. Persistence You can add pvc mount by editing persistence section. The most preferable way is to create PersistentVolume and PersistentVolumeClaim before installing this chart. After you created claim you can apply this values file to mount your claim into rustus. values.yml persistence : enabled : true existingClaim : \"rustus-pvc\" Warning Currently there's no ability to create multiple mounts and if you use file info storage you must specify the same direcotry as you specified for data storage. But it would be better to use other type of info-storage. Subcharts For example if you want to use redis as your info storage. values.yml env : RUSTUS_INFO_STORAGE : redis-info-storage RUSTUS_INFO_DB_DSN : redis://:pass@rustus-redis-master/0 redis : enabled : true redis , postgersql and mysql are subcharts. You can find information about configuration these subcharts here: Repo for redis; Repo for mysql; Repo for postgresql. In production you may ignore these subcharts to deploy your own redis or mysql or postgresql.","title":"Deployment"},{"location":"deploy/#deployment","text":"Deploying an application is always a challenge. Rustus was made to make deployment as easy as possible. Since this application works with files so if you want to scale number of rustus instances you have to somehow make different rustus instances to work with the same data or info directory.","title":"Deployment"},{"location":"deploy/#docker-compose","text":"docker-compose.yml # This is super simple configuration version : \"3.7\" services : rustus : image : s3rius/rustus volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data volumes : rustus_data_volume : After running docker compose up you will see rustus startup logs. If you want to deploy multiple rustus instances you can simply use config as this one: docker-compose.yml version : \"3.7\" services : proxy : image : jwilder/nginx-proxy:alpine container_name : proxy # Actual proxy ports. ports : - 8080:80 volumes : # This thing helps to locate containers # within this composition to generate nginx config. - /var/run/docker.sock:/tmp/docker.sock:ro rustus : image : s3rius/rustus ports : # Ports definition # To generate correct nginx config. - 1081 volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data environment : # Idk why but without this variable # load balancing with jwilder/nginx-proxy doesn't work. VIRTUAL_HOST : localhost volumes : rustus_data_volume : # This is named volume The main idea is that traffic that comes into nginx-proxy is routed in one of multiple rustus containers. Here I used jwilder/nginx-proxy but you can use other reverse-proxies such as raw nginx proxy or traefik . Now you can run multiple rustus instnaces like this. docker compose up --scale rustus = 3 After that you can upload files to http://localhost:8080/files","title":"Docker compose"},{"location":"deploy/#kubernetes","text":"Configuration for kubernetes is almost the same as docker. But the most preferable way is an official helm chart. Load balancing is done by kubernetes so you just have to create volume to mount data and info directories.","title":"Kubernetes"},{"location":"deploy/#helm","text":"You can install rustus by running this set of commands: helm repo add \"rustus\" \"https://s3rius.github.io/rustus/helm_releases\" helm repo update helm repo install \"rustus/rustus\"","title":"Helm"},{"location":"deploy/#configuration","text":"But of course it can be configured. # You can download basic configuration by running helm show values \"rustus/rustus\" > values.yml By editing values.yml you can configure many different options. Warning For production use you must provide and mount PersistentVolumeClaim in order to scale rustus. This helm chart has only one replica by default.","title":"Configuration"},{"location":"deploy/#persistence","text":"You can add pvc mount by editing persistence section. The most preferable way is to create PersistentVolume and PersistentVolumeClaim before installing this chart. After you created claim you can apply this values file to mount your claim into rustus. values.yml persistence : enabled : true existingClaim : \"rustus-pvc\" Warning Currently there's no ability to create multiple mounts and if you use file info storage you must specify the same direcotry as you specified for data storage. But it would be better to use other type of info-storage.","title":"Persistence"},{"location":"deploy/#subcharts","text":"For example if you want to use redis as your info storage. values.yml env : RUSTUS_INFO_STORAGE : redis-info-storage RUSTUS_INFO_DB_DSN : redis://:pass@rustus-redis-master/0 redis : enabled : true redis , postgersql and mysql are subcharts. You can find information about configuration these subcharts here: Repo for redis; Repo for mysql; Repo for postgresql. In production you may ignore these subcharts to deploy your own redis or mysql or postgresql.","title":"Subcharts"},{"location":"hooks/","text":"","title":"Hooks"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Rustus is a TUS protocol implementation that helps you handle file uploads. This project has many features that makes it easy to integrate in your service. Installation You can install rustus by 4 different ways. From source To build it from source rust must be installed. Preferred version is 1.59.0. git clone https://github.com/s3rius/rustus.git cd rustus cargo install --path . --features = all Also you can speedup build by disabling some features. Available features: amqp_notifier - adds amqp protocol support for notifying about upload status; db_info_storage - adds support for storing information about upload in different databases (Postgres, MySQL, SQLite); http_notifier - adds support for notifying about upload status via http protocol; redis_info_storage - adds support for storing information about upload in redis database; hashers - adds support for checksum verification; all - enables all rustus features. All precompiled binaries have all features enabled. With cargo If you have cargo installed maybe it would be easier to install it directly from crates.io. cargo install rustus --features = all Binaries All precompiled binaries available on github releases page. You can download binaries from here , unpack it and run. ./rustus Make sure that you download version for your cpu and os. Using docker One of the most simple ways to run rustus is docker. Rustus has two containers for each version. 1. debian based image 2. alpine based image Alpine based images are more lightweight than debian To run rustus you just need to run this command docker run --rm -p \"1081:1081\" -d s3rius/rustus --log-level \"DEBUG\"","title":"Welcome page"},{"location":"#installation","text":"You can install rustus by 4 different ways.","title":"Installation"},{"location":"#from-source","text":"To build it from source rust must be installed. Preferred version is 1.59.0. git clone https://github.com/s3rius/rustus.git cd rustus cargo install --path . --features = all Also you can speedup build by disabling some features. Available features: amqp_notifier - adds amqp protocol support for notifying about upload status; db_info_storage - adds support for storing information about upload in different databases (Postgres, MySQL, SQLite); http_notifier - adds support for notifying about upload status via http protocol; redis_info_storage - adds support for storing information about upload in redis database; hashers - adds support for checksum verification; all - enables all rustus features. All precompiled binaries have all features enabled.","title":"From source"},{"location":"#with-cargo","text":"If you have cargo installed maybe it would be easier to install it directly from crates.io. cargo install rustus --features = all","title":"With cargo"},{"location":"#binaries","text":"All precompiled binaries available on github releases page. You can download binaries from here , unpack it and run. ./rustus Make sure that you download version for your cpu and os.","title":"Binaries"},{"location":"#using-docker","text":"One of the most simple ways to run rustus is docker. Rustus has two containers for each version. 1. debian based image 2. alpine based image Alpine based images are more lightweight than debian To run rustus you just need to run this command docker run --rm -p \"1081:1081\" -d s3rius/rustus --log-level \"DEBUG\"","title":"Using docker"},{"location":"configuration/","text":"Rustus is highly configurable you can configure rustus with CLI or you can use environment variables. Info Some options can be passed only through as CLI parameters Info Information about hooks you can find on Hooks page . Configuring server We use actix to run server. You can configure on wich host and port rustus is listenging. Also you can configure number of actix workers that handle connections. --max-body-size is the max number of bytes that users can send in request body. --url is a base URL for all tus requests. --workers by default is euqal to number of physical CPU cores. Edit it carefully. CLI ENV rustus --host \"0.0.0.0\" \\ --port 1081 \\ --workers 8 \\ --max-body-size 1000000 \\ --url \"/files\" \\ --log-level \"INFO\" export RUSTUS_SERVER_HOST = \"0.0.0.0\" export RUSTUS_SERVER_PORT = \"1081\" export RUSTUS_SERVER_WORKERS = \"8\" export RUSTUS_MAX_BODY_SIZE = \"1000000\" export RUSTUS_URL = \"/files\" export RUSTUS_LOG_LEVEL = \"INFO\" rustus Configuring data storage Info Currently only file storage is available, so if you pass to --storage parameter other than file-storage you will get an error. Also you can not pass --force-fsync through environment variables. --storage is a type of data storage to be used. --data-dir is a path to the directory where all files are stored. --dir-structure is a pattern of a directory structure inside data dir. You can use variables within the pattern. Available variables: {year} - current year; {month} - current month number from 1 to 12; {day} - current day number from 1 to 31; {hour} - hour number from 0 to 23; {minute} - minute number from 0 to 59; {env[ENV_NAME]} - environment variable where ENV_NAME is name of your variable. Note All environment variables are saved in memory during rustus startup. So you cannot change variable dynamically. Even if you change env used in structure pattern it won't change. For example if you use {env[HOSTNAME]}/{year}/{month}/{day} as your dir-structure, rustus stores files like: $ tree data data \u2514\u2500\u2500 rtus-68cb5b8746-5mgw9 \u2514\u2500\u2500 2022 \u2514\u2500\u2500 1 \u2514\u2500\u2500 8 \u251c\u2500\u2500 0bd911d4054d41c6a3ad54be67ee3e66 \u2514\u2500\u2500 5bc9c62384494c439e2a064b82a39cc6 CLI ENV rustus --force-fsync \\ --storage \"file-storage\" \\ --data-dir \"./data/\" \\ --dir-structure \"{year}/{month}/{day}\" export RUSTUS_STORAGE = \"file-storage\" export RUSTUS_DATA_DIR = \"./data/\" export RUSTUS_DIR_STRUCTURE = \"{year}/{month}/{day}\" rustus --force-fsync Configuring info storage Info storages are used to store information about file uploads. These storages must be persistent, because every time chunk is uploaded rustus updates information about upload. And when someone wants to download file, information about it requested from storage to get actual path of an upload. Available info storages: file-info-storage - stores information in files on disk; redis-info-storage - information is stored in redis; db-info-storage - information is stored in database; File info storage file info storage stores information in files on disk. It's default info storage. Every download has it's own associated file. All .info files stored in flat structure so it's the least preferable way of storing information about uploads. But if you don't plan to have many uploads, it may fit well. --info-dir - directory where all .info file will be stored (default is ./data ). CLI ENV rustus --force-fsync \\ --storage \"file-info-storage\" \\ --info-dir \"./data\" export RUSTUS_INFO_STORAGE = \"file-info-storage\" export RUSTUS_INFO_DIR = \"./data\" rustus Redis info storage Redis db is a good way to store information. Note If you're using redis as a cluster you must provide connection string for master redis server. Since rustus need to have latest information and it writes a lot. --info-db-dsn - connection string for your redis database. It's required if redis-info-storage is chosen. CLI ENV rustus --force-fsync \\ --storage \"redis-info-storage\" \\ --info-db-dsn \"redis://localhost/0\" export RUSTUS_INFO_STORAGE = \"redis-info-storage\" export RUSTUS_INFO_DB_DSN = \"redis://localhost\" rustus DB info storage Rustus can store information about upload in database. It's a good and reliable option. But rustus can't work with replicas since it requires most recent information about uploads. You can use postgresql , mysql or even sqlite schemas to connect to database. --info-db-dsn - connection string for your database. CLI ENV rustus --force-fsync \\ --storage \"db-info-storage\" \\ --info-db-dsn \"postgresql://user:password@localhost/db\" export RUSTUS_INFO_STORAGE = \"redis-info-storage\" export RUSTUS_INFO_DB_DSN = \"postgresql://user:password@localhost/db\" rustus Configuring TUS Since tus protocol offers extensibility you can turn off some protocol extensions. Available extensions: getting - rustus specific extension that helps you download uploaded files with get request; creation - helps you to create files (It's like a core feature you better have this enabled); termination - allows you to delete uploads with DELETE request; creation-with-upload - allows you to write first bytes of a file while creating; creation-defer-length - allows you to create file without specifying file length; concatenation - allows you to concatenate finished partial uploads. checksum - allows you to verify checksum of every batch. You can read more about extensions on official web-site . --tus-extensions - a list of enabled extensions. By default all extensions are enabled. CLI ENV rustus --tus-extensions \"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum\" export RUSTUS_TUS_EXTENSIONS = \"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum\" rustus","title":"Configuration"},{"location":"configuration/#configuring-server","text":"We use actix to run server. You can configure on wich host and port rustus is listenging. Also you can configure number of actix workers that handle connections. --max-body-size is the max number of bytes that users can send in request body. --url is a base URL for all tus requests. --workers by default is euqal to number of physical CPU cores. Edit it carefully. CLI ENV rustus --host \"0.0.0.0\" \\ --port 1081 \\ --workers 8 \\ --max-body-size 1000000 \\ --url \"/files\" \\ --log-level \"INFO\" export RUSTUS_SERVER_HOST = \"0.0.0.0\" export RUSTUS_SERVER_PORT = \"1081\" export RUSTUS_SERVER_WORKERS = \"8\" export RUSTUS_MAX_BODY_SIZE = \"1000000\" export RUSTUS_URL = \"/files\" export RUSTUS_LOG_LEVEL = \"INFO\" rustus","title":"Configuring server"},{"location":"configuration/#configuring-data-storage","text":"Info Currently only file storage is available, so if you pass to --storage parameter other than file-storage you will get an error. Also you can not pass --force-fsync through environment variables. --storage is a type of data storage to be used. --data-dir is a path to the directory where all files are stored. --dir-structure is a pattern of a directory structure inside data dir. You can use variables within the pattern. Available variables: {year} - current year; {month} - current month number from 1 to 12; {day} - current day number from 1 to 31; {hour} - hour number from 0 to 23; {minute} - minute number from 0 to 59; {env[ENV_NAME]} - environment variable where ENV_NAME is name of your variable. Note All environment variables are saved in memory during rustus startup. So you cannot change variable dynamically. Even if you change env used in structure pattern it won't change. For example if you use {env[HOSTNAME]}/{year}/{month}/{day} as your dir-structure, rustus stores files like: $ tree data data \u2514\u2500\u2500 rtus-68cb5b8746-5mgw9 \u2514\u2500\u2500 2022 \u2514\u2500\u2500 1 \u2514\u2500\u2500 8 \u251c\u2500\u2500 0bd911d4054d41c6a3ad54be67ee3e66 \u2514\u2500\u2500 5bc9c62384494c439e2a064b82a39cc6 CLI ENV rustus --force-fsync \\ --storage \"file-storage\" \\ --data-dir \"./data/\" \\ --dir-structure \"{year}/{month}/{day}\" export RUSTUS_STORAGE = \"file-storage\" export RUSTUS_DATA_DIR = \"./data/\" export RUSTUS_DIR_STRUCTURE = \"{year}/{month}/{day}\" rustus --force-fsync","title":"Configuring data storage"},{"location":"configuration/#configuring-info-storage","text":"Info storages are used to store information about file uploads. These storages must be persistent, because every time chunk is uploaded rustus updates information about upload. And when someone wants to download file, information about it requested from storage to get actual path of an upload. Available info storages: file-info-storage - stores information in files on disk; redis-info-storage - information is stored in redis; db-info-storage - information is stored in database;","title":"Configuring info storage"},{"location":"configuration/#file-info-storage","text":"file info storage stores information in files on disk. It's default info storage. Every download has it's own associated file. All .info files stored in flat structure so it's the least preferable way of storing information about uploads. But if you don't plan to have many uploads, it may fit well. --info-dir - directory where all .info file will be stored (default is ./data ). CLI ENV rustus --force-fsync \\ --storage \"file-info-storage\" \\ --info-dir \"./data\" export RUSTUS_INFO_STORAGE = \"file-info-storage\" export RUSTUS_INFO_DIR = \"./data\" rustus","title":"File info storage"},{"location":"configuration/#redis-info-storage","text":"Redis db is a good way to store information. Note If you're using redis as a cluster you must provide connection string for master redis server. Since rustus need to have latest information and it writes a lot. --info-db-dsn - connection string for your redis database. It's required if redis-info-storage is chosen. CLI ENV rustus --force-fsync \\ --storage \"redis-info-storage\" \\ --info-db-dsn \"redis://localhost/0\" export RUSTUS_INFO_STORAGE = \"redis-info-storage\" export RUSTUS_INFO_DB_DSN = \"redis://localhost\" rustus","title":"Redis info storage"},{"location":"configuration/#db-info-storage","text":"Rustus can store information about upload in database. It's a good and reliable option. But rustus can't work with replicas since it requires most recent information about uploads. You can use postgresql , mysql or even sqlite schemas to connect to database. --info-db-dsn - connection string for your database. CLI ENV rustus --force-fsync \\ --storage \"db-info-storage\" \\ --info-db-dsn \"postgresql://user:password@localhost/db\" export RUSTUS_INFO_STORAGE = \"redis-info-storage\" export RUSTUS_INFO_DB_DSN = \"postgresql://user:password@localhost/db\" rustus","title":"DB info storage"},{"location":"configuration/#configuring-tus","text":"Since tus protocol offers extensibility you can turn off some protocol extensions. Available extensions: getting - rustus specific extension that helps you download uploaded files with get request; creation - helps you to create files (It's like a core feature you better have this enabled); termination - allows you to delete uploads with DELETE request; creation-with-upload - allows you to write first bytes of a file while creating; creation-defer-length - allows you to create file without specifying file length; concatenation - allows you to concatenate finished partial uploads. checksum - allows you to verify checksum of every batch. You can read more about extensions on official web-site . --tus-extensions - a list of enabled extensions. By default all extensions are enabled. CLI ENV rustus --tus-extensions \"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum\" export RUSTUS_TUS_EXTENSIONS = \"getting,creation,termination,creation-with-upload,creation-defer-length,concatenation,checksum\" rustus","title":"Configuring TUS"},{"location":"deploy/","text":"Deployment Deploying an application is always a challenge. Rustus was made to make deployment as easy as possible. Since this application works with files so if you want to scale number of rustus instances you have to somehow make different rustus instances to work with the same data or info directory. Docker compose docker-compose.yml # This is super simple configuration version : \"3.7\" services : rustus : image : s3rius/rustus volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data volumes : rustus_data_volume : After running docker compose up you will see rustus startup logs. If you want to deploy multiple rustus instances you can simply use config as this one: docker-compose.yml version : \"3.7\" services : proxy : image : jwilder/nginx-proxy:alpine container_name : proxy # Actual proxy ports. ports : - 8080:80 volumes : # This thing helps to locate containers # within this composition to generate nginx config. - /var/run/docker.sock:/tmp/docker.sock:ro rustus : image : s3rius/rustus ports : # Ports definition # To generate correct nginx config. - 1081 volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data environment : # Idk why but without this variable # load balancing with jwilder/nginx-proxy doesn't work. VIRTUAL_HOST : localhost volumes : rustus_data_volume : # This is named volume The main idea is that traffic that comes into nginx-proxy is routed in one of multiple rustus containers. Here I used jwilder/nginx-proxy but you can use other reverse-proxies such as raw nginx proxy or traefik . Now you can run multiple rustus instnaces like this. docker compose up --scale rustus = 3 After that you can upload files to http://localhost:8080/files Kubernetes Configuration for kubernetes is almost the same as docker. But the most preferable way is an official helm chart. Load balancing is done by kubernetes so you just have to create volume to mount data and info directories. Helm You can install rustus by running this set of commands: helm repo add \"rustus\" \"https://s3rius.github.io/rustus/helm_releases\" helm repo update helm repo install \"rustus/rustus\" Configuration But of course it can be configured. # You can download basic configuration by running helm show values \"rustus/rustus\" > values.yml By editing values.yml you can configure many different options. Warning For production use you must provide and mount PersistentVolumeClaim in order to scale rustus. This helm chart has only one replica by default. Persistence You can add pvc mount by editing persistence section. The most preferable way is to create PersistentVolume and PersistentVolumeClaim before installing this chart. After you created claim you can apply this values file to mount your claim into rustus. values.yml persistence : enabled : true existingClaim : \"rustus-pvc\" Warning Currently there's no ability to create multiple mounts and if you use file info storage you must specify the same direcotry as you specified for data storage. But it would be better to use other type of info-storage. Subcharts For example if you want to use redis as your info storage. values.yml env : RUSTUS_INFO_STORAGE : redis-info-storage RUSTUS_INFO_DB_DSN : redis://:pass@rustus-redis-master/0 redis : enabled : true redis , postgersql and mysql are subcharts. You can find information about configuration these subcharts here: Repo for redis; Repo for mysql; Repo for postgresql. In production you may ignore these subcharts to deploy your own redis or mysql or postgresql. After you done editing values.yml you can apply the configuration like this: helm upgrade \\ --install \\ # Install chart if it's not installed --namespace rustus \\ # k8s namespace --create-namespace \\ # Creates namespace if it doesn't exist --atomic \\ # Ensures that everything is deployed correctly --values \"values.yml\" \\ # Link to values.yml file \"rustus\" \\ # name of a release \"rustus/rustus\" # Name of the chart","title":"Deployment"},{"location":"deploy/#deployment","text":"Deploying an application is always a challenge. Rustus was made to make deployment as easy as possible. Since this application works with files so if you want to scale number of rustus instances you have to somehow make different rustus instances to work with the same data or info directory.","title":"Deployment"},{"location":"deploy/#docker-compose","text":"docker-compose.yml # This is super simple configuration version : \"3.7\" services : rustus : image : s3rius/rustus volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data volumes : rustus_data_volume : After running docker compose up you will see rustus startup logs. If you want to deploy multiple rustus instances you can simply use config as this one: docker-compose.yml version : \"3.7\" services : proxy : image : jwilder/nginx-proxy:alpine container_name : proxy # Actual proxy ports. ports : - 8080:80 volumes : # This thing helps to locate containers # within this composition to generate nginx config. - /var/run/docker.sock:/tmp/docker.sock:ro rustus : image : s3rius/rustus ports : # Ports definition # To generate correct nginx config. - 1081 volumes : # Volume mouted to default data directory # So it's available across multiple containers. - rustus_data_volume:/app/data environment : # Idk why but without this variable # load balancing with jwilder/nginx-proxy doesn't work. VIRTUAL_HOST : localhost volumes : rustus_data_volume : # This is named volume The main idea is that traffic that comes into nginx-proxy is routed in one of multiple rustus containers. Here I used jwilder/nginx-proxy but you can use other reverse-proxies such as raw nginx proxy or traefik . Now you can run multiple rustus instnaces like this. docker compose up --scale rustus = 3 After that you can upload files to http://localhost:8080/files","title":"Docker compose"},{"location":"deploy/#kubernetes","text":"Configuration for kubernetes is almost the same as docker. But the most preferable way is an official helm chart. Load balancing is done by kubernetes so you just have to create volume to mount data and info directories.","title":"Kubernetes"},{"location":"deploy/#helm","text":"You can install rustus by running this set of commands: helm repo add \"rustus\" \"https://s3rius.github.io/rustus/helm_releases\" helm repo update helm repo install \"rustus/rustus\"","title":"Helm"},{"location":"deploy/#configuration","text":"But of course it can be configured. # You can download basic configuration by running helm show values \"rustus/rustus\" > values.yml By editing values.yml you can configure many different options. Warning For production use you must provide and mount PersistentVolumeClaim in order to scale rustus. This helm chart has only one replica by default.","title":"Configuration"},{"location":"deploy/#persistence","text":"You can add pvc mount by editing persistence section. The most preferable way is to create PersistentVolume and PersistentVolumeClaim before installing this chart. After you created claim you can apply this values file to mount your claim into rustus. values.yml persistence : enabled : true existingClaim : \"rustus-pvc\" Warning Currently there's no ability to create multiple mounts and if you use file info storage you must specify the same direcotry as you specified for data storage. But it would be better to use other type of info-storage.","title":"Persistence"},{"location":"deploy/#subcharts","text":"For example if you want to use redis as your info storage. values.yml env : RUSTUS_INFO_STORAGE : redis-info-storage RUSTUS_INFO_DB_DSN : redis://:pass@rustus-redis-master/0 redis : enabled : true redis , postgersql and mysql are subcharts. You can find information about configuration these subcharts here: Repo for redis; Repo for mysql; Repo for postgresql. In production you may ignore these subcharts to deploy your own redis or mysql or postgresql. After you done editing values.yml you can apply the configuration like this: helm upgrade \\ --install \\ # Install chart if it's not installed --namespace rustus \\ # k8s namespace --create-namespace \\ # Creates namespace if it doesn't exist --atomic \\ # Ensures that everything is deployed correctly --values \"values.yml\" \\ # Link to values.yml file \"rustus\" \\ # name of a release \"rustus/rustus\" # Name of the chart","title":"Subcharts"},{"location":"hooks/","text":"Rustus can notify about uploads using hooks. This is useful when you integrate rustus in your architecture. Apps can keep track of every upload using this feature. Rustus has different event types for different moments of an upload's lifecycle. pre-create - This hook means that someone wants to create an upload; post-create - someone successfully created an upload; post-receive - someone uploaded a new part of an upload; post-terminate - someone deleted upload; post-finish - someone finished uploading file. Note Pre-create hook is very important. If at least one of hooks fails, upload is canceled. But AMQP hooks won't cancel the upload, since it's non blocking type of hooks. You can disable some hooks by using --hooks parameter. CLI ENV rustus --hooks \"pre-create,post-create,post-receive,post-terminate,post-finish\" export RUSTUS_HOOKS = \"pre-create,post-create,post-receive,post-terminate,post-finish\" rustus Fomat Information about every hook using JSON format. Format can be configured using --hooks-format parameter or RUSTUS_HOOKS_FORMAT environment variable. Available formats: default tusd default tusd { \"upload\" : { \"id\" : \"\" , \"offset\" : 0 , \"length\" : 39729945 , \"path\" : null , \"created_at\" : 1641620821 , \"deferred_size\" : false , \"metadata\" : { \"filename\" : \"38MB_video.mp4\" , \"meme\" : \"hehe2\" } }, \"request\" : { \"URI\" : \"/files\" , \"method\" : \"POST\" , \"remote_addr\" : \"127.0.0.1\" , \"headers\" : { \"accept-encoding\" : \"gzip, deflate\" , \"connection\" : \"keep-alive\" , \"host\" : \"localhost:1081\" , \"upload-metadata\" : \"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ=\" , \"tus-resumable\" : \"1.0.0\" , \"content-length\" : \"0\" , \"upload-length\" : \"39729945\" , \"user-agent\" : \"python-requests/2.26.0\" , \"accept\" : \"*/*\" } } } { \"Upload\" : { \"ID\" : \"\" , \"Offset\" : 0 , \"Size\" : 39729945 , \"IsFinal\" : true , \"IsPartial\" : false , \"PartialUploads\" : null , \"SizeIsDeferred\" : false , \"Metadata\" : { \"filename\" : \"38MB_video.mp4\" , \"meme\" : \"hehe2\" }, \"Storage\" : { \"Type\" : \"filestore\" , \"Path\" : null } }, \"HTTPRequest\" : { \"URI\" : \"/files\" , \"Method\" : \"POST\" , \"RemoteAddr\" : \"127.0.0.1\" , \"Header\" : { \"host\" : [ \"localhost:1081\" ], \"user-agent\" : [ \"python-requests/2.26.0\" ], \"accept\" : [ \"*/*\" ], \"content-length\" : [ \"0\" ], \"upload-metadata\" : [ \"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ=\" ], \"connection\" : [ \"keep-alive\" ], \"tus-resumable\" : [ \"1.0.0\" ], \"upload-length\" : [ \"39729945\" ], \"accept-encoding\" : [ \"gzip, deflate\" ] } } } Hook types Rustus offers multiple types of Hooks. We'll take a brief look on each type. File hooks Rustus can work with two types of file hooks. Single file hook Hooks directory The main difference is that in case if use single file hook, hook name is passed as a command line argument to an executable file, but if you use hooks directory then hook name is used to determine a file to call. Let's take a look at the examples. Parameters: * --hooks-file - path to an executable file; * --hooks-dir - path to a directory with executable files. single_file_hook.sh #!/bin/bash # Hook name would be \"pre-create\", \"post-create\" and so on. HOOK_NAME = \" $1 \" HOOK_INFO = \" $2 \" MEME = \" $( echo \" $HOOK_INFO \" | jq \".upload .metadata .meme\" | xargs ) \" # Here we check if name in metadata is equal to pepe. if [[ $MEME = \"pepe\" ]] ; then echo \"This meme isn't allowed\" 1 > & 2 ; exit 1 fi As you can see it uses first CLI parameter as a hook name and all hook data is received from the second one. Let's make it executable and make rustus use this hook. CLI ENV chmod +x \"hooks/single_file_hook.sh\" rustus --hooks-file \"hooks/single_file_hook.sh\" chmod +x \"hooks/single_file_hook.sh\" export RUSTUS_HOOKS_FILE = \"hooks/single_file_hook.sh\" rustus If you would like to use directory hooks you must create directory with the following structure: hooks \u251c\u2500\u2500 post-create \u251c\u2500\u2500 post-finish \u251c\u2500\u2500 post-receive \u251c\u2500\u2500 post-terminate \u2514\u2500\u2500 pre-create Warning If some hook file isn't found, rustus throws an error. In case with pre-create hook it can be fatal. Http Hooks Http hooks use HTTP to send POST requests to some endpoint. Configuration parameters: --hooks-http-proxy-headers - list of headers to proxy (separated by commas) to listener's endpoint; --hooks-http-urls - list of absolute urls to send request to (separated by commas). Note Hook names are passed as header called Hook-Name . CLI ENV rustus --hooks-http-urls \"https://httpbin.org/post\" \\ --hooks-http-proxy-headers \"Authorization\" export RUSTUS_HOOKS_HTTP_URLS = \"https://httpbin.org/post\" export RUSTUS_HOOKS_HTTP_PROXY_HEADERS = \"Authorization\" rustus Example application To be more verbose let's create simple web server that handles uploads using FastAPI . At first we need to install dependencies using pip. pip install fastapi uvicorn server.py from fastapi import FastAPI , Header , HTTPException from typing import Optional app = FastAPI () @app . post ( \"/hooks\" ) def hook ( authorization : Optional [ str ] = Header ( None ), hook_name : Optional [ str ] = Header ( None ), ): print ( f \"Received: { hook_name } \" ) if authorization != \"Bearer jwt\" : raise HTTPException ( 401 ) return None Now we can run this server using uvicorn. uvicorn server:app --port 8080 Let's configure rustus to use this server as a hook reciever. CLI ENV rustus --hooks-http-urls \"http://localhost:8000/hooks\" \\ --hooks-http-proxy-headers \"Authorization\" export RUSTUS_HOOKS_HTTP_URLS = \"http://localhost:8000/hooks\" export RUSTUS_HOOKS_HTTP_PROXY_HEADERS = \"Authorization\" rustus That's it. AMQP hooks AMQP hooks are used to store information about uploads using RabbitMQ. Configuration parameters: --hooks-amqp-url - connection string to RabbitMQ; --hooks-amqp-queues-prefix - prefix for queues for every event queue; --hooks-amqp-exchange - name of exchange to use. This hook will send every message in an exchange with routing keys like queues names. Queues are named like {prefix}.{event type} . Eg rustus.pre-create and so on. Warning Since we can't really track message delivery and responses Rustus doesn't stop in any case. CLI ENV rustus --hooks-amqp-url \"amqp://guest:guest@localhost:5672\" \\ --hooks-amqp-queues-prefix \"rustus_queue\" \\ --hooks-amqp-exchange \"rustus\" export RUSTUS_HOOKS_AMQP_URL = \"amqp://guest:guest@localhost:5672\" export RUSTUS_HOOKS_AMQP_QUEUES_PREFIX = \"rustus_queue\" export RUSTUS_HOOKS_AMQP_EXCHANGE = \"rustus\" rustus","title":"Setting up hooks"},{"location":"hooks/#fomat","text":"Information about every hook using JSON format. Format can be configured using --hooks-format parameter or RUSTUS_HOOKS_FORMAT environment variable. Available formats: default tusd default tusd { \"upload\" : { \"id\" : \"\" , \"offset\" : 0 , \"length\" : 39729945 , \"path\" : null , \"created_at\" : 1641620821 , \"deferred_size\" : false , \"metadata\" : { \"filename\" : \"38MB_video.mp4\" , \"meme\" : \"hehe2\" } }, \"request\" : { \"URI\" : \"/files\" , \"method\" : \"POST\" , \"remote_addr\" : \"127.0.0.1\" , \"headers\" : { \"accept-encoding\" : \"gzip, deflate\" , \"connection\" : \"keep-alive\" , \"host\" : \"localhost:1081\" , \"upload-metadata\" : \"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ=\" , \"tus-resumable\" : \"1.0.0\" , \"content-length\" : \"0\" , \"upload-length\" : \"39729945\" , \"user-agent\" : \"python-requests/2.26.0\" , \"accept\" : \"*/*\" } } } { \"Upload\" : { \"ID\" : \"\" , \"Offset\" : 0 , \"Size\" : 39729945 , \"IsFinal\" : true , \"IsPartial\" : false , \"PartialUploads\" : null , \"SizeIsDeferred\" : false , \"Metadata\" : { \"filename\" : \"38MB_video.mp4\" , \"meme\" : \"hehe2\" }, \"Storage\" : { \"Type\" : \"filestore\" , \"Path\" : null } }, \"HTTPRequest\" : { \"URI\" : \"/files\" , \"Method\" : \"POST\" , \"RemoteAddr\" : \"127.0.0.1\" , \"Header\" : { \"host\" : [ \"localhost:1081\" ], \"user-agent\" : [ \"python-requests/2.26.0\" ], \"accept\" : [ \"*/*\" ], \"content-length\" : [ \"0\" ], \"upload-metadata\" : [ \"meme aGVoZTI=,filename MzhNQl92aWRlby5tcDQ=\" ], \"connection\" : [ \"keep-alive\" ], \"tus-resumable\" : [ \"1.0.0\" ], \"upload-length\" : [ \"39729945\" ], \"accept-encoding\" : [ \"gzip, deflate\" ] } } }","title":"Fomat"},{"location":"hooks/#hook-types","text":"Rustus offers multiple types of Hooks. We'll take a brief look on each type.","title":"Hook types"},{"location":"hooks/#file-hooks","text":"Rustus can work with two types of file hooks. Single file hook Hooks directory The main difference is that in case if use single file hook, hook name is passed as a command line argument to an executable file, but if you use hooks directory then hook name is used to determine a file to call. Let's take a look at the examples. Parameters: * --hooks-file - path to an executable file; * --hooks-dir - path to a directory with executable files. single_file_hook.sh #!/bin/bash # Hook name would be \"pre-create\", \"post-create\" and so on. HOOK_NAME = \" $1 \" HOOK_INFO = \" $2 \" MEME = \" $( echo \" $HOOK_INFO \" | jq \".upload .metadata .meme\" | xargs ) \" # Here we check if name in metadata is equal to pepe. if [[ $MEME = \"pepe\" ]] ; then echo \"This meme isn't allowed\" 1 > & 2 ; exit 1 fi As you can see it uses first CLI parameter as a hook name and all hook data is received from the second one. Let's make it executable and make rustus use this hook. CLI ENV chmod +x \"hooks/single_file_hook.sh\" rustus --hooks-file \"hooks/single_file_hook.sh\" chmod +x \"hooks/single_file_hook.sh\" export RUSTUS_HOOKS_FILE = \"hooks/single_file_hook.sh\" rustus If you would like to use directory hooks you must create directory with the following structure: hooks \u251c\u2500\u2500 post-create \u251c\u2500\u2500 post-finish \u251c\u2500\u2500 post-receive \u251c\u2500\u2500 post-terminate \u2514\u2500\u2500 pre-create Warning If some hook file isn't found, rustus throws an error. In case with pre-create hook it can be fatal.","title":"File hooks"},{"location":"hooks/#http-hooks","text":"Http hooks use HTTP to send POST requests to some endpoint. Configuration parameters: --hooks-http-proxy-headers - list of headers to proxy (separated by commas) to listener's endpoint; --hooks-http-urls - list of absolute urls to send request to (separated by commas). Note Hook names are passed as header called Hook-Name . CLI ENV rustus --hooks-http-urls \"https://httpbin.org/post\" \\ --hooks-http-proxy-headers \"Authorization\" export RUSTUS_HOOKS_HTTP_URLS = \"https://httpbin.org/post\" export RUSTUS_HOOKS_HTTP_PROXY_HEADERS = \"Authorization\" rustus","title":"Http Hooks"},{"location":"hooks/#example-application","text":"To be more verbose let's create simple web server that handles uploads using FastAPI . At first we need to install dependencies using pip. pip install fastapi uvicorn server.py from fastapi import FastAPI , Header , HTTPException from typing import Optional app = FastAPI () @app . post ( \"/hooks\" ) def hook ( authorization : Optional [ str ] = Header ( None ), hook_name : Optional [ str ] = Header ( None ), ): print ( f \"Received: { hook_name } \" ) if authorization != \"Bearer jwt\" : raise HTTPException ( 401 ) return None Now we can run this server using uvicorn. uvicorn server:app --port 8080 Let's configure rustus to use this server as a hook reciever. CLI ENV rustus --hooks-http-urls \"http://localhost:8000/hooks\" \\ --hooks-http-proxy-headers \"Authorization\" export RUSTUS_HOOKS_HTTP_URLS = \"http://localhost:8000/hooks\" export RUSTUS_HOOKS_HTTP_PROXY_HEADERS = \"Authorization\" rustus That's it.","title":"Example application"},{"location":"hooks/#amqp-hooks","text":"AMQP hooks are used to store information about uploads using RabbitMQ. Configuration parameters: --hooks-amqp-url - connection string to RabbitMQ; --hooks-amqp-queues-prefix - prefix for queues for every event queue; --hooks-amqp-exchange - name of exchange to use. This hook will send every message in an exchange with routing keys like queues names. Queues are named like {prefix}.{event type} . Eg rustus.pre-create and so on. Warning Since we can't really track message delivery and responses Rustus doesn't stop in any case. CLI ENV rustus --hooks-amqp-url \"amqp://guest:guest@localhost:5672\" \\ --hooks-amqp-queues-prefix \"rustus_queue\" \\ --hooks-amqp-exchange \"rustus\" export RUSTUS_HOOKS_AMQP_URL = \"amqp://guest:guest@localhost:5672\" export RUSTUS_HOOKS_AMQP_QUEUES_PREFIX = \"rustus_queue\" export RUSTUS_HOOKS_AMQP_EXCHANGE = \"rustus\" rustus","title":"AMQP hooks"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index c094516dbc671749ab268eab616bc362392d2323..ebaa75eb2af63527adfb1b62cc391a9b709161ba 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ