Pages

12.13.2014

My perfect nginx config

Setting up web servers is a pain in the ass if you don't do it all the time.  I don't.  So I've spent the last few days trying to figure out how to configure nginx.  I have an Amazon AWS instance running a couple of low traffic sites mainly for fun.  One site in particular had some special requirements. 
  • only the index.php file should ever be executed
  • no static files are served from this site (css/html/js)
This site has a couple of composer files in the site root, and I didn't want anyone to just be able to download them.  This site also runs on a framework that uses a "front controller", meaning that one PHP file dispatches and handles all the requests.  So here's the nginx config that I came up with to do just that.

With this configuration, here's what works and what doesn't:
These work as expected:
example.com/
example.com/api/who
example.com/index.php
example.com/index.php/api/who

These are 404ed as they should be:
example.com/composer.lock
example.com/SomePHPFile.php


 server {
        listen 80;

        root /var/www/example;

        server_name example.com;

#direct all traffic to the front controller after trying files
    location / {
        index index.php;
        try_files $uri $uri/ /index.php?$args;
   }


#only redirects to the front controller will be processed.
    location ~ index\.php {
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;

    }


#any path which is an actual file will get a 404
    location ~ (\.[^/]+)$ {
        return 404;
    }

}


8.11.2014

rsync WTF

During the process of setting up my NAS box over the weekend, I discovered a curious thing about rsync.  The options that everyone on the internet seems to use, ("-avz") actually slow down the performance of rsync over LAN.  By slow down, I mean 20 MBps over gigabit ethernet. Theoretically, Gig-E can handle ~125 MBps.   Fortunately, the solution was simple.  Dropping the "z" flag (z enables compression) sped up my transfers to around 70 MBps.  

TLDR; use rsync -av, not rsync -avz

For those interested in the relevant details of my setup: I was using rsync to copy files locally from my Macbook to an SMB  mount point.  I'd also tested the speeds of rsync using the rsync protocol (rather than copying to a mounted volume) and they were equally poky.  NFS didn't fare much better.  It seemed to cap out around 40 MBps.   Strangely, SMB seems to be the fastest protocol for copying files in my setup.  Finder copies files even faster than rsync, pulling around 100 MBps.  My NAS box is a dual core Athlon X2 @3 GHz. I've got 4x 2 TB hard drives in RAID Z2 (RAID6) for a total of 4TB usable storage. 

6.19.2014

Refresh your Android wallpaper

I get sick of looking at the same background on my phone day after day.  (The same goes for my computer.) Interfacelift.com has always been my go to site for really amazing photography fit for desktop wallpapers.  Unfortunately, they don't have an Android app and going to the website all the time on my phone is a pain in the ass.  Enter my solution: Refresh.

Refresh is a stupid simple Android app that brings all the goodness of interfacelift.com to your Android phone (or tablet).   Simply scroll through a list of wallpapers and pick the ones you like.  Download them to your phone, or set them as your background right away.  The latest version of Refresh will automatically cycle through all the wallpapers you've downloaded.  Every time you turn the screen on, you'll be looking at a different wallpaper.

Check it out on the Google Play store.  I'm open to suggestions for new features and of course bug reports.  (I hate ads as much as the next person, but it's not free to use interfacelift.com's API.  I tried to make them as unobtrusive as possible.)



5.03.2014

Beware of commas in For loops

In a C like language, we can declare a for loop as such:
for(pre; condition; post)
where "pre" is something that happens before the loop starts, "condition" is a check that happens before each run of the loop, and "post" happens after each time through the loop. We can get even more fancy and do more than one of each of these. For example, we could have this:
for(pre1, pre2; cond1, cond2; post1, post2)

In this case, "pre1" and "pre2" happen before the loop, "cond1" and "cond2" are evaluated before each run of the loop, and "post1" and "post2" happen after each run of the loop.

Be careful however when placing commas between the conditions.  This may cause unexpected behavior in your program.  When conditions are separated by commas, they are evaluated as OR.  This would be the same as cond1 OR cond2. In my recent C programming adventures, I spent a non-trivial amount of time tracking down this misbehavior. Eventually, I changed the comma to the explicit AND operator and everything worked as expected.  For those interested, the line was as follows:

This causes problems:
for(i = 0; i < index, cur != head; i++, cur = cur->next);
This works the way I want:
for(i = 0; i < index && cur != head; i++, cur = cur->next);

4.01.2014

Two loops you didn't know about

Most of us that program are familiar with a few basic types of loops.  We all know the while loop, the for loop, the "for each" loop and the "do while" loop.   Today you'll learn about two little used loops that are built into many modern languages.  I'll show you the pseudo code for the constructs.

Everybody has written some sort of program that got stuck in an infinite loop.  More than likely you wrote a while loop where the condition never became false.  It's possible to write and infinite "for each" loop, but it just takes more work. If you find yourself needing an infinite "for each" loop, you could instead use the special "for ever" loop construct.  This loop is especially handy when you want to iterate through a list infinitely.  The forever loop will iterate through your collection and start right over at the beginning.

