Appengine transition from python to Go
Hadn't updated this blog for a few months, and neither the "personal web site" that I had started earlier. So, to try something new, I decided to port that appengine site from python to go (looking at the Github logs, I haven't updated that for 2 years !!)
app.yaml is changed to get rid of all non-static handlers (which are now declared inside the
func init() in the
.go file. So the only handlers will be
The first thing I did was to make a barebones "Hello World" index handler, and run it with
$ google_appengine/dev_appserver.py <path to my app>
But I immediately got this error:
google.appengine.tools.devappserver2.wsgi_server.BindError: Unable to find a consistent port localhost Exception in thread Thread-4 (most likely raised during interpreter shutdown): Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner File "/usr/lib/python2.7/threading.py", line 504, in run File "/home/agam/Documents/Code/google_appengine/google/appengine/api/taskqueue/taskqueue_stub.py", line 2014, in MainLoop File "/home/agam/Documents/Code/google_appengine/google/appengine/api/taskqueue/taskqueue_stub.py", line 2006, in _Wait File "/usr/lib/python2.7/threading.py", line 403, in wait File "/usr/lib/python2.7/threading.py", line 258, in wait <type 'exceptions.TypeError'>: 'NoneType' object is not callable
After some Googling and Stackoverflowing, I found a somewhat bizarre fix (to use
–api_port argument) with the root cause identified as being duplicate
localhost mappings in the
/etc/hosts file, including ipv6 mappings to localhost. Now I don't want to mess up my
/etc/hosts with what is certainly a bad idea, so I used the
–api_port option and I saw the 'hello world'. So far, so good.
I had terrible fonts from long ago, and since Google Web Fonts has become pretty awesome since then, headed on over to pick a few custom fonts. Also realized that I really just need to keep the index page, since the custom blog that I started is really superseded by this one and the posterous feed tracker was obsolete some time ago.
The handler idea is quite straightforward, and there is definitely less boilerplate than what
index.py was using earlier.
Initial stupid error: All requests were going to the same handler (including static css ones). Had to change url order in
app.yaml to move the
/static above the
Ok, all set, the barebones appengine site is up and running, I hope I can add some fun stuff to this in the future!
We aren't done yet; after I uploaded the app (
appcfg.py update, which by the way prefers
–oauth2 but won't tell you about it) the html wasn't being served.
I added a
log.Fatal() and sure enough the file wasn't being read any more.
This was also a good time to see error handling in place, the application logs showed
panic: os.Exit called runtime.panic go/src/pkg/runtime/panic.c:230 os.Exit go/src/pkg/os/proc.go:42 log.Fatal go/src/pkg/log/log.go:289 agamsweb.indexHandler agamsweb/agamsweb.go:18 net/http.HandlerFunc.ServeHTTP go/src/pkg/net/http/server.go:1150 net/http.(*ServeMux).ServeHTTP go/src/pkg/net/http/server.go:1417 appengine_internal.executeRequestSafely go/src/pkg/appengine_internal/api_prod.go:248 appengine_internal.(*server).HandleRequest go/src/pkg/appengine_internal/api_prod.go:198 reflect.Value.call go/src/pkg/reflect/value.go:474 reflect.Value.Call go/src/pkg/reflect/value.go:345 _ _.go:316 runtime.goexit go/src/pkg/runtime/proc.c:280
While testing this I also ran into an appengine bug: it is possible to get the following error message, though it literally doesn't make much sense
E 2013-06-23 11:53:32.539 Request failed because the app binary was missing. This can generally be fixed by redeploying your app. I 2013-06-23 11:53:32.539 This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
(i..e how can the app binary be missing after the application was loaded? :) )
After much digging, realized that it isn't possible to read files specified by the
Hmm so I don't really need any go code to do anything meaningful right now, I'll leave 'hello world' running :/