basehandler.java
来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 551 行 · 第 1/2 页
JAVA
551 行
*/ private void setCacheExpiry () { String expires = response.getHeader ("Expires"); if (expires != null) { Date exp = HttpDateParser.getDate (expires); // common case, handle it... if (exp == null && expires.equals ("0")) exp = new Date (0); if (exp != null) { long now = System.currentTimeMillis (); if (now > exp.getTime ()) { getLogger ().logWarn ("expire date in the past: '" + expires + "'"); entry = null; return; } entry.setExpires (exp.getTime ()); } else { getLogger ().logMsg ("unable to parse expire date: '" + expires + "' for URI: '" + request.getRequestURI () + "'"); entry = null; return; } } } private void updateRange (CacheEntry<HttpHeader, HttpHeader> old, HttpHeader response, PartialCacher pc, Cache<HttpHeader, HttpHeader> cache) { HttpHeader oldRequest = old.getKey (); HttpHeader oldResponse = old.getDataHook (cache); String cr = oldResponse.getHeader ("Content-Range"); if (cr == null) { String cl = oldResponse.getHeader ("Content-Length"); if (cl != null) { long size = Long.parseLong (cl); cr = "bytes 0-" + (size - 1) + "/" + size; } } ContentRangeParser crp = new ContentRangeParser (cr, getLogger ()); if (crp.isValid ()) { long start = crp.getStart (); long end = crp.getEnd (); long total = crp.getTotal (); String t = total < 0 ? "*" : Long.toString (total); if (end == pc.getStart () - 1) { oldRequest.setHeader ("Range", "bytes=" + start + "-" + end); oldResponse.setHeader ("Content-Range", "bytes " + start + "-" + pc.getEnd () + "/" + t); } else { oldRequest.addHeader ("Range", "bytes=" + start + "-" + end); oldResponse.addHeader ("Content-Range", "bytes " + start + "-" + pc.getEnd () + "/" + t); } cache.entryChanged (old, oldRequest, oldResponse); } } private void setupPartial (CacheEntry<HttpHeader, HttpHeader> oldEntry, CacheEntry<HttpHeader, HttpHeader> entry, String entryName, Cache<HttpHeader, HttpHeader> cache) throws IOException { if (oldEntry != null) { String oldName = cache.getEntryName (oldEntry); PartialCacher pc = new PartialCacher (getLogger (), oldName, response); cacheChannel = pc.getChannel (); updateRange (oldEntry, response, pc, cache); return; } else { entry.setDataHook (response); PartialCacher pc = new PartialCacher (getLogger (), entryName, response); cacheChannel = pc.getChannel (); } } /** Set up the cache stream if available. */ protected void addCache () { if (mayCache && mayCacheFromSize ()) { Cache<HttpHeader, HttpHeader> cache = con.getProxy ().getCache (); entry = cache.newEntry (request); setCacheExpiry (); if (entry == null) { getLogger ().logAll ("Expiry =< 0 set on entry, will not cache"); return; } String entryName = cache.getEntryName (entry.getId (), false); if (response.getStatusCode ().equals ("206")) { CacheEntry<HttpHeader, HttpHeader> oldEntry = cache.getEntry (request); try { setupPartial (oldEntry, entry, entryName, cache); } catch (IOException e) { getLogger ().logWarn ("Got IOException, " + "not updating cache: " + e + "'"); entry = null; cacheChannel = null; } } else { entry.setDataHook (response); try { FileOutputStream cacheStream = new FileOutputStream (entryName); /* TODO: implement this: if (mayRestrictCacheSize ()) cacheStream = new MaxSizeOutputStream (cacheStream, cache.getMaxSize ()); */ cacheChannel = cacheStream.getChannel (); } catch (IOException e) { getLogger ().logWarn ("Got IOException, not caching: " + e + "'"); entry = null; cacheChannel = null; } } } } /** This method is used to prepare the stream for the data being sent. * This method does nothing here. */ protected void prepareStream () { // nothing here. } /** Check if this handler supports direct transfers. * @return this handler always return true. */ protected boolean mayTransfer () { return true; } protected void send () { if (mayTransfer () && content.length () > 0 && content.supportsTransfer ()) { TransferListener tl = new ContentTransferListener (); TransferHandler th = new TransferHandler (con.getProxy (), content, con.getChannel (), tlh.getCache (), tlh.getClient (), tl); th.transfer (); } else { content.addBlockListener (this); } } private class ContentTransferListener implements TransferListener { public void transferOk () { try { finishData (); finish (true); } catch (IOException e) { failed (e); } } public void failed (Exception cause) { BaseHandler.this.failed (cause); } } protected void writeCache (ByteBuffer buf) throws IOException { // TODO: another thread? buf.mark (); while (buf.hasRemaining ()) cacheChannel.write (buf); buf.reset (); tlh.getCache ().write (buf.remaining ()); } public void bufferRead (ByteBuffer buf) { try { // TODO: do this in another thread? if (cacheChannel != null) writeCache (buf); totalRead += buf.remaining (); new BlockSender (con.getChannel (), con.getSelector (), getLogger (), tlh.getClient (), buf, con.getChunking (), this); } catch (IOException e) { failed (e); } } public void blockSent () { content.addBlockListener (this); } public void finishedRead () { try { if (size > 0 && totalRead != size) setPartialContent (totalRead, size); finishData (); if (con.getChunking () && !emptyChunkSent) { emptyChunkSent = true; BlockSentListener bsl = new Finisher (); ChunkEnder ce = new ChunkEnder (); ce.sendChunkEnding (con.getChannel (), con.getSelector (), getLogger (), tlh.getClient (), bsl); } else { finish (true); } } catch (IOException e) { failed (e); } } private class Finisher implements BlockSentListener { public void blockSent () { finish (true); } public void failed (Exception cause) { BaseHandler.this.failed (cause); } public void timeout () { BaseHandler.this.timeout (); } } String getStackTrace (Exception cause) { StringWriter sw = new StringWriter (); PrintWriter ps = new PrintWriter (sw); cause.printStackTrace (ps); return sw.toString (); } protected void removeCache () { if (cacheChannel != null) { try { cacheChannel.close (); Cache<HttpHeader, HttpHeader> cache = con.getProxy ().getCache (); String entryName = cache.getEntryName (entry.getId (), false); File f = new File (entryName); f.delete (); entry = null; } catch (IOException e) { getLogger ().logMsg ("failed to remove cache entry: " + e); } finally { cacheChannel = null; } } } public void failed (Exception cause) { if (con != null) getLogger ().logWarn ("BaseHandler: error handling request: " + getStackTrace (cause)); removeCache (); finish (false); } public void timeout () { if (con != null) getLogger ().logWarn ("BaseHandler: timeout"); removeCache (); finish (false); } public void setup (Logger logger, SProperties properties) { // nothing to do. }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?