terom@93: import os, os.path terom@93: import pypngtile as pt terom@93: terom@93: from werkzeug import Response, exceptions terom@93: terom@93: from pngtile import render terom@93: terom@93: # path to images terom@93: DATA_ROOT = os.environ.get("PNGTILE_DATA_PATH") or os.path.abspath('data/') terom@93: terom@93: # only open each image once terom@93: IMAGE_CACHE = {} terom@93: terom@93: ### Parse request data terom@93: def get_path (req_path) : terom@93: """ terom@93: Returns the name and path requested terom@93: """ terom@93: terom@93: # check DATA_ROOT exists.. terom@93: if not os.path.isdir(DATA_ROOT) : terom@93: raise exceptions.InternalServerError("Missing DATA_ROOT") terom@93: terom@93: # path to image terom@93: image_name = req_path.lstrip('/') terom@93: terom@93: # build absolute path terom@93: image_path = os.path.abspath(os.path.join(DATA_ROOT, image_name)) terom@93: terom@93: # ensure the path points inside the data root terom@93: if not image_path.startswith(DATA_ROOT) : terom@93: raise exceptions.NotFound(image_name) terom@93: terom@93: return image_name, image_path terom@93: terom@93: def get_image (name, path) : terom@93: """ terom@93: Gets an Image object from the cache, ensuring that the cached is available terom@93: """ terom@93: terom@93: # get Image object terom@93: if path in IMAGE_CACHE : terom@93: # get from cache terom@93: image = IMAGE_CACHE[path] terom@93: terom@93: else : terom@93: # open terom@93: image = pt.Image(path) terom@93: terom@93: # check terom@93: if image.status() not in (pt.CACHE_FRESH, pt.CACHE_STALE) : terom@93: raise exceptions.InternalServerError("Image cache not available: %s" % name) terom@93: terom@93: # load terom@93: image.open() terom@93: terom@93: # cache terom@93: IMAGE_CACHE[path] = image terom@93: terom@93: return image terom@93: terom@93: terom@93: ### Handle werkzeug.Request objects -> werkzeug.Response terom@93: def handle_dir (req, name, path) : terom@93: """ terom@93: Handle request for a directory terom@93: """ terom@93: terom@107: prefix = req.script_root terom@107: terom@93: return Response(render.dir_html(prefix, name, path), content_type="text/html") terom@93: terom@93: terom@93: terom@93: def handle_img_viewport (req, image, name) : terom@93: """ terom@93: Handle request for image viewport terom@93: """ terom@93: terom@107: prefix = req.script_root terom@93: terom@93: # viewport terom@93: return Response(render.img_html(prefix, name, image), content_type="text/html") terom@93: terom@93: terom@103: def handle_img_region (req, image, cache) : terom@93: """ terom@93: Handle request for an image region terom@93: """ terom@93: terom@93: # specific image terom@93: width = int(req.args['w']) terom@93: height = int(req.args['h']) terom@93: cx = int(req.args['cx']) terom@93: cy = int(req.args['cy']) terom@93: zoom = int(req.args.get('zl', "0")) terom@93: terom@93: try : terom@93: # yay full render terom@103: return Response(render.img_png_region(image, cx, cy, zoom, width, height, cache), content_type="image/png") terom@93: terom@93: except ValueError, ex : terom@93: # too large terom@93: raise exceptions.Forbidden(str(ex)) terom@93: terom@93: terom@103: def handle_img_tile (req, image, cache) : terom@93: """ terom@93: Handle request for image tile terom@93: """ terom@93: terom@93: # tile terom@93: x = int(req.args['x']) terom@93: y = int(req.args['y']) terom@93: zoom = int(req.args.get('zl', "0")) terom@103: terom@103: # cache? terom@93: terom@93: # yay render terom@103: return Response(render.img_png_tile(image, x, y, zoom, cache), content_type="image/png") terom@93: terom@93: ## Dispatch req to handle_img_* terom@103: def handle_img (req, name, path, cache) : terom@93: """ terom@93: Handle request for an image terom@93: """ terom@93: terom@93: # get image object terom@93: image = get_image(name, path) terom@93: terom@93: # what view? terom@93: if not req.args : terom@93: return handle_img_viewport(req, image, name) terom@93: terom@93: elif 'w' in req.args and 'h' in req.args and 'cx' in req.args and 'cy' in req.args : terom@103: return handle_img_region(req, image, cache) terom@93: terom@93: elif 'x' in req.args and 'y' in req.args : terom@103: return handle_img_tile(req, image, cache) terom@93: terom@93: else : terom@93: raise exceptions.BadRequest("Unknown args") terom@93: terom@93: terom@93: terom@93: ## Dispatch request to handle_* terom@103: def handle_req (req, cache) : terom@93: """ terom@93: Main request handler terom@93: """ terom@93: terom@93: # decode req terom@93: name, path = get_path(req.path) terom@93: terom@93: # determine dir/image terom@93: if os.path.isdir(path) : terom@93: # directory terom@93: return handle_dir(req, name, path) terom@93: terom@93: elif not os.path.exists(path) : terom@93: # no such file terom@93: raise exceptions.NotFound(name) terom@93: terom@93: elif not name or not name.endswith('.png') : terom@93: # invalid file terom@93: raise exceptions.BadRequest("Not a PNG file") terom@93: terom@93: else : terom@93: # image terom@103: return handle_img(req, name, path, cache) terom@93: terom@93: