<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Monkey Snatch Banana</title>
 <link href="http://www.monkeysnatchbanana.com/atom.xml" rel="self"/>
 <link href="http://www.monkeysnatchbanana.com/"/>
 <updated>2010-09-02T11:54:56-04:00</updated>
 <id>http://www.monkeysnatchbanana.com/</id>
 <author>
   <name>Monkey Snatch Banana</name>
   <email>sean@monkeysnatchbanana.com</email>
 </author>
 
 
   <entry>
     <title>In Search of Twitter Client Nirvana</title>
     <link href="http://www.monkeysnatchbanana.com/posts/2010/09/02/in-search-of-twitter-client-nirvana.html"/>
     <updated>2010-09-02T00:00:00-04:00</updated>
     <id>http://www.monkeysnatchbanana.com/posts/2010/09/02/in-search-of-twitter-client-nirvana</id>
     <content type="html">&lt;h3&gt;Why I Need A New Twitter Client&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve gone through a number of twitter clients, switching as I&amp;#8217;ve found new features that I consider &amp;#8216;must have&amp;#8217; items. Currently I use &lt;a href=&quot;http://echofon.com&quot;&gt;echofon&lt;/a&gt;. Until today I was happy with it however, I just hit a very large snag.  There are many user streams I&amp;#8217;d like to &amp;#8216;sample&amp;#8217; without adding noise to my main stream; following these streams is out of the question as I&amp;#8217;m only interested in small percentage of their tweets. Lists seem like the perfect mechanism to deal with this problem. I&amp;#8217;ve created a private list called &amp;#8216;dip into&amp;#8217; that I can jump over and scan from time to time without cluttering my main stream of tweets I&amp;#8217;m always interested in. In addition to &amp;#8216;dip into&amp;#8217;, I have a number of other lists for things that I&amp;#8217;m interested in but don&amp;#8217;t consider time sensitive&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.  Unfortunately, Echofon&amp;#8217;s handling of lists is horribly lacking. It only tracks new tweets/last read for the last list you looked at in the last account you had open. This means, I have to remember where I was in most lists I&amp;#8217;ve created; an extreme non-starter. I have come to the conclusion that I either have to stop using lists or replace echofon.&lt;/p&gt;
&lt;h3&gt;Must Have Features&lt;/h3&gt;
&lt;dl&gt;
  &lt;dt&gt;Mac OS X&lt;/dt&gt;
  &lt;dd&gt;I use Mac OS X.&lt;/dd&gt;

  &lt;dt&gt;Multiple Accounts&lt;/dt&gt;
  &lt;dd&gt;I have multiple accounts and need to be able to easily switch between them.&lt;/dd&gt;

  &lt;dt&gt;Threaded Conversations&lt;/dt&gt;
  &lt;dd&gt;Twitter became far more useful to me when I started using a client that supported threading conversations.&lt;/dd&gt;

  &lt;dt&gt;Remember Last Read Tweet Per View&lt;/dt&gt;
  &lt;dd&gt;If the client doesn&amp;#8217;t support remembering the last read tweet and returning you back there, it isn&amp;#8217;t useful it me. It needs to remember the last read tweet in each view I&amp;#8217;m in: main stream by account, lists etc.&lt;/dd&gt;

  &lt;dt&gt;Account Control&lt;/dt&gt;
  &lt;dd&gt;Echofon has a feature I&amp;#8217;ve found to be a massive time saver: Click on an account name and it opens up a side window with a their tweet stream plus controls change lists the account is in along with follow, unfollow, block and report as spam options.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3&gt;Nice To Have Features&lt;/h3&gt;
&lt;dl&gt;
  &lt;dt&gt;Built in Translation&lt;/dt&gt;
  &lt;dd&gt;I follow non-english speakers and it would be nice to be able to press a translate button to see what their non-english tweets are. Bonus points for being able to set specific users to be auto-translated.&lt;/dd&gt;

  &lt;dt&gt;Muting&lt;/dt&gt;
  &lt;dd&gt;Ability to mute a user or hashtag for a period of time&lt;/dd&gt;

  &lt;dt&gt;Saved Searches&lt;/dt&gt;
  &lt;dd&gt;Access to commonly used searches via the client is nice. I tend to do a lot of searches for &lt;em&gt;smalltalk&lt;/em&gt; and &lt;em&gt;clojure&lt;/em&gt; looking for new people to follow.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;Can You Help?&lt;/h3&gt;
