Category: Exoweb
Checking PostgreSQL to ensure it works with SSL or non-SSL ports
By Chee Ming on Mar 18, 2009 | In Technical, Exoweb, Python, Postgresql | Send feedback »
If you want to check to ensure your SSL or non-SSL ports in PostgreSQL are working properly, read further to find out how.
For SSL support, you need to setup your PostgreSQL to work with SSL properly. Just turn on the ssl flag in postgresql.conf and then make sure you've setup the server.crt as mentioned in PostgreSQL docs about Secure TCP/IP Connections with SSL.
If you want force psql to use non-SSL for the connection, you need to set the PGSSLMODE environment variable. If you're using bash, do something like this:
export PGSSLMODE=disable
And then try to run the psql to connect to the server. I would suggest that you be explicit in your pg_hba.conf to specify that you want hostnossl, so that the server will not accept SSL connections.
If you got things configured correctly, it should work without problems. On the other hand, you can force it to use SSL, like this:
export PGSSLMODE=require
You should see a fatal error message from psql, stating that there is no pg_hba.conf entry for SSL on. You can use the same method to test for SSL-only connections by using hostssl instead in pg_hba.conf.
This environment variable works not only for psql but also for any library or tool that uses libpq. For example, I include the console output for testing the psycopg library. I have already set up the PostgreSQL to work with SSL only.
silviana:~ cheeming$ export PGSSLMODE=disable
silviana:~ cheeming$ python2.4
Python 2.4.5 (#1, Jul 15 2008, 23:37:00)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg
>>> psycopg.__version__
'1.1.21'
>>> psycopg.connect('host=127.0.0.1 dbname=mydatabase')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
psycopg.OperationalError: FATAL: no pg_hba.conf entry for host "127.0.0.1",
user "cheeming", database "mydatabase", SSL off
>>> psycopg.connect('host=127.0.0.1 dbname=mydatabase sslmode=require')
<connection object at 0x6a180>
>>>
silviana:~ cheeming$ export PGSSLMODE=require
silviana:~ cheeming$ python2.4
Python 2.4.5 (#1, Jul 15 2008, 23:37:00)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg
>>> psycopg.connect('host=127.0.0.1 dbname=mydatabase')
<connection object at 0x6a1d8>
As I tried out using the environment variable way, I realised that you can also change the data source name to include sslmode=require, the same like the PGSSLMODE environment variable. I have updated the console listing above to show that as well.
Oh by the way, I heard a rumour that psycopg 1 doesn't support SSL. I am not 100% sure about it. Its quite hard to find out for sure (as I have tried on google, maybe I am not RTFM-ing enough) other than just testing it. The only info I found indicating this is some guy complaining about ssl not being supported in Windows.
Looking at the psycopg source code shows that there is support for something called sslmode. And in the ChangeLog file, its stated as follows:
2004-01-10 Federico Di Gregorio <fog@debian.org>
* module.c (psyco_connect): added "sslmode" parameter.
There are more environment variables that you can tweak to change the behaviour of the libpq C library and its stated here.
Hope this is useful for future PostgreSQL bug hunters!
Hacking Ubiquity for better Identi.ca/Twitter usage
By Chee Ming on Mar 1, 2009 | In Random Thoughts, Technical, Exoweb, Mac OSX | 2 feedbacks »
I've been using Ubiquity plugin with Firefox for quite a while, mostly for Tinyurl-ing and Identi.ca-ing/Twitter-ing.
For those who don't know what it is: it is a Quicksilver-ish clone but for Firefox and it allows you to create shortcuts for a lot of the web related tasks that you might normally perform. For example: converting a URL to tinyurl, you just need to hit a shortcut, type a command and voila, its done. No need to copy and paste or click on some button. Or send a quick tweet; no need to switch application or create a new tab and login to twitter.com.
And for those who don't know what is Quicksilver: its a very cool program launcher for the OSX and it actually does a lot more than a simple program launcher, although I don't use much of the other, more powerful functions.
Ubiquity is a pretty good idea and quite good to use, minus the bug #19 (broken growl notification) that drives me crazy, but I am getting used to it.

Since I am a programmer I guess I should hack on more code to make my life easier (Hmmm, maybe I should fix that bug #19). I've been using Identi.ca to post my tweets and because I was lazy I wanted to do it in Ubiquity and I got a Ubiquity script from the Ubiquity Firefox Google Groups that would do the trick.
I've been using it for quite a while and realised I have the tendency to make a mistake when replying to tweets (using @nickname) in Ubiquity. So I thought that it would be useful to change the script to make the experience slightly better.
Before I start, I would like to just talk about my micro-blog setup: I have setup my Identi.ca to post my tweets to Twitter. And my normal use case is to tweet using Identi.ca and then check the feed with all those that I following in Twitter since I have more activity there. So if I see anything interesting that I would like to reply to or retweet I can just type in the username in my status message. But the problem I have is that I might type wrongly so I just wanted a way to make it less error prone.
So what I did was to hack the original Identi.ca script and added a simple check when I type the @ symbol in my message. It will extract all the Twitter usernames from the current active webpage when I activated the Ubiquity command prompt and then display in the Ubiquity preview panel as a list of candidates.

As I slowly complete the nickname, it will drill down the list of candidates based on the character by character matching. If I make a typo, then there would be no candidate names in the list. Its just a very simple hack but I think it would make my replying a bit less error prone. The next step would be to have an easy way to match the reply to the correct tweet. I wonder if there is a way to do it in my case, since I am using Identi.ca. I haven't really explored the API at all.
Because of this small itch I managed to learn a bit about hacking Ubiquity and I have to say that its really straightforward and the fact that I can use jQuery makes programming in Javascript almost fun. I would rather code in Python but I think I can live with this.
So if anyone wants to try out the hack I made, the code is hosted as a Gist in GitHub. Do give me some feedback, whether you find it useful or useless.
JSON response in Django views with jQuery
By Chee Ming on Feb 21, 2009 | In Random Thoughts, Technical, Exoweb, Python, Django | Send feedback »
I have been looking for a more elegant way to code and structure a Django view so that it will support rendering of responses encoded in either HTML or JSON.
I do this because I want to add some AJAXy usability to my HTML forms while retaining some backwards compatibility for non-Javascript enabled Web browsers.
First, lets look at a simple Django view:
def foo(request):
if request.method == 'POST':
form = Form1(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/foo/success/')
else:
form = Form1()
return render_to_response('app1/template1.html', {'form': form})
I was lazy and did some hacky stuff like this to support JSON response.
def foo(request):
if request.method == 'POST':
form = Form1(request.POST)
if form.is_valid():
form.save()
if request.POST.get('type', '') == 'json':
data = {} # define your own data structure
return HttpResponse(simplejson.dumps(data),
mimetype='application/json')
else:
return HttpResponseRedirect('/foo/success/')
else:
form = Form1()
return render_to_response('app1/template1.html', {'form': form})
And for the HTML form, I needed some Javascript (using jQuery) like this:
$("#id_cmd_submit").click(function(){
$.post("/foo/", {type: "json"},
function(data) {
alert(data);
}, "json");
});
I was thinking to myself that this type parameter is kinda of ugly and not necessary. The HTTP protocol actually has a Accept header that you can use to define what encoding the HTTP response from the server can be and this is automatically added when you use the $.post() from jQuery using the json type.
If you examine the HTTP headers in the Django view through request.META['HTTP_ACCEPT'] you will see values like this:
application/json, text/javascript, */*
So to make the hacky method a bit less hacky, I did this:
def foo(request):
if request.method == 'POST':
form = Form1(request.POST)
if form.is_valid():
form.save()
if 'application/json' in request.META.get('HTTP_ACCEPT', '')
data = {} # define your own data structure
return HttpResponse(simplejson.dumps(data),
mimetype='application/json')
else:
return HttpResponseRedirect('/foo/success/')
else:
form = Form1()
return render_to_response('app1/template1.html', {'form': form})
And the Javascript now looks like this:
$("#id_cmd_submit").click(function(){
$.post("/foo/", {},
function(data) {
alert(data);
}, "json");
});
Of course the code is still not very pretty and there are better ways to structure it better. In fact, all I did was just to make the API more "conforming" to HTTP and thus the Javascript code slightly cleaner. The Python code is somewhat the same.
As for the Python code, I see that someone has tried to make this style a bit prettier but I am not too sure if it will fit with all my use cases and I don't like the additional complexity.
I did read a bit about Adrian Holovaty's take on this AJAXy stuff. Its definitely cleaner than my approach but I wish Django have better support for HTTP's Accept header since I like the approach of using the Accept header. I found a middleware in Django snippets that can abstract away the complexity a bit in a more elegant way.
There is a good writeup on REST worst practices by Jacob Kaplan-Moss which touches a bit on using the Accept header instead. Malcolum Tredinnick also though on this a bit in an article about content types on this blog.
So I guess I did not bark up the wrong tree. And surprisingly, those blog articles that I found were quite recent. At least I am not outdated. ![]()
Chinese New Year (or Spring Festival) in Malaysia
By Chee Ming on Jan 31, 2009 | In Random Thoughts, Pictures, Exoweb, Travel, China | Send feedback »
In Malaysia, for me, Chinese New Year (CNY) means meeting up with family and relatives, having lots of good food, getting some "ang pow" (红包, hong2 pao1) and finally getting fried in the super hot weather.
In China, its more of playing with firecrackers and spectating the fireworks, trying to rest amidst all the hustle and bustle, playing mahjong and braving the cold weather.
I initially wanted to write about what is different between Malaysia and China in terms of Chinese customs, but I realised that its quite hard. Its basically the same but tiny differences in the way it is practiced. First difference, most people call it CNY in Malaysia but in Beijing, its Spring Festival, although, its changing to favour Spring Festival a bit more in Malaysia these days.
I feel that the Chinese in Malaysia are a bit more superstitious than the Chinese in the northern part of China, e.g. Beijing. I can't say for the Chinese in the southern China since I didn't live there much.
During CNY, its considered bad luck to do things like: sweeping the floor or breaking a bowl. The reasoning for both is somewhat along the lines of removing or destroying the prosperity. It is also bad to sleep during CNY in the afternoon, because its considered lazy. I think there are less of this superstition stuff when I was living in China.
For Malaysia, one only gives "ang pow" when they are married. And if you're not, then you receive "ang pow". Of course, there is supposedly some limit to this, for those who don't get married.
It seems quite a number of the Chinese in China I know don't receive "ang pow" when they are already working. In some families, I hear, if you're working, you're supposed to be giving out "ang pow".
I know that in Beijing, its customary to give things in pairs, e.g. 2 bottles of wine. I thought this was a Cantonese ritual, because of that we get two "ang pows" from each married couple.
One thing I don't get is why do we need so many different ways to say angpow:
- Angpow (hokkien), Hongpao (mandarin), Red envelope (english)
- Lai see (cantonese)
- Yasui qian (mandarin)
We eat "tang yuan" (汤圆 tang1 yuan2) during CNY and its normally quite sweet. The ones I ate in Beijing, I remember, aren't so sweet. The northern Chinese would eat "jiaozi" (饺子 jiao3zi) on the 5th day of CNY.

One special thing that the Malaysians do is to "low sang" during CNY. There isn't a wikipedia article on this, but this blog article covers it well with pictures.
Using Bitten 0.6 with Trac 0.11
By Chee Ming on Jan 27, 2009 | In Random Thoughts, Technical, Exoweb, Python | Send feedback »
I got Trac 0.11.2.1 up and running with Apache using FastCGI and then decided to try out Bitten. I've read about it before but never seen it in action or configured it before. I downloaded the 0.6 version (r567) of Bitten and realised that it still requires Clearsilver. Trac 0.11 is supposed to be using a new templating system. But its not so bad, its pretty easy to install Clearsilver. Check Ticket #248 for the Clearsilver issue.
Then after that I realised that it requires the WebTracAdmin plugin, I suppose there are some code dependencies. But it doesn't require the plugin to be enabled in the Trac setup. Having WebTracAdmin installed will allow you to see additional Bitten specific Admin options in Trac. Check the install instructions for more info.
Things look like its working well. Clicking around doesn't seem to trigger any issues. I read more about how Bitten works and I realise I need to create a build recipe in the Admin section. So I head off to create one, but Trac continually gives me an error about having issues with missing or invalid form token, which might be caused by cookies.
So I went ahead to troubleshoot this problem and realised that the form token that is rendered in the HTML form is different from the form token that is stored in the cookie. After a bit more digging, it seems everytime I load the Bitten form in Trac, 2 requests are made to the server.
So what is the 2nd requests? And why does it matter? A bit more digging reveals that Trac will generate a different form token for each requests and the offending request is for an invalid Javascript file (wikitoolbar.js).
Because Bitten is written based on pre-Trac-0.11 code base, I guess there are some missing stuff, which lead to the template generating the wrong path for static files, which lead to making erroneous requests and finally creating this buggy behaviour with the form token. There is a ticket already about something similar and I reported my findings as well.
A bit of templating hacking here and voila Bitten seems to be working for real now, at least that is what I thought until I get to running Bitten slaves. Only after doing all this work did I realise that there is a Bitten for Trac 0.11, an experimental branch. I wonder if everything is working as it should. I am currently happy with the hacked up setup and won't want to modify it for the time being.
A Bitten slave will do all the grunt work of running the builds. You need to write some XML files as instructions for the slave. I wanted to write the whole build script in the Bitten recipe XML DSL but it seems that is not the right way to go. The way the Bitten slave runs the shell commands make it hard to do so. So you'll actually have to write a shell script first to do all that work (it makes sense anyway) and use the Bitten recipe to invoke it.
The Bitten slave will capture all the output and result of the commands that you execute and send it back to Trac. From my testing it seems that the Bitten slave is quite sensitive, I had a script that output new lines and that seemed to have broken the build. I actually had to make my scripts output less crap to make it a bit more Bitten friendly.
All in all, it wasn't that hard to setup and I am pretty happy with the setup at the moment. I am so happy that it is open sourced and I can hack on it. I am still trying to figure out how to use virtualenv in this whole setup so that I can also test the setup of python related dependencies. That will be another experiment for another day and maybe another blog post, I suppose...
