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 + -
显示快捷键?