May 09th, 2011
Stop Rails trying to parse the POST / PUT request body
Topics: Rails, Ruby, HowtoRails 3 has a nice feature where it will parse the body of PUT and POST requests depending on the Content-type given. So for example if I POST XML to Rails it will all be decoded for me and put into the params hash.
Well it's a nice feature until you try to switch it off, it's a nightmare to disable! I managed it in the end, here's what I did.
Created a piece of 'rack middleware' that overwrites the Content-Type for given paths:
# lib/no_parse.rb
class NoParse
def initialize(app, options={})
@app = app
@urls = options[:urls]
end
def call(env)
env['CONTENT_TYPE'] = 'text/plain' if @urls.include? env['PATH_INFO']
@app.call(env)
end
end
Included it:
#config/application.rb require_relative '../lib/no_parse'
Added it into the 'stack':
#config/initializers/no_parse.rb
# (Change the :urls to specify which paths use NoParse.)
Rails.configuration.middleware.insert_before('ActionDispatch::ParamsParser',
'NoParse', :urls => ['/example-path'])
Make sure you restart rails and you should be good to go. If it's not working make sure the rake middleware command is listing the NoParse class above ActionDispatch::ParamsParser.
Cheers, Dave.
January 26th, 2011
Fixing an autoload 'uninitialized constant' NameError
Topics: Ruby, HowtoI ran into a spot of bother getting some Ruby code to work, I kept getting a uninitialized constant NameError on the line declaring the very class I've autoloaded the file to declare! I got this problem running Ruby 1.9.2p0
Anyway adding this to the top of the file that autoloaded the file giving the error fixed it for me:
$LOAD_PATH.unshift './'
Cheers, Dave.
January 20th, 2011
Installing RVM on a Mac
Topics: Ruby, Mac, Howtosudo mkdir /usr/local/lib sudo bash < <( curl -L http://bit.ly/rvm-install-system-wide ) sudo dseditgroup -o edit -a YOURUSERNAME -t user rvm echo '[[ -s "/usr/local/lib/rvm" ]] && . "/usr/local/lib/rvm"' >> ~/.bash_profile source ~/.bash_profile rvm install 1.9.2 rvm --default use 1.9.2 rvm 1.9.2 ruby --version
December 11th, 2010
Blocking Spotify's P2P Connections
Topics: HowtoIt turns out Spotify uses P2P technology so that it can reduce the load on it's servers. Great, except that uses a fair amount of bandwidth and sometimes that's not OK.
The client always falls back on their central servers, so we could just block P2P. Problem is that we're given no manual option to disable, (or limit) P2P sharing. Worse still, the client spawns connections to other users within a massive range of ports making them tricky to block.
I just spent the last few hours looking at this because my bandwidth quota has been destroyed, I've got a few ideas and some of them have worked.
Desktop Firewall
I know, I know, I hate these Desktop firewalls as well. I never thought I'd see the day when I wanted to use one. On the other hand it does make dealing with programs like Spotify much easier. On my Macbook I was able to install The Little Snitch and set it up to block the Spotify process from connecting to anything except .spotify.com .
It actually turned out to work pretty well and it was the easiest / quickest solution. It's not helpful if you're using more than one computer though and I still don't like the idea of relying on programs like these.
Edit: On the Windows 2000 box Tiny Personal Firewall was the best firewall I could find, it's lacking compared to The Little Snitch for Mac though.
Socks Proxy
Spotify gives the option to send connections through a proxy server. This gave me an idea, what if we setup a proxy server that only allowed connections to .spotify.com and then forced Spotify to use it. (Of course the proxy server would be useless for web-browsing or any other purpose.)
This took me a while to get working properly, in the end I setup the Dante proxy server on one of my Debian servers. Here's my /etc/danted.conf , it's probably wrong and insecure so don't count on it. (10.10.10.0/24 is my internal subnet and eth1 happens to be the box's primary ethernet adapter. You will probably have to change those settings.)
After the proxy is set up you need to tell Spotify to use it (I had to restart Spotify before it kicked in). But now we're set, we've thrown all the bathwater out and the baby's fine. This method has a lot of benefits too. It's a centralized solution and doesn't require any other software for the clients.
Edit: Spotify ignored my proxy settings for P2P traffic! It sends all the good stuff through the proxy though, I then had to block any other traffic with a desktop firewall myself :(
Hidden option
If I made Spotify I would have probably added a secret option somewhere to disable P2P connections. It would be tricky to test the app without it and surely Spotify's office would be brought to a standstill otherwise?! Let's find the option, I've got two ideas where it might be.

Spotify seems to support command line switches, although they are undocumented there might be some interesting functionality hidden away and who knows maybe we can turn off sharing?
{"autologin_username":"daveinadub",
"listen_port":12517,
"cache_size":1024,
"proxy":"10.10.10.99:8080@socks4",
"proxy_mode":2,
"proxy_pass":"REDACTED",
"g_sett_high_bitrate":1,
"flash_version":9,
"realtime_clock_delta":0}
My final thought is editing the settings manually. Spotify has a settings file, it seems to be a simple JSON format so if we knew the names of hidden options we could change the settings there. Who knows maybe 'p2p': 0 is all that's standing in the way?
Either way, I have no idea where this elusive option is. Get searching and report back!
Mess up the cache
Well Spotify has a cache of files, presumably for use with the P2P sharing. If we could clear that cache or somehow disable it perhaps this could break P2P sharing?
The Spotify client only lets you reduce the cache size to a minimum of 1 Gigabyte but interestingly I've noticed the setting is stored in the settings file. (Look at that sample above, '"cache_size": 1024'). Perhaps this could be set to 0 manually? I don't have time to test that idea but let me know if it works for you.
Edit: I've just given it a try, I found that setting cache_size to 1 was lowest it would accept. It reduced my cache down to 90megs initially and since then it's been dropping slowly. I'm not sure if it will ever get as low as 1meg though. This idea might be counterproductive if it means we need to download more often, I'm also not sure if it's reduced the P2P traffic or not. Another downside with this train of thought is it would be very easy for the Spotify team to just make the minimum number 1024 in a future update.
Alternative Client
I just had another thought, instead of forcing the official Spotify client to conform we could just use an alternative client. There seems to be a range of alternative clients available. I haven't tried any of them yet but it looks like an promising approach.
Cheers Dave.
November 18th, 2010
Syncing Google calendar with Facebook birthdays and events
Topics: Howto, Project, PythonHi everyone,
I recently tried to get Facebook birthdays and events to show up in my Google calendar. Everything I tried was broken, I just couldn't find something that worked properly.
Anyway I've made my own solution, it's available here: http://apps.facebook.com/calenderp
You have to click two install buttons (one with Facebook and one with Google) and then your calendar will be synced. It gets timezones right, has been translated into 3 languages so far and is starting to build up a fair following of users.
If you're interested in the technical side of things I've shared the source on GitHub https://github.com/kzar/CalenDerp . It uses Python, Google appengine, Facebook's graph API and the Google calendar API to sync everything.
Anyway let me know if you have feedback!
Cheers, Dave.
Edit: Also I'm looking for translators, get in touch if you can translate about 20 phrases into your language for me.