mirror of
https://github.com/balkian/balkian.github.com.git
synced 2025-02-23 10:15:05 +00:00
91 lines
22 KiB
HTML
91 lines
22 KiB
HTML
<!doctype html><html lang=en-us dir=ltr><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><meta name=description content='This is a quick note on proxying a local python application (e.g. flask) to a subdirectory in Apache. This assumes that the file wsgi.py contains a WSGI application with the name application. Hence, wsgi:application.\nGunicorn 1 2 3 4 5 <Location /myapp/> ProxyPass http://127.0.0.1:8888/myapp/ ProxyPassReverse http://127.0.0.1:8888/myapp/ RequestHeader set SCRIPT_NAME "/myapp/" </Location> '><title>Proxies with Apache and python</title>
|
|
<link rel=canonical href=https://balkian.com/p/proxies-with-apache-and-python/><link rel=stylesheet href=/scss/style.min.663803bebe609202d5b39d848f2d7c2dc8b598a2d879efa079fa88893d29c49c.css><meta property='og:title' content="Proxies with Apache and python"><meta property='og:description' content='This is a quick note on proxying a local python application (e.g. flask) to a subdirectory in Apache. This assumes that the file wsgi.py contains a WSGI application with the name application. Hence, wsgi:application.\nGunicorn 1 2 3 4 5 <Location /myapp/> ProxyPass http://127.0.0.1:8888/myapp/ ProxyPassReverse http://127.0.0.1:8888/myapp/ RequestHeader set SCRIPT_NAME "/myapp/" </Location> '><meta property='og:url' content='https://balkian.com/p/proxies-with-apache-and-python/'><meta property='og:site_name' content='J. Fernando Sánchez'><meta property='og:type' content='article'><meta property='article:section' content='Post'><meta property='article:tag' content='python'><meta property='article:tag' content='apache'><meta property='article:tag' content='proxy'><meta property='article:tag' content='gunicorn'><meta property='article:tag' content='uwsgi'><meta property='article:published_time' content='2014-10-09T10:00:00+00:00'><meta property='article:modified_time' content='2014-10-09T10:00:00+00:00'><meta name=twitter:title content="Proxies with Apache and python"><meta name=twitter:description content='This is a quick note on proxying a local python application (e.g. flask) to a subdirectory in Apache. This assumes that the file wsgi.py contains a WSGI application with the name application. Hence, wsgi:application.\nGunicorn 1 2 3 4 5 <Location /myapp/> ProxyPass http://127.0.0.1:8888/myapp/ ProxyPassReverse http://127.0.0.1:8888/myapp/ RequestHeader set SCRIPT_NAME "/myapp/" </Location> '><link rel="shortcut icon" href=/img/favicon.ico></head><body class=article-page><script>(function(){const e="StackColorScheme";localStorage.getItem(e)||localStorage.setItem(e,"auto")})()</script><script>(function(){const t="StackColorScheme",e=localStorage.getItem(t),n=window.matchMedia("(prefers-color-scheme: dark)").matches===!0;e=="dark"||e==="auto"&&n?document.documentElement.dataset.scheme="dark":document.documentElement.dataset.scheme="light"})()</script><div class="container main-container flex on-phone--column extended"><aside class="sidebar left-sidebar sticky"><button class="hamburger hamburger--spin" type=button id=toggle-menu aria-label="Toggle Menu">
|
|
<span class=hamburger-box><span class=hamburger-inner></span></span></button><header><figure class=site-avatar><a href=/><img src=/img/me_hu_caa0902d7ae4598e.png width=300 height=300 class=site-logo loading=lazy alt=Avatar>
|
|
</a><span class=emoji>💭</span></figure><div class=site-meta><h1 class=site-name><a href=/>J. Fernando Sánchez</a></h1><h2 class=site-description>My ramblings and reflections</h2></div></header><ol class=menu-social><li><a href=https://github.com/CaiJimmy/hugo-theme-stack target=_blank title=GitHub rel=me><svg class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6.0 00-1.3-3.2 4.2 4.2.0 00-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3.0 00-6.2.0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2.0 00-.1 3.2A4.6 4.6.0 004 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21"/></svg></a></li><li><a href=https://git.sinpapel.es/balkian target=_blank title=gitea rel=me><svg viewBox="0 0 640 640" width="32" height="32"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9.0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6M125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1m300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8s2 16.3 9.1 20c7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3s17.4 1.7 22.5-5.3c5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8z" style="fill:#609926"/></svg></a></li><li><a href='https://scholar.google.com/citations?user=JLNusZ8AAAAJ&hl=en' target=_blank title="Google scholar" rel=me><svg aria-label="Google Scholar" role="img" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#4285f4"/><path fill="#fff" d="M213 111l-107 94h69c5 45 41 64 78 67-7 18-4 27 7 39-43 1-103 26-103 67 4 45 63 54 92 54 38 1 81-19 90-54 4-35-10-54-31-71-23-18-28-28-21-40 15-17 35-27 39-51 2-17-2-28-6-43l45-38-1 16c-3 2-5 6-5 9v103c2 13 22 11 23 0V160c0-3-2-7-5-8v-25l16-16zm58 141c-61 10-87-87-38-99 56-11 83 86 38 99zm-5 73c60 13 61 63 10 78-44 9-82-4-81-30 0-25 35-48 71-48z"/></svg></a></li></ol><ol class=menu id=main-menu><li><a href=/><svg class="icon icon-tabler icon-tabler-home" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><polyline points="5 12 3 12 12 3 21 12 19 12"/><path d="M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7"/><path d="M9 21v-6a2 2 0 012-2h2a2 2 0 012 2v6"/></svg>
|
|
<span>Home</span></a></li><li><a href=/projects/><svg class="icon icon-tabler icon-tabler-clock" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 15"/></svg>
|
|
<span>Projects</span></a></li><li><a href=/archives/><svg class="icon icon-tabler icon-tabler-archive" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><rect x="3" y="4" width="18" height="4" rx="2"/><path d="M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8"/><line x1="10" y1="12" x2="14" y2="12"/></svg>
|
|
<span>Archives</span></a></li><li><a href=/search/><svg class="icon icon-tabler icon-tabler-search" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="10" cy="10" r="7"/><line x1="21" y1="21" x2="15" y2="15"/></svg>
|
|
<span>Search</span></a></li><li><a href=/page/cheatsheet/><svg class="icon icon-tabler icon-tabler-infinity" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M9.828 9.172a4 4 0 100 5.656A10 10 0 0012 12a10 10 0 012.172-2.828 4 4 0 110 5.656A10 10 0 0112 12 10 10 0 009.828 9.172"/></svg>
|
|
<span>Cheatsheets</span></a></li><li><a href=/links/><svg class="icon icon-tabler icon-tabler-link" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M10 14a3.5 3.5.0 005 0l4-4a3.5 3.5.0 00-5-5l-.5.5"/><path d="M14 10a3.5 3.5.0 00-5 0l-4 4a3.5 3.5.0 005 5l.5-.5"/></svg>
|
|
<span>Links</span></a></li><li class=menu-bottom-section><ol class=menu><li id=dark-mode-toggle><svg class="icon icon-tabler icon-tabler-toggle-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="8" cy="12" r="2"/><rect x="2" y="6" width="20" height="12" rx="6"/></svg>
|
|
<svg class="icon icon-tabler icon-tabler-toggle-right" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="16" cy="12" r="2"/><rect x="2" y="6" width="20" height="12" rx="6"/></svg>
|
|
<span>Dark Mode</span></li></ol></li></ol></aside><aside class="sidebar right-sidebar sticky"><section class="widget archives"><div class=widget-icon><svg class="icon icon-tabler icon-tabler-hash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><line x1="5" y1="9" x2="19" y2="9"/><line x1="5" y1="15" x2="19" y2="15"/><line x1="11" y1="4" x2="7" y2="20"/><line x1="17" y1="4" x2="13" y2="20"/></svg></div><h2 class="widget-title section-title">Table of contents</h2><div class=widget--toc><nav id=TableOfContents><ol><li><a href=#gunicorn>Gunicorn</a></li><li><a href=#uwsgi>UWSGI</a></li><li><a href=#extra-supervisor>Extra: Supervisor</a></li></ol></nav></div></section></aside><main class="main full-width"><article class=main-article><header class=article-header><div class=article-details><div class=article-title-wrapper><h2 class=article-title><a href=/p/proxies-with-apache-and-python/>Proxies with Apache and python</a></h2></div><footer class=article-time><div><svg class="icon icon-tabler icon-tabler-calendar-time" width="56" height="56" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M11.795 21H5a2 2 0 01-2-2V7a2 2 0 012-2h12a2 2 0 012 2v4"/><circle cx="18" cy="18" r="4"/><path d="M15 3v4"/><path d="M7 3v4"/><path d="M3 11h16"/><path d="M18 16.496V18l1 1"/></svg>
|
|
<time class=article-time--published>09 Oct 2014</time></div><div><svg class="icon icon-tabler icon-tabler-clock" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 15"/></svg>
|
|
<time class=article-time--reading>2 minute read</time></div></footer></div></header><section class=article-content><p>This is a quick note on proxying a local python application (e.g. flask)
|
|
to a subdirectory in Apache. This assumes that the file wsgi.py contains
|
|
a WSGI application with the name <em>application</em>. Hence, wsgi:application.</p><h2 id=gunicorn>Gunicorn</h2><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
|
|
</span><span class=lnt>2
|
|
</span><span class=lnt>3
|
|
</span><span class=lnt>4
|
|
</span><span class=lnt>5
|
|
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-apache data-lang=apache><span class=line><span class=cl><span class=nt><Location</span> <span class=s>/myapp/</span><span class=nt>></span>
|
|
</span></span><span class=line><span class=cl> <span class=nb>ProxyPass</span> http://127.0.0.1:8888/myapp/
|
|
</span></span><span class=line><span class=cl> <span class=nb>ProxyPassReverse</span> http://127.0.0.1:8888/myapp/
|
|
</span></span><span class=line><span class=cl> <span class=nb>RequestHeader</span> set SCRIPT_NAME <span class=s2>"/myapp/"</span>
|
|
</span></span><span class=line><span class=cl><span class=nt></Location></span>
|
|
</span></span></code></pre></td></tr></table></div></div><p><strong>Important</strong>: <em>SCRIPT_NAME</em> and the end of <em>ProxyPass</em> URL <strong>MUST BE
|
|
THE SAME</strong>. Otherwise, Gunicorn will fail miserably.</p><p>Try it with:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
|
|
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>venv/bin/gunicorn -w <span class=m>4</span> -b 127.0.0.1:8888 --log-file - --access-logfile - wsgi:application
|
|
</span></span></code></pre></td></tr></table></div></div><h2 id=uwsgi>UWSGI</h2><p>This is a very simple configuration. I will try to upload one with more
|
|
options for uwsgi (in a .ini file).</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
|
|
</span><span class=lnt>2
|
|
</span><span class=lnt>3
|
|
</span><span class=lnt>4
|
|
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-apache data-lang=apache><span class=line><span class=cl><span class=nt><Location</span> <span class=s>/myapp/</span><span class=nt>></span>
|
|
</span></span><span class=line><span class=cl> <span class=nb>SetHandler</span> uwsgi_handler
|
|
</span></span><span class=line><span class=cl> <span class=nb>uWSGISocker</span> <span class=m>127.0.0.1</span>:8888
|
|
</span></span><span class=line><span class=cl><span class=nt></Location></span>
|
|
</span></span></code></pre></td></tr></table></div></div><p>Try it with:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
|
|
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>uwsgi --socket 127.0.0.1:8888 -w wsgi:application
|
|
</span></span></code></pre></td></tr></table></div></div><h2 id=extra-supervisor>Extra: Supervisor</h2><p>If everything went as expected, you can wrap your command in a
|
|
supervisor config file and let it handle the server for you.</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt> 1
|
|
</span><span class=lnt> 2
|
|
</span><span class=lnt> 3
|
|
</span><span class=lnt> 4
|
|
</span><span class=lnt> 5
|
|
</span><span class=lnt> 6
|
|
</span><span class=lnt> 7
|
|
</span><span class=lnt> 8
|
|
</span><span class=lnt> 9
|
|
</span><span class=lnt>10
|
|
</span><span class=lnt>11
|
|
</span><span class=lnt>12
|
|
</span><span class=lnt>13
|
|
</span><span class=lnt>14
|
|
</span><span class=lnt>15
|
|
</span><span class=lnt>16
|
|
</span><span class=lnt>17
|
|
</span><span class=lnt>18
|
|
</span><span class=lnt>19
|
|
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-ini data-lang=ini><span class=line><span class=cl><span class=k>[unix_http_server]</span>
|
|
</span></span><span class=line><span class=cl><span class=na>file</span><span class=o>=</span><span class=s>/tmp/myapp.sock ; path to your socket file</span>
|
|
</span></span><span class=line><span class=cl>
|
|
</span></span><span class=line><span class=cl><span class=k>[supervisord]</span>
|
|
</span></span><span class=line><span class=cl><span class=na>logfile</span> <span class=o>=</span> <span class=s>%(here)s/logs/supervisor.log</span>
|
|
</span></span><span class=line><span class=cl><span class=na>childlogdir</span> <span class=o>=</span> <span class=s>%(here)s/logs/</span>
|
|
</span></span><span class=line><span class=cl>
|
|
</span></span><span class=line><span class=cl><span class=k>[rpcinterface:supervisor]</span>
|
|
</span></span><span class=line><span class=cl><span class=na>supervisor.rpcinterface_factory</span> <span class=o>=</span> <span class=s>supervisor.rpcinterface:make_main_rpcinterface</span>
|
|
</span></span><span class=line><span class=cl>
|
|
</span></span><span class=line><span class=cl><span class=k>[supervisorctl]</span>
|
|
</span></span><span class=line><span class=cl><span class=na>logfile</span> <span class=o>=</span> <span class=s>%(here)s/logs/supervisorctl.log</span>
|
|
</span></span><span class=line><span class=cl><span class=na>serverurl</span><span class=o>=</span><span class=s>unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket</span>
|
|
</span></span><span class=line><span class=cl>
|
|
</span></span><span class=line><span class=cl><span class=k>[program:myapp]</span>
|
|
</span></span><span class=line><span class=cl><span class=na>command</span> <span class=o>=</span> <span class=s>venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 --log-file %(here)s/logs/gunicorn.log --access-logfile - wsgi:application</span>
|
|
</span></span><span class=line><span class=cl><span class=na>directory</span> <span class=o>=</span> <span class=s>%(here)s</span>
|
|
</span></span><span class=line><span class=cl><span class=na>environment</span> <span class=o>=</span> <span class=s>PATH=%(here)s/venv/bin/</span>
|
|
</span></span><span class=line><span class=cl><span class=na>logfile</span> <span class=o>=</span> <span class=s>%(here)s/logs/myapp.log</span>
|
|
</span></span></code></pre></td></tr></table></div></div></section><footer class=article-footer><section class=article-tags><a href=/tags/python/>Python</a>
|
|
<a href=/tags/apache/>Apache</a>
|
|
<a href=/tags/proxy/>Proxy</a>
|
|
<a href=/tags/gunicorn/>Gunicorn</a>
|
|
<a href=/tags/uwsgi/>Uwsgi</a></section><section class=article-copyright><svg class="icon icon-tabler icon-tabler-copyright" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><path d="M14.5 9a3.5 4 0 100 6"/></svg>
|
|
<span>Licensed under CC BY-NC-SA 4.0</span></section></footer><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css integrity=sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV crossorigin=anonymous><script src=https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js integrity=sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8 crossorigin=anonymous defer></script><script src=https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js integrity=sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05 crossorigin=anonymous defer></script><script>window.addEventListener("DOMContentLoaded",()=>{const e=document.querySelector(".main-article");renderMathInElement(e,{delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredClasses:["gist"]})})</script></article><footer class=site-footer><section class=copyright>©
|
|
2012 -
|
|
2025 J. Fernando Sánchez</section><section class=powerby>Built with <a href=https://gohugo.io/ target=_blank rel=noopener>Hugo</a><br>Theme <b><a href=https://github.com/CaiJimmy/hugo-theme-stack target=_blank rel=noopener data-version=3.30.0>Stack</a></b> designed by <a href=https://jimmycai.com target=_blank rel=noopener>Jimmy</a></section></footer><div class=pswp tabindex=-1 role=dialog aria-hidden=true><div class=pswp__bg></div><div class=pswp__scroll-wrap><div class=pswp__container><div class=pswp__item></div><div class=pswp__item></div><div class=pswp__item></div></div><div class="pswp__ui pswp__ui--hidden"><div class=pswp__top-bar><div class=pswp__counter></div><button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
|
|
<button class="pswp__button pswp__button--share" title=Share></button>
|
|
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
|
|
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button><div class=pswp__preloader><div class=pswp__preloader__icn><div class=pswp__preloader__cut><div class=pswp__preloader__donut></div></div></div></div></div><div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class=pswp__share-tooltip></div></div><button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
|
|
</button>
|
|
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button><div class=pswp__caption><div class=pswp__caption__center></div></div></div></div></div><script src=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js integrity="sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo=" crossorigin=anonymous defer></script><script src=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js integrity="sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU=" crossorigin=anonymous defer></script><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css crossorigin=anonymous><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css crossorigin=anonymous></main></div><script src=https://cdn.jsdelivr.net/npm/node-vibrant@3.1.6/dist/vibrant.min.js integrity="sha256-awcR2jno4kI5X0zL8ex0vi2z+KMkF24hUW8WePSA9HM=" crossorigin=anonymous></script><script type=text/javascript src=/ts/main.1e9a3bafd846ced4c345d084b355fb8c7bae75701c338f8a1f8a82c780137826.js defer></script><script>(function(){const e=document.createElement("link");e.href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap",e.type="text/css",e.rel="stylesheet",document.head.appendChild(e)})()</script></body></html> |