@Override
	public void doGet( HttpServletRequest req, HttpServletResponse res )
	throws IOException {
		logger.info( "get" );
		
		String prefix = (String) req.getAttribute( "prefix" );
		String path = (String) req.getAttribute( "path" );
		String query = (String) req.getAttribute( "query" );
		Store store = (Store) req.getAttribute( "store" );
		
		if ( (Boolean) req.getAttribute( "form" ) ) {
			
			res.setContentType( "text/html" );
			res.setCharacterEncoding( "UTF-8" );
			PrintWriter w = res.getWriter();
			
			// Eeeeew
			w.print(
"<!DOCTYPE html>"
+ "<html>"
+ "<head>"
	+ "<meta charset=\"UTF-8\" />"
	+ "<title>!"+ path + "</title>"
+ "</head>"
+ "<body>"
	+ "<form action=\"" + store.createUploadUrl( prefix + path + query )
	+ "\" method=\"post\" enctype=\"multipart/form-data\">"
		+ "<input type=\"file\" name=\"file\" />"
		+ "<hr />"
		+ "<input type=\"button\" value=\"cancel\""
		+ " onclick=\"window.location='" + prefix + path + stripQuery( query ) + "'\" />"
		+ "<input type=\"submit\" value=\"submit\" />"
	+ "</form>"
+ "</body>"
+ "</html>" 
			);
			
		} else {
			
			@SuppressWarnings("unchecked")
			Map<String, String> headers = (Map<String, String>) req.getAttribute( "headers" );
			Item item = store.read( path );
			if ( item == null ) {
				res.sendError( 404 );
			} else {
				if ( item.type == null ) {
					// TODO we could write this HTML to the blobstore too?
					// although it will be a hassle to keep it up to date...
					store.handleDirectory( item, res );
				} else {
					try {
						String head;
						if ( ( (head = headers.get( "if-none-match" )) != null && head.equals( item.etag ) )
						|| ( (head = headers.get( "if-modified-since" )) != null && RFC2822.parse( head ).after( item.modified ) ) ) {
							// System.out.println("cached version for " + item.path );
							res.setStatus( 304 );
						} else {
							res.setHeader( "Etag", item.etag );
							res.setHeader( "Last-Modified", RFC2822.format( item.modified ) );
							res.setHeader( "Cache-Control", "max-age=3600, public, must-revalidate" );
							res.setHeader( "Expires", RFC2822.format( new Date( System.currentTimeMillis() + 3600 * 1000 ) ) );
							res.setHeader( "Content-Type", item.type );
							store.handleDownload( item, res );
						}
					} catch ( ParseException x ) {
						// this happens when request header contains malformed date..
						res.sendError( 400 );
					}
				}
			}
			
		}
		
	}