&lt;p&gt;If you know of a twitter client that meets my needs, please drop me a line via &lt;a href=&quot;http://www.twitter.com/SeanTAllen&quot;&gt;twitter&lt;/a&gt; or &lt;a href=&quot;mailto:sean@monkeysnatchbanana.com&quot;&gt;email&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; e.g. &lt;a href=&quot;http://twitter.com/SeanTAllen/services&quot;&gt;@SeanTAllen/services&lt;/a&gt;&lt;/p&gt;</content>
   </entry>
 
   <entry>
     <title>Using FastCGI with Nginx and Seaside</title>
     <link href="http://www.monkeysnatchbanana.com/posts/2010/08/17/using-fastcgi-with-nginx-and-seaside.html"/>
     <updated>2010-08-17T00:00:00-04:00</updated>
     <id>http://www.monkeysnatchbanana.com/posts/2010/08/17/using-fastcgi-with-nginx-and-seaside</id>
     <content type="html">&lt;h3&gt;Why FastCGI a.k.a Why Not Reverse Proxy?&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve &lt;a href=&quot;/posts/2010/06/23/reverse-proxying-to-seaside-with-nginx.html&quot;&gt;previously written&lt;/a&gt; about why I prefer reverse proxying to FastCGI. I still believe all those points, however there are certain Seaside deployment situations where FastCGI is currently preferable to reverse proxying. If you are deploying your Seaside application to run on Gemstone&amp;#8217;s &lt;a href=&quot;http://seaside.gemstone.com/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt;&lt;/a&gt; then you should give FastCGI serious consideration. The current swazoo adapter that you use when proxying to &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; is nowhere near as battle tested as the FastCGI adapter. If you want a rock solid deployment, FastCGI will give you much better results than Swazoo.&lt;/p&gt;
&lt;h3&gt;Our Bare Bones Nginx FastCGI configuration&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;worker_processes&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;events&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;worker_connections&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;http&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt;       &lt;span class=&quot;s&quot;&gt;mime.types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;default_type&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;application/octet-stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;upstream&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;seaside&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9003&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/www/glass/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;24&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;26&lt;/span&gt;       &lt;span class=&quot;kn&quot;&gt;error_page&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;403&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@seaside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28&lt;/span&gt;     
&lt;span class=&quot;lineno&quot;&gt;29&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@seaside&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31&lt;/span&gt;       &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fastcgi_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32&lt;/span&gt;       &lt;span class=&quot;kn&quot;&gt;fastcgi_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;seaside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The preceeding bit of code is a mostly bare bones Nginx to &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; FastCGI configuration. There isn&amp;#8217;t a whole lot to it, so I will quickly hit the points of interest:&lt;/p&gt;
&lt;h4&gt;Lines 13-18&lt;/h4&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;upstream&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;seaside&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9003&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Define a named upstream pool called &lt;em&gt;seaside&lt;/em&gt;. The default &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; installation sets up 3 FastCGI listeners on ports 9001 to 9003. You would just add more server entries in the upstream block to have Nginx start using any additional FastCGI listeners that you might setup in &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt;.&lt;/p&gt;
&lt;h4&gt;Line 22&lt;/h4&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/www/glass/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Defines where our static assets like images, css and html are served from. You need to change the definition to a directory you create or create &lt;em&gt;/var/www/glass/&lt;/em&gt; and populate it with your various assets.&lt;/p&gt;
&lt;h4&gt;Lines 24-27&lt;/h4&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;kn&quot;&gt;error_page&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;403&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@seaside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Define a location handler&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; that encompasses everything that matches &amp;#8216;/&amp;#8217;. Any standard uri will match against this location so, you can consider it to be &amp;ldquo;global&amp;rdquo; in scope. Line 26 states that any uri request that would result in an http 403 or 404 response code should be routed to the named location &lt;em&gt;@seaside&lt;/em&gt;. N.B. This named location is not the same as our upstream block. Nginx will process a request as follows:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Check to see if a static asset for the uri exists. If it does, return it.&lt;/li&gt;
		&lt;li&gt;If a static asset doesn&amp;#8217;t exist then either a 403 or 404 error will be generated resulting in handing the uri off to the @seaside location.&lt;/li&gt;
	&lt;/ol&gt;&lt;p&gt;This could also be done as:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;kn&quot;&gt;try_files&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@seaside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Getting into the details of why you would prefer &lt;em&gt;try_files&lt;/em&gt; or &lt;em&gt;error_page&lt;/em&gt; is the subject for another post.&lt;/p&gt;
