<?xml version="1.0" encoding="UTF-8"?><rss 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" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[robertglynn.info]]></title><description><![CDATA[My musings on the world.]]></description><link>http://www.robertglynn.info/</link><image><url>http://www.robertglynn.info/favicon.png</url><title>robertglynn.info</title><link>http://www.robertglynn.info/</link></image><generator>Ghost 2.11</generator><lastBuildDate>Mon, 22 Jul 2019 18:40:42 GMT</lastBuildDate><atom:link href="http://www.robertglynn.info/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Azure, Concrete5, and the HTTPS mystery]]></title><description><![CDATA[<p>As a general rule, I try to avoid painful experiences, but in this case the experience was thrust upon me. I was given two Concrete5 websites to migrate to Azure. </p><p>I'm comfortable running my own Linux server, but I'm the only one on my team that is so. Running PHP</p>]]></description><link>http://www.robertglynn.info/azure-concrete5-and-the-https-mystery/</link><guid isPermaLink="false">5cab7b2090d9a30001acb79a</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Mon, 08 Apr 2019 23:12:00 GMT</pubDate><content:encoded><![CDATA[<p>As a general rule, I try to avoid painful experiences, but in this case the experience was thrust upon me. I was given two Concrete5 websites to migrate to Azure. </p><p>I'm comfortable running my own Linux server, but I'm the only one on my team that is so. Running PHP on Windows is best avoided if possible, and wasn't cost-effective when compared to running as App Services. We had tested running one of the sites on a Linux-based App Service versus a Windows-based App Service, and found the Linux-based service had a significant performance advantage, as measured by response time to the browser.</p><p>While we're on the subject of performance, I did not find the performance of Concrete5 to be satisfactory. Both sites are pretty basic brochureware. Some text, images, navigation; a single "contact us" form. Yet, reviewing the database query log for a single page showed 762 database queries. <em>Seven-hundred-sixty-two. Individual queries. One page requested, one time.</em> The action to take here, proposed on the Concrete5 forums and elsewhere by developers building sites with C5, is to enable caching. This does produce a snappy site, as pages are simply served from an on-disk cache instead of constructed from data, but this means you've got to tussle with reconstructing the cache as part of your publishing workflow. I've not had similar problems using WordPress, and maybe either the sites I was given (from two different developers) were poorly implemented, or they're two different use-cases, but either way I'd recommend WP over C5 in cases like this.</p><figure class="kg-card kg-image-card"><img src="http://www.robertglynn.info/content/images/2019/04/Single-Concrete5-Page-Load-Queries.png" class="kg-image"><figcaption>Single-page request queries in a Concrete5 site&nbsp;</figcaption></figure><p>In the end though, the fault did not lie solely with Concrete5, Microsoft's Azure cloud service was also to blame.</p><p>What was happening, is that when a request came in, C5 was checking to see if the site was being served over HTTPS; and it was. Sort of. The requests were being made to the server and responses back to the client over HTTPS. However, behind the scenes, Azure accepted our request and then via its Application Request Routing scheme, routes the request to our code. As part of that proxying, it changes to HTTP.</p><p>An HTTPS header is not set<br>An HTTP_X_ARR_SSL header is set to the SSL info<br>An HTTP_X_FORWARDED_PROTO is set to the value "https"<br>A REQUEST_SCHEME header is set to "http"<br>A SERVER_PORT header is set to "80"</p><figure class="kg-card kg-image-card"><img src="http://www.robertglynn.info/content/images/2019/04/Azure-SSL-Headers.jpg" class="kg-image"><figcaption>Headers coming in to a Linux Azure Web Service</figcaption></figure><p>If your application is checking for a header other than HTTP_X_FORWARDED_PROTO, then it will not correctly detect the URL scheme the request was made via. This is not clearly documented by Microsoft; I happened upon it in a Stack Overflow answer: (<a href="https://stackoverflow.com/a/38726543/248917">https://stackoverflow.com/a/38726543/248917</a>).</p><p>Concrete5 builds page content URLs using the scheme and domain info from the incoming request. It checks for an HTTPS header, only checks the HTTP_X_FORWARDED_PROTO in the event a "trusted proxy" is set, and uses that to write the scheme for URLs on the page (see <em>/concrete/vendor/symfony/http-foundation/Request.php</em>). Personally, I'd prefer if URLs were written to the page scheme-less; forcing https-everywhere at the site level would enforce security. </p><p>Setting up a C5 site on an Azure Web Service resource with an SSL binding causes pages to be served back to the client over HTTPS, but URLs on the page, including form actions, are written with an HTTP scheme; with an SSL-rewrite rule on the server, C5 forms will not be processed correctly - you won't be able to log in to the admin section, for example.</p><p>My solution, while probably not the best, was to add the following code to index.php in the site root:</p><pre><code>if(isset($_SERVER['HTTP_X_ARR_SSL'])) {
    $_SERVER['HTTPS'] = 'on';
}</code></pre>
]]></content:encoded></item><item><title><![CDATA[Virtual Machine - An Exercise in Development - Part 3]]></title><description><![CDATA[<p>I'm currently developing on a Mac, at least for open-source development, and I'm going to do all of the development for this excercise utilizing a virtual machine for the hosting environment. While it's certainly possible to do all development entirely on a Mac, I find it can lead to issues</p>]]></description><link>http://www.robertglynn.info/virtual-machine-an-exercise-in-development-part-3/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8842</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Thu, 12 Apr 2018 23:10:49 GMT</pubDate><content:encoded><![CDATA[<p>I'm currently developing on a Mac, at least for open-source development, and I'm going to do all of the development for this excercise utilizing a virtual machine for the hosting environment. While it's certainly possible to do all development entirely on a Mac, I find it can lead to issues and conflicts and we can avoid most issues by using a VM.</p>
<p>I've done this before, a bit differently, with the files living on the Mac, and utilizing PHPStorm to SCP files to the VM on save for testing/hosting, but this time I'm going to utilize a samba share with inspiration from <a href="https://gist.github.com/fideloper/2879466">https://gist.github.com/fideloper/2879466</a>.</p>
<p>I'll enumerate out the steps, and maybe I'll come back and add more detail, but this page is (at least not currently) a complete guide to setup.</p>
<h3 id="steps">Steps</h3>
<p>I'm not going to go into everything done to set up a virtual machine; I'm using VMWare Fusion 10 and the gues OS is CentOS 7. I'll enumerate some of the steps taken as well as anything unique to this process.</p>
<ul>
<li>Create virtual machine via installation media</li>
<li>Configure VM (standard housekeeping)
<ul>
<li>set static IP address (192.168.180.112)
<ul>
<li>set gateway, DNS</li>
</ul>
</li>
<li>install wget</li>
<li>install nano</li>
<li>install EPEL</li>
<li>install cron</li>
<li>install at</li>
<li>install screen</li>
<li>install NTP
<ul>
<li>synchronize clock</li>
<li>start ntpd, run at startup</li>
</ul>
</li>
<li>create a user to replace root login
<ul>
<li>enable sudo add user to wheel</li>
</ul>
</li>
<li>change default SSH port</li>
<li>disable root SSH login</li>
<li>add user to SSH</li>
<li>install firewalld
<ul>
<li>allow ssh on new port</li>
<li>allow localhost</li>
<li>alllow http, https, smtp</li>
</ul>
</li>
</ul>
</li>
<li>Create directory</li>
<li>Install nginx</li>
</ul>
<p>That will get us a machine we can develop against. Now to be able to utilize it.</p>
<h4 id="ondevserver">On dev server</h4>
<ul>
<li>install samba</li>
<li>set up a share pointing at our directory created previously (/var/www/eid)</li>
<li>allow samba via firewall-cmd</li>
<li>add our user to samba users</li>
</ul>
<h4 id="onmac">On Mac</h4>
<p>Finder -&gt; Go -&gt; Connect To Server<br>
Add in our server address 192.168.180.112<br>
Connect</p>
<p>Now that we've spent a day searching for solutions for all of the above steps, we're ready to start development.</p>
]]></content:encoded></item><item><title><![CDATA[Strategy - An Exercise in Development - Part 2]]></title><description><![CDATA[<p>In any project such as this, creating or updating a website with no limitations (except perhaps financial), one of the juciest parts is choosing the tech stack. There are lots of reasons and justifications for why we'd pick one thing over another; and no doubt any choice made could be</p>]]></description><link>http://www.robertglynn.info/strategy-an-exercise-in-development-part-2/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8841</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Wed, 14 Feb 2018 22:23:11 GMT</pubDate><content:encoded><![CDATA[<p>In any project such as this, creating or updating a website with no limitations (except perhaps financial), one of the juciest parts is choosing the tech stack. There are lots of reasons and justifications for why we'd pick one thing over another; and no doubt any choice made could be debated. In fact, having a strongly-held opinion about a particular technology is one of the attributes I most value in a developer - it means you care about what you're working with.</p>
<p>So, let's go through the choices I've made for this project, and some of the thought behind those choices.</p>
<h3 id="nodejs">Node.js</h3>
<p>The storesdowntown.com site is already on Node. I really like it as a platform for hosting web sites and services; I enjoy working with JavaScript; and there's already more than enough that's new and changing as part of this project, no need to pick something else here.</p>
<h3 id="express">Express</h3>
<p>The site we're replacing uses <a href="http://www.robertglynn.info/strategy-an-exercise-in-development-part-2/Sails.js">https://sailsjs.com/</a> , which is based off Express. I really like Sails, and would use it in the future, but I feel it obscures some of the lower-level aspects of using Node and Express. I so very briefly considered a switch to Koa or Hapi, but there's not enough of a reason for it not to wait for another project.</p>
<h3 id="mongodb">MongoDB</h3>
<p>The first version of the site is running on MySQL, and it's worked quite well. The data model for the site is for now, and the foreseeable future, simple enough that any modern data storage solution would suffice. I'm picking Mongo as I've had little opportunity to work with it in the past. Also, picking the most popular NoSQL database is likely not a bad choice.</p>
<h3 id="react">React</h3>
<p>I definitely wanted to use this project as a springboard into single page applications with a focus on SEO. We've adopted Angular as the SPA framework of choice at my day job and while this was pretty much a coin-toss between Angular and React, I'm going to try and expand my horizons even further with this project and see on which side of the coin I'd prefer to be on.</p>
<h3 id="amazonaws">Amazon AWS</h3>
<p>storesdowntown.com was initially published on an instance of CentOS running Nginx. Hosting was procured from <a href="http://www.robertglynn.info/strategy-an-exercise-in-development-part-2/openvirtuals.com">https://openvirtuals.com/</a> and has been a good experience. I'm going to continue running other sites and services there, but in the interest of staying up-to-date (the whole purpose of this exercise), we're moving to a cloud hosting provider.</p>
<p>I'll continue to do development on a Mac with the actual development server as a VMWare Fusion-hosted CentOS instance. I find developing full stack natively that eventually you run into a conflict.</p>
<h3 id="docker">Docker</h3>
<p>We probably won't be utilizing Docker to its potential on a simple project like this, but I'm trying to define a set of best practices for myself as part of this and containerization definitely falls into that.</p>
<h3 id="jenkins">Jenkins</h3>
<p>For CI/CD, I only considered three options: Jenkins, Circle CI, and Strider. I'm using Jenkins and Circle CI on other projects, and between those two I'd choose Jenkins, mostly based on cost and popularity. Of the CI/CD tools out there, the only one that caught my attention was Strider, as it's based on Node. I think I'll stick with Jenkins for the time being though.</p>
<h3 id="github">Github</h3>
<p>Source control is not even up for debate, even though I'm the only one working on this project. Of all the source control sytems I've used, I actually like Mercurial the best, but Git is a close second and the clear frontrunner in the space.</p>
<p>I've been using <a href="http://www.robertglynn.info/strategy-an-exercise-in-development-part-2/repositoryhosting.com">http://repositoryhosting.com/</a> for my personal repos up until now, but I'm using Github everywhere else, so let's use this opportunity to transition to that.</p>
<h3 id="scssandbem">SCSS and BEM</h3>
<p>Like Mercurial and Git, I actually prefer Stylus over SCSS (or, at least I did last time I used both concurrently), but the other (SCSS in this case) is wildly more popular, and I use it on other projects.</p>
<p>The only reason I mention this here, and haven't explicitly called out other tech choices, like Webpack, et. al, is that I want to bring attention to using BEM. BEM stands for Block, Element, Modifier, and is a stylistic choice when writing CSS. The best explanation I've found is in [<a href="https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/">https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/</a>](MindBEMding – getting your head ’round BEM syntax). I've used it on another project, and definitely appreciate it.</p>
<p>Whew! There's a lot in this post, but I wanted to get my stack choices and rationale written down - this is more important than you think. How many times have you worked on a project long after decisions were made and can't remember why those choices were made in the first place? I'm sure there's lots to disagree with here, but I'm not trying to say these are the best, only the best for me on this project. Whether that means they're the best overall, really is up to the individual. Let's move on to some hands-on work.</p>
]]></content:encoded></item><item><title><![CDATA[An Exercise in Development]]></title><description><![CDATA[<p>As I feel happens to any good developer, the work you perform on a day-to-day basis is more often than not applying existing skills to legacy applications. That is to say, your day job is not constantly updating technology.</p>
<p>In order to stay current, and relevant, there's got to be</p>]]></description><link>http://www.robertglynn.info/an-exercise-in-development/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8840</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Wed, 17 Jan 2018 23:07:02 GMT</pubDate><content:encoded><![CDATA[<p>As I feel happens to any good developer, the work you perform on a day-to-day basis is more often than not applying existing skills to legacy applications. That is to say, your day job is not constantly updating technology.</p>
<p>In order to stay current, and relevant, there's got to be time you spend on projects that take you out of your daily work's stack. To try and achieve this, I'm going to take an existing application I've got in production <a href="http://www.storesdowntown.com">storesdowntown.com</a> . Often the most difficult hurdle to jump in a project like this, which is done mostly for educational purposes, is the idea of what application to build. Using something that already exists makes things easier and has the added benefit that I'll end up with an upgraded site.</p>
<p>I'll also document the whole thing here; it's primarily for my notes, but if making them public helps someone else, or brings a valuable opinion from a peer, then that's great.</p>
]]></content:encoded></item><item><title><![CDATA[Handling naming conflicts in javascript libraries]]></title><description><![CDATA[<p>When using code or plugins written by third parties, a programmer may encounter naming collisions. This condition is produced by two pieces of code attempting to give the same name to two different objects. As an example, I&#39;ve personally come across a conflict between jQuery.ui and jQuery.</p>]]></description><link>http://www.robertglynn.info/handling-naming-conflicts-in-javascript-libraries/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8834</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Mon, 04 Sep 2017 23:52:11 GMT</pubDate><content:encoded><![CDATA[<p>When using code or plugins written by third parties, a programmer may encounter naming collisions. This condition is produced by two pieces of code attempting to give the same name to two different objects. As an example, I&#39;ve personally come across a conflict between jQuery.ui and jQuery.tools. Both libraries contain a jQuery function named &quot;tabs.&quot; The solution I came up with is to rename one of the conflicting functions.</p>
<p>In javascript, all objects are associative arrays. That is to say, each method or property an object contains can be thought of as a key-value pair. So window.location.href can be expressed as window[location][href], where location is the key name of an object inside the window object and href is the key name of an object inside the location object. In the third party libraries I was using, both tried to create an object named &quot;tabs&quot; inside the jQuery.fn object.</p>
<p>Each plugin tried this:</p>
<pre class="brush: js;">
$.fn.tabs = function(some, parameters) {/* plugin code goes here */}
</pre>
<p>Where "$" is shorthand for jQuery.</p>
<p>What happens is that the included javascript is parsed in order and the last statement to define &quot;tabs&quot; via &quot;$.fn.tabs = X&quot; sets the value of &quot;tabs.&quot; If we understand this, we can leverage it to solve our problem. What I did was to create a new jQuery function and assign the value of one of the conflicting functions to this new object.</p>
<p>Create a js file (I named mine fixTabs.js), and include the following:</p>
<pre class="brush: js;">
$.fn.uitabs = $.fn.tabs;
delete $.fn.tabs;
</pre>
<p>What this does is takes the tabs() function already defined by the first library included and renames it. When the second library defines the tabs() function the first is kept under it&#39;s new name (in this case &quot;uitabs&quot;, but it can be named whatever you like).</p>
<p>You must include the fix js file between the script tags of the two libraries and remember that the first will be renamed. In this example I am first including the jQuery.ui library, then the fix script, then the jQuery.tools library.</p>
<p>You can then call:</p>
<pre class="brush: js;">
$("#tabs").uitabs(); <!--$.ui.tabs-->
$(".tabs").tabs(); <!--$.tools.tabs-->
</pre>]]></content:encoded></item><item><title><![CDATA[About]]></title><description><![CDATA[<p>I'm a web developer currently living in New York.</p>
<p>I spend most of my free time with family or developing personal projects.</p>]]></description><link>http://www.robertglynn.info/about/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8833</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Mon, 04 Sep 2017 23:51:35 GMT</pubDate><content:encoded><![CDATA[<p>I'm a web developer currently living in New York.</p>
<p>I spend most of my free time with family or developing personal projects.</p>
]]></content:encoded></item><item><title><![CDATA[Microsoft mouse slow on OSX Sierra]]></title><description><![CDATA[<p>In order to run my preferred mouse, the very comfortable <a href="https://www.amazon.com/Microsoft-Sculpt-Ergonomic-Mouse-L6V-00001/dp/B00D68ZVY8">Microsoft Sculpt Ergonomic Mouse (L6V-00001)</a>, I had installed Smoothmouse to adjust acceleration. This had worked fine, even under Sierra, but not after an update bringing me to 10.12.4.</p>
<p>After the update, the mouse was moving extremely slowly. The</p>]]></description><link>http://www.robertglynn.info/microsoft-mouse-slow-on-osx-sierra-2/</link><guid isPermaLink="false">5c48bd9b3142fa00016a883c</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Wed, 19 Apr 2017 15:02:30 GMT</pubDate><content:encoded><![CDATA[<p>In order to run my preferred mouse, the very comfortable <a href="https://www.amazon.com/Microsoft-Sculpt-Ergonomic-Mouse-L6V-00001/dp/B00D68ZVY8">Microsoft Sculpt Ergonomic Mouse (L6V-00001)</a>, I had installed Smoothmouse to adjust acceleration. This had worked fine, even under Sierra, but not after an update bringing me to 10.12.4.</p>
<p>After the update, the mouse was moving extremely slowly. The fix was removing the Smoothmouse driver, using an <a href="http://smoothmouse.com/">uninstaller provided by Smoothmouse.</a></p>
]]></content:encoded></item><item><title><![CDATA[Handling naming conflicts in javascript libraries]]></title><description><![CDATA[<p>When using code or plugins written by third parties, a programmer may encounter naming collisions. This condition is produced by two pieces of code attempting to give the same name to two different objects. As an example, I&#39;ve personally come across a conflict between jQuery.ui and jQuery.</p>]]></description><link>http://www.robertglynn.info/handling-naming-conflicts-in-javascript-libraries-2/</link><guid isPermaLink="false">5c48bd9b3142fa00016a8838</guid><dc:creator><![CDATA[Robert M Glynn]]></dc:creator><pubDate>Wed, 14 May 2008 20:35:00 GMT</pubDate><content:encoded><![CDATA[<p>When using code or plugins written by third parties, a programmer may encounter naming collisions. This condition is produced by two pieces of code attempting to give the same name to two different objects. As an example, I&#39;ve personally come across a conflict between jQuery.ui and jQuery.tools. Both libraries contain a jQuery function named &quot;tabs.&quot; The solution I came up with is to rename one of the conflicting functions.</p>
<p>In javascript, all objects are associative arrays. That is to say, each method or property an object contains can be thought of as a key-value pair. So window.location.href can be expressed as window[location][href], where location is the key name of an object inside the window object and href is the key name of an object inside the location object. In the third party libraries I was using, both tried to create an object named &quot;tabs&quot; inside the jQuery.fn object.</p>
<p>Each plugin tried this:</p>
<pre class="brush: js;">
$.fn.tabs = function(some, parameters) {/* plugin code goes here */}
</pre>
<p>Where "$" is shorthand for jQuery.</p>
<p>What happens is that the included javascript is parsed in order and the last statement to define &quot;tabs&quot; via &quot;$.fn.tabs = X&quot; sets the value of &quot;tabs.&quot; If we understand this, we can leverage it to solve our problem. What I did was to create a new jQuery function and assign the value of one of the conflicting functions to this new object.</p>
<p>Create a js file (I named mine fixTabs.js), and include the following:</p>
<pre class="brush: js;">
$.fn.uitabs = $.fn.tabs;
delete $.fn.tabs;
</pre>
<p>What this does is takes the tabs() function already defined by the first library included and renames it. When the second library defines the tabs() function the first is kept under it&#39;s new name (in this case &quot;uitabs&quot;, but it can be named whatever you like).</p>
<p>You must include the fix js file between the script tags of the two libraries and remember that the first will be renamed. In this example I am first including the jQuery.ui library, then the fix script, then the jQuery.tools library.</p>
<p>You can then call:</p>
<pre class="brush: js;">
$("#tabs").uitabs(); <!--$.ui.tabs-->
$(".tabs").tabs(); <!--$.tools.tabs-->
</pre>]]></content:encoded></item></channel></rss>