public void handleRequest(HttpRequest req) { 
		// TODO: handle the failed requests, returning error responses.
		HttpRequestHeader hdr = (HttpRequestHeader) req.getHeader();
		if (Cache.isCachable(hdr)) {
			//proxy.logger.info("URL "+hdr.getURL()+" is cachable");
			CachableHttpObject obj = proxy.cache.get(hdr);
			if (obj == null) {
				try {
					obj = new CachableHttpObject(hdr, proxy);
					obj.setCache(proxy.cache);
				} catch (HttpException httpe) { 
					// Response other than 200 OK
					try {
						new TransferHandler(conn, httpe.getResponse()).run();
						proxy.releaseConnection(httpe.getResponse().getConnection());
						conn.close();
					} catch (IOException e) { }
					return;
				} catch (IOException ioe) { 
					proxy.logger.warning(ioe.getMessage());
					return;
				}
			} else { 
				/* always check if is valid */
				try {
					obj.validate();
				} catch (IOException e) { 
					handleFailedRequest();
				} catch (HttpException httpe) { 
					// something going wrong with validation
					// tunnel the error response to client
					try {
						new TransferHandler(conn, httpe.getResponse()).run();
						proxy.releaseConnection(httpe.getResponse().getConnection());
						conn.close();
					} catch (IOException e) { }
				}
				proxy.logger.info("cache hit: "+hdr.getURL());
				/* we have a cache hit! */
			}
			new TransferHandler(conn, obj).run();
			proxy.cache.put(hdr.getURL(), obj);
		} else {
			/* no caching just forward the request */
			tunnelRequest(req);
		}
	}