&lt;h4&gt;Lines 29-33&lt;/h4&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@seaside&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fastcgi_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;fastcgi_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;seaside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Define our named @seaside location that is responsible for handling FastCGI. The &lt;em&gt;include fastcgi_params&lt;/em&gt; directive has Nginx include its standard FastCGI protocol definitions that are installed at &lt;em&gt;/etc/nginx/fastcgi_params&lt;/em&gt;. The &lt;em&gt;fastcgi_pass&lt;/em&gt; directive simply says: &amp;lsquo;pass all uris from this to the servers defined in the &lt;em&gt;seaside&lt;/em&gt; upstream block&amp;rsquo;.&lt;/p&gt;
&lt;h3&gt;Are We Done?&lt;/h3&gt;
&lt;p&gt;Yes. Yes we are. There is plenty more configuration that can be added to make the FastCGI handling more robust ( failovers, timeouts etc ), but that is all you need to get started. I would suggest visiting the &lt;a href=&quot;http://wiki.nginx.org/&quot;&gt;Nginx wiki&lt;/a&gt; to learn about Nginx so you can flesh out your configuration. If you run into issues or need any help, feel free to drop me an email or catch up with me on &lt;a href=&quot;http://www.twitter.com/SeanTAllen&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; See the &lt;a href=&quot;http://wiki.nginx.org/NginxHttpCoreModule#location&quot;&gt;Nginx wiki&lt;/a&gt; for more information on the location directive.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt; Directory indexes&amp;#8217; that don&amp;#8217;t exist like &amp;#8216;/&amp;#8217; will result in a 403; regular files that don&amp;#8217;t exist like &amp;#8216;/welcome&amp;#8217; will result in a 404.&lt;/p&gt;</content>
   </entry>
 
   <entry>
     <title>Reverse Proxying to Seaside with Nginx</title>
     <link href="http://www.monkeysnatchbanana.com/posts/2010/06/23/reverse-proxying-to-seaside-with-nginx.html"/>
     <updated>2010-06-23T00:00:00-04:00</updated>
     <id>http://www.monkeysnatchbanana.com/posts/2010/06/23/reverse-proxying-to-seaside-with-nginx</id>
     <content type="html">&lt;h3&gt;Why Reverse Proxy a.k.a Why Not FastCGI?&lt;/h3&gt;
&lt;p&gt;Transparency.&lt;/p&gt;
&lt;p&gt;FastCGI setups are opaque. You can&amp;#8217;t easily test all aspects of it. Unless you write your own FastCGI client, debugging configuration problems can be very difficult. Lets imagine for a moment that are trying to debug a problem with your application&amp;mdash; the issue might be in the front end server or it might be in the Seaside application server. When you are using FastCGI, all your interactions with your application server are routed through the front end server which acts as a client for you. If you are reverse proxying to your Seaside application running at http://127.0.0.1:8080/, you can fire up lynx&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and hit the application directly. No error from the application? Probably a front end server issue. It might be slightly hyperbolic, but I can&amp;#8217;t count the number of hours of head scratching this has saved me.&lt;/p&gt;
&lt;h3&gt;Reverse Proxying to Seaside Options&lt;/h3&gt;
&lt;p&gt;Now that you have decided that you want to use reverse proxying to your Seaside application, you need to decide between a couple of basic setup options. You can either setup each application on its own subdomain of your domain or you can run multiple applications off the same domain.&lt;/p&gt;
&lt;h4&gt;One Application Per Subdomain&lt;/h4&gt;
&lt;p&gt;Our first example, shows a basic setup for running the counter and multicounter example applications off their own subdomains. With this configuration, you would be able to access the counter example via the uri http://counter.example.com/ and the multicounter example via http://multicounter.example.com/.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;counter.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;rewrite&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;^/&lt;/span&gt;$ &lt;span class=&quot;s&quot;&gt;/examples/counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;proxy_redirect&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/examples/counter&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/examples/counter&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;multicounter.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;proxy_redirect&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/examples/multicounter&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;rewrite&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;^/&lt;/span&gt;$ &lt;span class=&quot;s&quot;&gt;/examples/multicounter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/examples/multicounter&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you&amp;#8217;ve never seen a nginx configuration file before that might be quite a bit to absorb, so lets break it down:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;We setup two virtual servers, one for each application. This is done via the server {} directives that start on lines 1 and 14. Each virtual server is almost identical except counter appears in one and multicounter in the other.&lt;/li&gt;
	&lt;li&gt;Line 3 tells our first server to respond to requests for the host &lt;em&gt;counter.example.com&lt;/em&gt;.&lt;/li&gt;
	&lt;li&gt;Line 5 rewrites http://counter.example.com/ to http://counter.example.com/examples/counter. &lt;em&gt;This change in &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt; isn&amp;#8217;t seen by the client browser&lt;/em&gt;.&lt;/li&gt;
	&lt;li&gt;Line 6 removes /examples/counter from URIs being returned by the counter application.&lt;/li&gt;
	&lt;li&gt;Line 8 sets up an nginx location. It passes the &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt; /examples/counter to a our application server listening on port 8080 of localhost.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Multiple Applications Per Domain&lt;/h4&gt;
