Skip to content

Instantly share code, notes, and snippets.

@samatjain
Created December 19, 2011 23:20
Show Gist options
  • Save samatjain/1499378 to your computer and use it in GitHub Desktop.
Save samatjain/1499378 to your computer and use it in GitHub Desktop.
Bottle-powered version of OSM XML → JSON proxy
#!/usr/bin/env python
import json
import urlparse
import bottle
import requests
from bottle import request, response, route
from bottle import install, uninstall
from lxml import etree
from json import dumps as json_dumps
class JSONAPIPlugin(object):
name = 'jsonapi'
api = 1
def __init__(self, json_dumps=json_dumps):
uninstall('json')
self.json_dumps = json_dumps
def apply(self, callback, context):
dumps = self.json_dumps
if not dumps: return callback
def wrapper(*a, **ka):
r = callback(*a, **ka)
# Attempt to serialize, raises exception on failure
json_response = dumps(r)
# Set content type only if serialization succesful
response.content_type = 'application/json'
# Wrap in callback function for JSONP
callback_function = request.query.get('callback')
if callback_function:
json_response = ''.join([callback_function, '(', json_response, ')'])
return json_response
return wrapper
install(JSONAPIPlugin())
@route('/<type>/<id:int>')
def fetch(type, id):
if type not in ('node', 'way', 'relation'):
abort('500', 'Primitive must be node, way, or relation')
r = _fetch(type, id)
if r is None:
abort('404', 'Object not found')
return r
def _fetch(item_type, item_id):
url = 'http://api.openstreetmap.org/api/0.6/%s/%d' % (item_type, item_id)
headers = {'user-agent': 'OSMPlaces JSON API Proxy (Contact: http://samat.org/contact.html)'}
response = requests.get(url, headers=headers)
# Request failed; may not exist, server error, etc
if response.status_code != requests.codes.ok:
return None
out = {}
root = etree.fromstring(response.content.encode('utf-8'))
i = root[0] # Skip <osm/>; should we be iterating over all children here?
out['type'] = i.tag # Save whether node, way, relation
# Copy attributes on node/way/relation tag
for k, v in i.items():
# Store certain keys as int, float, bool, etc
if k in ('changeset', 'uid', 'version', 'id'):
v = int(v)
if k in ('lat', 'lon'):
v = float(v)
if k in ('visible',):
v = True if v.lower() == 'true' else 'false'
out[k] = v
# Copy tags
tags = {}
for t in i.iterfind('tag'):
k, v = t.get('k'), t.get('v')
tags[k] = v
if tags:
out['tags'] = tags
# Create list of nodes for ways
nodes = []
for t in i.iterfind('nd'):
nodes.append(int(t.get('ref')))
if nodes:
out['nodes'] = nodes
# Copy members for relations
members = []
for t in i.iterfind('member'):
a = {}
for k, v in t.items():
if k in ('ref',):
v = int(v)
a[k] = v
members.append(a)
if members:
out['members'] = members
return out
application = bottle.default_app()
if __name__ == '__main__':
from bottle import run
run(reloader=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment