<?xml version="1.0" encoding="UTF-8"?>
<rss version='2.0' xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jonathan la Cour</title>
    <description>Full-stack developer. Co-founder at [Hund.io](https://hund.io/).</description>
    <link>https://lacour.silvrback.com/feed</link>
    <atom:link href="https://lacour.silvrback.com/feed" rel="self" type="application/rss+xml"/>
    <category domain="lacour.silvrback.com">Content Management/Blog</category>
    <language>en-us</language>
      <pubDate>Sun, 26 Jun 2016 20:32:07 +0100</pubDate>
    <managingEditor>jon@lacour.me (Jonathan la Cour)</managingEditor>
      <item>
        <guid>http://blog.lacour.me/proxy-protocol-across-nginx-ports-quirck#25637</guid>
          <pubDate>Sun, 26 Jun 2016 20:32:07 +0100</pubDate>
        <link>http://blog.lacour.me/proxy-protocol-across-nginx-ports-quirck</link>
        <title>PROXY Protocol across NGINX Ports Quirck</title>
        <description></description>
        <content:encoded><![CDATA[<p>I noticed an odd quirk while configuring NGINX to accept PROXY protocol headers from a load balancer. I thought I&#39;d share a quick note about using <code>proxy_protocol</code>, and its effects across multiple server directives sharing the same port.</p>

<p>When using <code>proxy_protocol</code>, it&#39;s enabled for all server directives that share the same port. Take for example the following configuration:</p>
<div class="highlight"><pre><span></span><span class="k">server</span> <span class="p">{</span>
  <span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
  <span class="kn">server_name</span> <span class="s">_</span><span class="p">;</span>

  <span class="kn">allow</span> <span class="mi">172</span><span class="s">.31.0.0/32</span><span class="p">;</span>

  <span class="kn">location</span> <span class="s">/health</span> <span class="p">{</span>
    <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span>
    <span class="kn">add_header</span> <span class="s">Content-Type</span> <span class="s">text/plain</span><span class="p">;</span>
    <span class="kn">return</span> <span class="mi">200</span> <span class="s">&quot;OK&quot;</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="k">server</span> <span class="p">{</span>
  <span class="kn">listen</span> <span class="mi">80</span> <span class="s">proxy_protocol</span><span class="p">;</span>
  <span class="kn">server_name</span> <span class="s">example.com</span><span class="p">;</span>

  <span class="kn">location</span> <span class="s">/</span> <span class="p">{</span>
    <span class="kn">return</span> <span class="mi">301</span> <span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p><code>example.com:80</code> has <code>proxy_protocol</code> enabled, thus enabling <code>proxy_protocol</code> on all port 80 requests. Requests to the former <code>/health</code> path would return a 400 Bad Request since it&#39;s expecting a PROXY protocol header that isn&#39;t there for AWS ELB health checks.</p>

<p>This can be mitigated by using a different port for server directives (in this case, we&#39;d have our health check server block use port 8080, for example).</p>
]]></content:encoded>
      </item>
      <item>
        <guid>http://blog.lacour.me/making-slack-night-mode#21578</guid>
          <pubDate>Fri, 22 Jan 2016 04:27:09 +0000</pubDate>
        <link>http://blog.lacour.me/making-slack-night-mode</link>
        <title>Making Slack Night Mode</title>
        <description></description>
        <content:encoded><![CDATA[<p><strong>Update Jan 22, 2016:</strong> Slack has fixed this vulnerability, in under 24 hours! This means the solution in this article about using Slack Night Mode on Slack&#39;s desktop applications is no longer viable.</p>

<hr>

<p>As with other companies, Slack is a valuable communication tool for us at Hund. Using integrations helps centralize notifications from services like GitLab, Sentry, DeployBot, Datadog, etc. It&#39;s no longer necessary to have tabs open for each of these services while developing, as any relevant information is sent to Slack. <a href="https://twitter.com/apaprocki/status/690427462795317248">But, there is still one issue that many people face with Slack: its lack of a night mode/dark theme.</a></p>

<p>Before going further, I should mention that I&#39;m a huge fan of <a href="https://justgetflux.com/">f.lux</a> and <a href="http://jonls.dk/redshift/">Redshift</a> due to the <a href="http://www.pnas.org/content/112/4/1232.abstract">benefits</a> they offer. These applications are a life-changer for developers who find themselves groggy upon waking up after working late. Still, bright-white pages like Slack can be annoying to have open on a second monitor when chatting or developing.</p>

<p>It would be impractical for Slack to focus on adding a night mode. Such a change would require significant refactoring of their enormous stylesheets, all for a minor feature that many people wouldn&#39;t care about. Although they&#39;ve stated it&#39;s a &quot;<a href="https://twitter.com/SlackHQ/status/622868653248245760">future possibility</a>&quot;, as well as having been a highly requested feature since 2014, I doubt we&#39;ll see something like this for some time.</p>

<h1 id="making-my-own-solution">Making my own solution</h1>

<p><img alt="Slack Night Mode" src="https://silvrback.s3.amazonaws.com/uploads/59bc41a5-54b1-4041-9d4d-2f2688f7a8b3/slck_large.png" /></p>

<p>Since 2014, I&#39;ve maintained a <a href="https://en.wikipedia.org/wiki/Stylish">Stylish</a> style named <a href="https://userstyles.org/styles/101971/slack-night-mode">Slack Night Mode</a>. I&#39;ve refactored everything I wrote, switching from a single CSS file, branching out to what is now <a href="https://github.com/laCour/slack-night-mode/tree/master/scss">over 50 Sass files</a>. Recently, I switched from Slack&#39;s primary aubergine color, to a <a href="https://userstyles.org/styles/117475/slack-night-mode-black">more practical black color</a> which quickly overtook the original in popularity.</p>

<p>One issue I ran into was how large the style had grown. Userstyles.org (a Stylish theme repository) has a large 100KB limit for themes, so I was rather shocked when I met that limit. I still needed to expand the style to support larger Slack features (like their <a href="http://slackhq.com/post/130081834025/refreshing-posts-20">post editor</a>). Jason, the owner of Userstyles kindly lifted the limit so I could continue.</p>

<p>So a solution already exists, for the browser. But what about the popular desktop application?</p>

<h1 id="supporting-the-desktop-application">Supporting the desktop application</h1>

<p>For those unaware, Slack uses <a href="http://electron.atom.io/">Electron</a> to package applications. Electron lets you develop native desktop applications using web technologies. Going into this, I knew this was going to be a bit challenging considering how Slack doesn&#39;t open source their desktop application. This wouldn&#39;t be as simple as changing the source.</p>

<h2 id="a-temporary-solution">A temporary solution</h2>

<p>I do have experience with Electron, so being familiar with it helped me know what to look for. As such, I looked for a way to enable the application&#39;s developer tools (because Electron uses Chromium). Slack&#39;s desktop application will enable them if the <code>SLACK_DEVELOPER_MENU</code> environment variable is set.</p>

<p>With these developer tools, I could attempt to inject the style into the chat&#39;s <a href="https://github.com/atom/electron/blob/master/docs/api/web-view-tag.md">webview</a>. Now, I can&#39;t just include the styles in a stylesheet link tag, as Stylish requires some Mozilla-specific domain constraints, so none of the styles would even load. What I needed to do was strip this constraint from the stylesheet, then inject the CSS. I ended up with this:</p>
<div class="highlight"><pre><span></span><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
  <span class="nx">url</span><span class="o">:</span> <span class="s2">&quot;https://cdn.rawgit.com/laCour/slack-night-mode/master/css/black.css&quot;</span><span class="p">,</span>
  <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">css</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;style&gt;&lt;/style&gt;&quot;</span><span class="p">).</span><span class="nx">appendTo</span><span class="p">(</span><span class="s2">&quot;head&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">css</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">35</span><span class="p">).</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">));</span>
  <span class="p">}</span>
<span class="p">});</span>
</pre></div>
<p>This is run on the chat&#39;s webview, not the containing frame. If this were run on the containing frame, we&#39;d need to send it to the webview as a string to <code>eval</code> by using <code>executeJavaScript</code>.</p>

<h2 id="persisting-the-change">Persisting the change</h2>

<p>This is the tricky part. It shouldn&#39;t be possible to persist a client-side change that&#39;s executed only once. I immediately assumed that it wouldn&#39;t be possible to do this, so I looked for other ways in the package&#39;s source. Eventually I came across Slack&#39;s deep link URI handler, which handles <code>slack:</code> protocol links. This grabbed my attention as a simple way to (<em>hopefully</em>) inject styles upon each run regardless of the platform.</p>

<p>Suffice it to say Slack parses our deep link and creates a JSON object with the desired information to provide to the chat&#39;s webview. This JSON object is stringified, URI encoded, then base64 encoded (in the <code>executeJavaScript</code> function of the <code>SlackWebViewContext</code> class). This is then sent to the webview by means of the built-in <code>executeJavaScript</code>:</p>
<div class="highlight"><pre><span></span><span class="c1">// NB: This is a secret handshake with the embedded page</span>
<span class="k">this</span><span class="p">.</span><span class="nx">wv</span><span class="p">.</span><span class="nx">executeJavaScript</span><span class="p">(</span><span class="s1">&#39;window.rendererEvalAsync(\&quot;${btoa(encodeURIComponent(JSON.stringify(msg)))}\&quot;)&#39;</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">ret</span><span class="p">;</span>
</pre></div>
<p>Now, let&#39;s take a closer look at <code>window.rendererEvalAsync</code>... immediately we see something of concern (this is in the context of the chat webview):</p>
<div class="highlight"><pre><span></span><span class="nx">data</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">atob</span><span class="p">(</span><span class="nx">blob</span><span class="p">)));</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">code</span><span class="p">);</span>
</pre></div>
<p>Well hello there, <code>eval</code>. Nice to meet you. Don&#39;t mind if I do:</p>

<h3 id="a-solution">A solution</h3>

<h4 id="linux">Linux</h4>
<div class="highlight"><pre><span></span>slack <span class="s2">&quot;slack://?s=&#39;);jQuery.ajax({url:&#39;https://cdn.rawgit.com/laCour/slack-night-mode/master/css/black.css&#39;,success:function(e){jQuery(&#39;&lt;style&gt;&lt;/style&gt;&#39;).appendTo(&#39;head&#39;).html(e.slice(35).slice(0,-2))}});//&quot;</span>
</pre></div>
<p>I recommend putting this in a user application desktop entry. <code>cp /usr/share/applications/slack ~/.local/share/applications/</code> will get you started.</p>

<h4 id="mac">Mac</h4>

<p>No Electron here. :(</p>

<h4 id="windows">Windows</h4>
<div class="highlight"><pre><span></span>C:\Users\-\AppData\Local\slack\Update.exe --processStart slack.exe --process-start-args &quot;slack://?s=&quot;&#39;);jQuery.ajax({url:&#39;https://cdn.rawgit.com/laCour/slack-night-mode/master/css/black.css&#39;,success:function(e){$(&#39;style&#39;).append(e.slice(35).slice(0,-2))}});//&quot;
</pre></div>
<p>To persist this, make a <code>.bat</code> file.</p>

<h1 id="conclusion">Conclusion</h1>

<p>So, I doubt this will be possible for much longer given what is being done here. But regardless, enjoy, and give your eyes a break.</p>
]]></content:encoded>
      </item>
  </channel>
</rss>