&lt;p&gt;For our multiple applications per domain example, we are going to setup example.com to server any of the example Seaside applications. All the example Seaside applications start with their &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt; path with &lt;em&gt;/examples&lt;/em&gt;&amp;mdash; a nicety we will take advantage of.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/examples&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;7&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://127.0.0.1:8080/examples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;8&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The nginx location we setup on line 5, routes anything under &lt;em&gt;/examples&lt;/em&gt; to the same path on our application server. Under this setup, we could access the counter application at http://example.com/examples/counter and multi counter application at http://example.com/examples/multicounter.&lt;/p&gt;
&lt;h3&gt;Complete Nginx Reverse Proxy Server Configuration&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;Building on the &amp;#8216;One Application Per Subdomain&amp;#8217; setup above, lets setup the serving a hypothetical To Do application. Our application will be responsible for serving the site&amp;#8217;s homepage. Nginx will serve any static assets ( css files, images etc ).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;todo.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;  
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/www/todo.example.com/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;try_files&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;proxy_redirect&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;rewrite&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;^/&lt;/span&gt;$ &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;   &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;     &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A quick breakdown of the new elements we&amp;#8217;ve introduced:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Line 5 tells nginx that any static attributes should be located by looking in &lt;em&gt;/var/www/todo.example.com/&lt;/em&gt;. This is equivalent to Apache&amp;#8217;s DocumentRoot directive.&lt;/li&gt;
	&lt;li&gt;The location directive that starts on line 7 defines how nginx should locate static assets&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. The try_files directive on line 9 tells nginx to try to means to satisfy a &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt;. If our incoming request has a path of &lt;em&gt;/about&lt;/em&gt; then, nginx will first look for a file called &lt;em&gt;about&lt;/em&gt; in the server root. If that isn&amp;#8217;t found nginx will look for a directory &lt;em&gt;about/&lt;/em&gt; in the server root. If neither rule can be satisfied, nginx will return a 404 error.&lt;/li&gt;
	&lt;li&gt;Line 15 defines a location rule that is more specific than the one on line 7.  It will only be triggered if the &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt; path is /todo. This is the same setup that we saw in both of our previous examples.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Putting It All Together&lt;/h3&gt;