forever ( theList : listItem ) {
    //do some stuff
}

The next obscure loop is similar to a "do while" loop.  The do while loop executes the body of the loop once, evaluates the conditional, and executes the body again until the condition is false.  The "don't while" loop is slightly different.  The don't while loop skips over the body of the loop and evaluates the condition.  If the condition is true, the body of the loop is skipped, until the condition becomes false at which point the loop body executes exactly once.

don't{

      //only executes once
     // after the condition is false

}while(condition)

Next time you're trying to write obscure barely functional code, consider using these special loops.  These loops are a really convenient way to confuse new programmers that look at your code.  Experienced programmers will be equally baffled by your decision to utilize such loops.  Happy April 1st!

3.17.2014

Keep your OSX workspaces in order

As an OSX user I frequently divide my work up into multiple workspaces.  I keep my email and chat program open on one, IDEs in another, and my browser in a third.  This is especially handy when working without a second monitor, because I can effortlessly swipe between workspace without having to click around to find my windows.


This system works really well until OSX decides to help me out by rearranging my workspaces automatically.  Expecting that my IDE is always to the left of my browser workspace, I swipe left only to find that my email and chat windows are now there.  This can get really annoying when I have 5 or 6 workspaces open, as I end up playing hide-and-seek with windows.


Thanks Mission Control, but I don't need your help.
Fortunately, the solution is simple.  Go into System Preferences >> Mission Control and uncheck the option for "Automatically rearrange Spaces based on most recent use".  Now you can arrange your workspaces without OSX trying to outsmart you. 

2.18.2014

I call BS...

A few weeks ago, I bought a pair of jeans from Sears at a local mall.  It has become common practice for retailers to email receipts to customers instead of printing four feet of paper.  Of course, in order to do this, they have to solicit your email address.  And when the cashier asked to my email address, I gave it to her.

In addition to receiving the receipt for my purchase, I was involuntarily signed up for spam.  Over a span of 11 days, I received 6 advertising emails from Sears.  The stupidest thing about the entire situation:  I unsubscribed after the second email.  Why do they keep sending me ads after I've told them I'm no longer interested?

A huge pile of shit
When I clicked the unsubscribe button on the website, I expected to see a message saying that I was unsubscribed and would no longer receive advertising emails.  Instead, Sears showed a popup saying that it would take 7 - 10 days to process my request.  If I weren't a computer science major, I might believe that.  In fact, any logical thinker could figure out that this is just a marketing tactic.

It's highly suspicious of them to quote "7-10 days" to unsubscribe, when it took them about 30 seconds to get me in the system in the first place.  Seriously, my phone was buzzing away with new emails before I reached my car.  I wonder, what about their system causes it to take 20,000 times longer to unsubscribe me for the list than it took to subscribe me in the first place?

Certainly, it's not a technical issue.  I don't know the exact workings of Sears email system, but it wouldn't be unreasonable to think that three or four SQL statements got me in the system.  Unsubscribing should be simpler: I'm thinking one SQL statement ought to drop me from the list.  The last time I checked, it didn't take 7 days to process a SQL command.  Unless they have to send a tech down to the data center to scrub my name off the hard drive with a Q-tip, this practice is inexcusable.

As I've deduced that there's not a technical factor at play here, the logical explanation is that the 7-10 day delay is simply a matter of policy.  This policy only serves one real purpose... to distribute more spam.  From the moment I click unsubscribe to when my name actually goes off the list is a window of opportunity to send me a few more emails.  Admittedly, this a great marketing tactic masquerading as a technical limitation.  It still doesn't make me hate spam any less though.  That four foot receipt might not be so bad after all.

2.08.2014

Making an endless list load smoothly in Android

In my latest Android app endeavor, I needed to create an endless list.  There's no built in class that does this, so I had to create something that would approximate one.  There are plenty of tutorials on the basic ideas behind endless lists, but none of them worked very well for my application.

My app is a viewer for interfacelift.com, which provides high quality wallpaper downloads.  The app displays a list of wallpapers in descending chronological order.  The user can continue scrolling indefinitely (until the site runs out of wallpapers).   The standard way of approaching the infinitely scrolling list tends to be glitchy when the next set of wallpapers loads.  I've come up with a simple solution to solve the glitchy-ness problem.

When the app loads a set of wallpapers, it adds them to an ArrayList, which is displayed by the ListView.  However, the list adapter doesn't know about the new wallpapers until it is explicitly told that the data set has changed with a call to notifyDataSetChanged().  When this happens, the list adapter is forced to update all of the views.  In my app's case, issuing a new view sets the ImageView's drawable to a placeholder, which is almost immediately replaced with the real image.  This causes the entire list to "jerk" when the existing images are updated.


Continue reading to see code solution.