swc.java
来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 259 行
JAVA
259 行
package rabbit.proxy;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.Selector;import java.util.Date;import rabbit.io.WebConnection;import rabbit.io.WebConnectionListener;import rabbit.http.HttpDateParser;import rabbit.http.HttpHeader;/** A class that tries to establish a connection to the real server * or the next proxy in the chain. * * @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a> */public class SWC implements HttpHeaderSentListener, HttpHeaderListener, WebConnectionListener, ClientResourceTransferredListener { private Connection con; private long timeOffset; private HttpHeader header; private ByteBuffer buffer; private TrafficLoggerHandler tlh; private ClientResourceHandler crh; private Connection.RequestHandler rh; private int attempts = 0; private String method; private boolean safe = true; private char status = '0'; private Exception lastException; public SWC (Connection con, long timeOffset, HttpHeader header, ByteBuffer buffer, TrafficLoggerHandler tlh, ClientResourceHandler crh, Connection.RequestHandler rh) { this.con = con; this.timeOffset = timeOffset; this.header = header; this.buffer = buffer; this.tlh = tlh; this.crh = crh; this.rh = rh; method = header.getMethod ().trim (); } public void establish () { attempts++; con.getCounter ().inc ("Trying to establish a WebConnection: " + attempts); // if we cant get a connection in five cancel.. if (!safe || attempts > 5) { con.webConnectionSetupFailed (rh, lastException); } else { rh.requestTime = System.currentTimeMillis (); con.getProxy ().getWebConnection (header, this); } } public void connectionEstablished (WebConnection wc) { con.getCounter ().inc ("WebConnection established: " + attempts); rh.wc = wc; /* TODO: handle this if (header.getContentStream () != null) header.setHeader ("Transfer-Encoding", "chunked"); */ // we cant retry if we sent the header... safe = wc.getReleasedAt () > 0 || (method != null && (method.equals ("GET") || method.equals ("HEAD"))); try { if (crh != null) crh.modifyRequest (header); HttpHeaderSender sender = new HttpHeaderSender (wc.getChannel (), con.getSelector (), con.getLogger (), tlh.getNetwork (), header, con.useFullURI (), this); } catch (IOException e) { failed (e); } } public void httpHeaderSent () { if (crh != null) crh.transfer (rh.wc, this); else httpHeaderSentTransferDone (); } public void clientResourceTransferred () { httpHeaderSentTransferDone (); } public void clientResourceAborted (HttpHeader reason) { if (rh != null && rh.wc != null) { rh.wc.setKeepalive (false); con.getProxy ().releaseWebConnection (rh.wc); } con.sendAndClose (reason); } private void httpHeaderSentTransferDone () { if (!header.isDot9Request ()) { readRequest (); } else { // HTTP/0.9 close after resource.. rh.wc.setKeepalive (false); con.webConnectionEstablished (rh); } } private void readRequest () { con.getCounter ().inc ("Trying read response from WebConnection: " + attempts); try { HttpHeaderReader hhreader = new HttpHeaderReader (rh.wc.getChannel (), rh.webBuffer, con.getSelector (), con.getLogger (), tlh.getNetwork (), false, con.getProxy ().getStrictHttp (), this); } catch (IOException e) { failed (e); } } public void httpHeaderRead (HttpHeader header, ByteBuffer buffer, boolean keepalive, boolean isChunked, long dataSize) { con.getCounter ().inc ("Read response from WebConnection: " + attempts); rh.webHeader = header; rh.webBuffer = buffer; rh.wc.setKeepalive (keepalive); String sc = rh.webHeader.getStatusCode (); if (sc.length () > 0 && (status = sc.charAt (0)) == '1') { //if client is using http/1.1 if (con.getRequestVersion ().endsWith ("1.1")) { // tell client Looper l = new Looper (); con.getCounter ().inc ("WebConnection got 1xx reply " + attempts); try { HttpHeaderSender sender = new HttpHeaderSender (con.getChannel (), con.getSelector (), con.getLogger (), tlh.getClient (), header, false, l); return; } catch (IOException e) { failed (e); } } } // since we have posted the full request we // loop while we get 100 (continue) response. if (status == '1') { readRequest (); } else { String responseVersion = rh.webHeader.getResponseHTTPVersion (); setAge (rh); WarningsHandler wh = new WarningsHandler (); wh.removeWarnings (con.getLogger (), rh.webHeader, false); rh.webHeader.addHeader ("Via", responseVersion + " RabbIT"); HttpProxy proxy = con.getProxy (); rh.size = dataSize; rh.content = new WebConnectionResourceSource (con.getSelector (), rh.wc, buffer, tlh.getNetwork (), isChunked, dataSize, proxy.getStrictHttp ()); con.webConnectionEstablished (rh); } } public void closed () { lastException = new IOException ("closed"); establish (); } /** Calculate the age of the resource, needs ntp to be accurate. */ private void setAge (Connection.RequestHandler rh) { long now = System.currentTimeMillis (); String age = rh.webHeader.getHeader ("Age"); String date = rh.webHeader.getHeader ("Date"); Date dd = HttpDateParser.getDate (date); long ddt = now; if (dd != null) ddt = dd.getTime (); long lage = 0; try { if (age != null) lage = Long.parseLong (age); long dt = Math.max ((now - ddt) / 1000, 0); long correct_age = lage + dt; long correct_recieved_age = Math.max (dt, lage); long corrected_initial_age = correct_recieved_age + dt; if (corrected_initial_age > 0) { rh.webHeader.setHeader ("Age", "" + corrected_initial_age); } } catch (NumberFormatException e) { // if we cant parse it, we leave the Age header.. con.getLogger ().logWarn ("Bad age: " + age); } } private class Looper implements HttpHeaderSentListener { public void httpHeaderSent () { // read the next request... readRequest (); } public void timeout () { SWC.this.timeout (); } public void failed (Exception e) { SWC.this.failed (e); } } public void timeout () { // retry lastException = new IOException ("timeout"); establish (); } public void failed (Exception e) { lastException = e; con.getCounter ().inc ("WebConnections failed: " + attempts + ": " + e); if (rh.wc != null) { try { rh.wc.close (); } catch (IOException ioe) { con.getLogger ().logWarn ("Unable to close WebConnection" + ioe); } } rh.wc = null; // retry establish (); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?