&lt;p&gt;Now all we have to do is drop our reverse proxy server configuration into our nginx configuration and we end up with something like&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&amp;#8230;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;worker_processes&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;events&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;worker_connections&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;http&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt;       &lt;span class=&quot;s&quot;&gt;mime.types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;default_type&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;application/octet-stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      
  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;todo.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
    &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/www/todo.example.com/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
    &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;try_files&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
    &lt;span class=&quot;kn&quot;&gt;proxy_redirect&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;rewrite&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;^/&lt;/span&gt;$ &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/todo&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;footnote&quot; id=&quot;fn1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; Or any other http client; one of my favorites is &lt;a href=&quot;http://github.com/cloudhead/http-console&quot;&gt;http console&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt; See &lt;a href=&quot;http://wiki.nginx.org/NginxHttpProxyModule&quot;&gt;http://wiki.nginx.org/NginxHttpProxyModule&lt;/a&gt; for complete nginx proxy module documentation. If you are running multiple Seaside application instances ( on &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; for instance ), you should also check out the &lt;a href=&quot;http://wiki.nginx.org/NginxHttpUpstreamModule&quot;&gt;upstream&lt;/a&gt;, &lt;a href=&quot;http://wiki.nginx.org/NginxHttpUpstreamFairModule&quot;&gt;fair upstream&lt;/a&gt; and &lt;a href=&quot;http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule&quot;&gt;upstream_hash&lt;/a&gt; modules.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt; Location / is the most general location rule possible with nginx. It will used if a more specific location can&amp;#8217;t be found.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn4&quot;&gt;&lt;sup&gt;4&lt;/sup&gt; Yours may look radically different. This is just a basic example of a full nginx configuration file.&lt;/p&gt;</content>
   </entry>
 
   <entry>
     <title>Faking a https client for GLASS</title>
     <link href="http://www.monkeysnatchbanana.com/posts/2010/06/22/faking-a-https-client-for-glass.html"/>
     <updated>2010-06-22T00:00:00-04:00</updated>
     <id>http://www.monkeysnatchbanana.com/posts/2010/06/22/faking-a-https-client-for-glass</id>
     <content type="html">&lt;p&gt;So, you are humming along developing your &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; hosted Seaside application. If you are following the proscribed development path, your application is running in Pharo and you&amp;#8217;ve started porting it to &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; when a problem arises:&lt;/p&gt;
&lt;p&gt;Your application needs to make calls out to a secure web service ( merchant processor etc ) but, &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; doesn&amp;#8217;t have a native https client. The Pharo &amp;#8220;cryptography package:&amp;#8221;http://www.squeaksource.com/Cryptography.html implements an https client which you could port to Gemstone, but the process model it uses doesn&amp;#8217;t map nicely and you have better things to do with your time. You could wrap up the &lt;a href=&quot;http://www.openssl.org/&quot;&gt;C OpenSSL library&lt;/a&gt; and access it from Smalltalk&amp;mdash; also a large amount of work or&amp;#8230; you could go for the quick, dirty and effective approach: open a regular http connection and run it through a https proxy. This article covers the last option.&lt;/p&gt;
&lt;h3&gt;Http to Https Proxying&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;http://en.wikipedia.org/wiki/Proxy_server&quot;&gt;proxy server&lt;/a&gt; is &lt;em&gt;a server (a computer system or an application program) that acts as an intermediary for requests from clients seeking resources from other servers.&lt;/em&gt; In our current scenario, our Seaside application will make an http connection to a local proxy that will in turn open a https connection to a remote server passing our info along in the process. In order to accomplish this, we will give a hostname to our proxy and connect to it from our smalltalk code. Lets say you want to use a resource on the server &lt;em&gt;api.secure_service.com&lt;/em&gt;, you need to setup a name for the proxy that does the actual connection to &lt;em&gt;api.secure_service.com&lt;/em&gt;. If proxy is running on your local machine and you want to name it &lt;em&gt;secure_service&lt;/em&gt;, add the following entry to your machine&amp;#8217;s &lt;em&gt;/etc/hosts&lt;/em&gt; file&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;127.0.0.1   secure_service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;From our smalltalk code instead of opening a connection to &lt;em&gt;https://api.secure_service.com/apiLocation&lt;/em&gt;, we will open a connection to &lt;em&gt;http://secure_service/apiLocation&lt;/em&gt;. With this simple code change out of the way, we can move on to setting up the proxy. There are two primary options for doing http to https proxying. Using &lt;a href=&quot;http://stunnel.mirt.net/&quot;&gt;stunnel&lt;/a&gt; or a proxying web server:&lt;/p&gt;
&lt;h4&gt;Stunnel&lt;/h4&gt;
&lt;p&gt;I&amp;#8217;m not going to give an in depth coverage to setting up stunnel as a means of doing outgoing https connections from  &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt;. Why? For any production &lt;span class=&quot;caps&quot;&gt;GLASS&lt;/span&gt; system, we are probably going to be running a web server in front of the swazoo, hyper or fastcgi adapter that is serving your Seaside content; that web server is all you need. If we use stunnel to as a proxy for our http to https connections, we are just adding another point of failure to our setup. By using our existing web server as the proxy, there is less to worry about. If our web server goes down, we aren&amp;#8217;t going to need the https proxying as we have bigger problems.&lt;/p&gt;
&lt;h4&gt;Proxying Web Server&lt;/h4&gt;
&lt;p&gt;We could use &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_proxy.html&quot;&gt;apache&lt;/a&gt;, &lt;a href=&quot;http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxy&quot;&gt;lighttpd&lt;/a&gt; or any other proxying web server to implement the following solution. I&amp;#8217;ll use &lt;a href=&quot;http://www.nginx.org&quot;&gt;nginx&lt;/a&gt; &lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; as it is the server I&amp;#8217;m most comfortable with. We already added a name for our &lt;em&gt;/etc/hosts&lt;/em&gt; and now it is time to add an additional server entry to our nginx.conf file&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;secure_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://api.secure_service.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Restart nginx and we are good to go.&lt;/p&gt;
&lt;h3&gt;Using test resources&lt;/h3&gt;
&lt;p&gt;If we use a build system and the remote service offers production and testing versions, we can get an added bonus from the proxy setup: easy switching at build time between production and testing services.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s assume that &lt;em&gt;secure_service&lt;/em&gt; is a merchant processing provider that provides a test interface where no billing is actually done as well as a production system where transactions are charged to the consumer. Instead of having testing and production objects that change the url we are using, we can have a build system insert the correct url in our nginx.conf file. If we are using a &lt;a href=&quot;http://gcc.gnu.org/onlinedocs/cpp/index.html&quot;&gt;standard c preprocessor&lt;/a&gt; &lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, the following setup and slight nginx.conf change allows us to switch from production to testing at build time rather than relying on switching objects in our smalltalk code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#ifdef PRODUCTION&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define SECURE_SERVICE_URL  production-api.secure_service.com&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define SECURE_SERVICE_URL  testing-api.secure_service.com&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;secure_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://SECURE_SERVICE_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;footnote&quot; id=&quot;fn1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; If we need to access your proxy from multiple machines, using real dns entries for our domain will make maintenance much easier.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt; Normally located in &lt;em&gt;/etc/nginx.conf&lt;/em&gt;.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt; You need to configure nginx at build time to include https support.&lt;/p&gt;
&lt;p class=&quot;footnote&quot; id=&quot;fn4&quot;&gt;&lt;sup&gt;4&lt;/sup&gt; Any preprocessor would do.&lt;/p&gt;</content>
   </entry>
 
   <entry>
     <title>Compress images to speed up your website</title>
     <link href="http://www.monkeysnatchbanana.com/posts/2010/02/01/image-compression-script.html"/>
     <updated>2010-02-01T00:00:00-05:00</updated>
     <id>http://www.monkeysnatchbanana.com/posts/2010/02/01/image-compression-script</id>
     <content type="html">&lt;p&gt;Everyone has heard that you need to compress images on your website to get the best performance, but not everyone knows how. There are a number of programs that can help. If you use linux, I would suggest:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;pngcrush for png&lt;/li&gt;
	&lt;li&gt;jpegtran for jpeg&lt;/li&gt;
	&lt;li&gt;gifsicle for gif&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Debian &amp;amp; Ubuntu both have packages for all 3. Combine with &lt;a href=&quot;http://dl.dropbox.com/u/3649105/compress_images.rb&quot;&gt;the following script&lt;/a&gt; and you are moments away from better site performance:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;find&amp;#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ARGV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\.gif$&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;gifsicle --batch -O2 %s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\.jpe?g$&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;jpegtran -copy none -optimize -outfile %s %s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\.png$&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-crushed&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pngcrush -q -rem alla -brute -reduce %s %s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exists?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;mv &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rm &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Just pass the local filesystem root of your website to the script and it will compress all gif, jpeg and png images that it finds within the website hierarchy.&lt;/p&gt;</content>
   </entry>
 
 
</feed>