public void startResponseReqBody() { MappingResult mapping = getRequestMapping(); if (Boolean.TRUE.equals(mapping.getOption("replay"))) { ReplayHelper helper = Config.getConfig().getReplayHelper(); // ByteBuffer[] body=bodyPage.getBuffer(); if (helper.doReplay(this, null)) { return; // replayできた,bodyは消費されている } } if (response()) { responseEnd(); // TODO必要ないと思う return; } }
/* 自サーバの/connection WebScoketに接続する */ public class ConnectChecker implements Timer, WsClient { private static Logger logger = Logger.getLogger(ConnectChecker.class); private static Config config = Config.getConfig(); private static ConnectChecker instance = new ConnectChecker(); private enum Stat { READY, STARTING, INC, // connection増加中 KEEP, // 保持中 DEC, // connection切断中 } private List<WsClientHandler> clients = new ArrayList<WsClientHandler>(); private int failCount; private PaPeer peer; private int count; private int maxFailCount; private Stat stat = Stat.READY; private long timerId; private long startTime; public static boolean start(int count, int maxFailCount, long timeout, PaPeer peer) { if (instance.init(count, maxFailCount, peer) == false) { return false; } instance.run(timeout); return true; } public static void end() { instance.stop(); } private synchronized boolean init(int count, int maxFailCount, PaPeer peer) { if (stat != Stat.READY) { logger.error("aleady start." + stat); // queueManager.complete(chId, null); return false; } if (this.peer != null) { this.peer.unref(); } if (peer != null) { peer.ref(); } this.peer = peer; this.count = count; this.maxFailCount = maxFailCount; this.failCount = 0; // this.paManager=config.getAdminPaManager(); if (count > 0) { stat = Stat.INC; } else { stat = Stat.KEEP; } return true; } private static Runtime runtime = Runtime.getRuntime(); private void publish(int count, int failCount, boolean isComplete) { JSONObject eventObj = new JSONObject(); eventObj.put("kind", "checkConnectProgress"); eventObj.put("time", (System.currentTimeMillis() - startTime)); eventObj.put("connectCount", count); eventObj.put("failCount", failCount); eventObj.put("useMemory", (runtime.totalMemory() - runtime.freeMemory())); eventObj.put("stat", stat); peer.message(eventObj); if (isComplete) { peer.unref(); peer = null; } } private synchronized void addWsClient() { if (stat != Stat.INC) { return; } int size = clients.size(); if ((size % 100) == 0 || size == count) { publish(size, failCount, false); } if (size >= count) { if (timerId == TimerManager.INVALID_ID) { stop(); } else { stat = Stat.KEEP; } return; } WsClientHandler wsClientHandler = WsClientHandler.create(false, config.getSelfDomain(), config.getInt(Config.SELF_PORT)); wsClientHandler.ref(); wsClientHandler.startRequest( this, wsClientHandler, 10000, "/connect", "connect", config.getAdminUrl()); clients.add(wsClientHandler); } private synchronized void delWsClient(WsClientHandler wsClientHandler, boolean isFail) { clients.remove(wsClientHandler); wsClientHandler.unref(); int size = clients.size(); if (isFail) { failCount++; if (failCount >= maxFailCount) { publish(size, failCount, false); stop(); return; } } switch (stat) { case INC: addWsClient(); break; case DEC: if ((size % 100) == 0) { publish(size, failCount, false); } sendStop(); break; } } private void sendStop() { Iterator<WsClientHandler> itr = clients.iterator(); if (itr.hasNext()) { WsClientHandler client = itr.next(); client.postMessage("doClose"); } else { // clientsが空 stat = Stat.READY; publish(0, failCount, true); } } private void run(long timeout) { startTime = System.currentTimeMillis(); if (timeout > 0) { timerId = TimerManager.setTimeout(timeout, this, null); } else { timerId = TimerManager.INVALID_ID; } addWsClient(); } private synchronized void stop() { if (stat == Stat.DEC || stat == Stat.READY) { logger.warn("aleady stoped"); return; } stat = Stat.DEC; sendStop(); } /* public void postAll(){ String now=Long.toString(System.currentTimeMillis()); synchronized(this){ if(isStop){ logger.warn("ConnectChecker was stoped"); return; } isStop=true; for(WsClientHandler client:clients){ client.postMessage(now); } } } */ public void onTimer(Object userContext) { timerId = TimerManager.INVALID_ID; int curCount; synchronized (this) { curCount = clients.size(); } publish(curCount, failCount, false); stop(); } @Override public void onWcClose(Object userContext, int stat, short closeCode, String closeReason) { WsClientHandler wsClientHandler = (WsClientHandler) userContext; delWsClient(wsClientHandler, false); } @Override public void onWcConnected(Object userContext) {} @Override public void onWcFailure(Object userContext, int stat, Throwable t) { logger.info("#wcFailure", t); WsClientHandler wsClientHandler = (WsClientHandler) userContext; delWsClient(wsClientHandler, true); } @Override public void onWcHandshaked(Object userContext, String subprotocol) {} @Override public void onWcMessage(Object userContext, String message) { if ("OK".equals(message)) { addWsClient(); return; } long sendTime = Long.parseLong(message); long now = System.currentTimeMillis(); } @Override public void onWcMessage(Object userContext, CacheBuffer message) {} @Override public void onWcProxyConnected(Object userContext) {} @Override public void onWcResponseHeader(Object userContext, HeaderParser responseHeader) {} @Override public void onWcSslHandshaked(Object userContext) {} @Override public void onWcWrittenHeader(Object userContext) {} }
private static Config getConfig() { if (config == null) { config = Config.getConfig(); } return config; }
public class PortalInjector extends PoolBase implements ProxyInjector { private static Pattern portalPathInfoPattern = Pattern.compile(";phportal=([^\\s;/?]*)"); public static final String PORTAL_PATHINFO_KEY = "portalPathInfo"; public static final String REPLACE_MARK_HEADER = "X-PH-WebAuthReplaceMark"; private static Config config = Config.getConfig(); private ProxyHandler proxyHandler; private PortalSession portalSession; private Object injectContext = null; public void init(ProxyHandler proxyHandler) { this.proxyHandler = proxyHandler; this.portalSession = PortalSession.getPortalSession(proxyHandler); injectContext = null; } public void onRequestHeader(HeaderParser requestHeader) { /* portal機能の場合path情報にportal機能用の情報が着いている場合がある。 * この情報は削除してproxy対象サーバにリクエスト */ MappingResult mapping = proxyHandler.getRequestMapping(); String path = mapping.getResolvePath(); Matcher matcher = null; synchronized (portalPathInfoPattern) { matcher = portalPathInfoPattern.matcher(path); } StringBuffer sb = null; String portalPathInfo = null; if (matcher.find()) { sb = new StringBuffer(); matcher.appendReplacement(sb, ""); portalPathInfo = matcher.group(1); matcher.appendTail(sb); path = sb.toString(); mapping.setResolvePath(path); requestHeader.setRequestUri(mapping.getResolvePath()); proxyHandler.setRequestAttribute(PORTAL_PATHINFO_KEY, portalPathInfo); } /* * proxyでAuthrizationヘッダを付加する作戦の場合 String basicAuthHeader = getBasicAuthHeader(mapping.isResolvedHttps(),mapping.getResolveServer()); if (basicAuthHeader != null) { requestHeader.addHeader(HeaderParser.WWW_AUTHRIZATION_HEADER, basicAuthHeader); proxyHandler.setRequestAttribute(HeaderParser.WWW_AUTHRIZATION_HEADER, basicAuthHeader); } */ } private static Pattern authenticationPattern = Pattern.compile("\\s*Basic\\s+realm\\s*=\\s*\"(.[^\"]*)\"", Pattern.CASE_INSENSITIVE); public void onResponseHeader(HeaderParser responseHeader) { InjectionHelper helper = config.getInjectionHelper(); MappingResult mapping = proxyHandler.getRequestMapping(); HeaderParser requestHeader = proxyHandler.getRequestHeader(); String WebAuthReplaceMark = requestHeader.getHeader(REPLACE_MARK_HEADER); String resolveUrl = mapping.getResolveUrl(); if (WebAuthReplaceMark == null) { portalSession.endBasicProcess(resolveUrl); } String statusCode = responseHeader.getStatusCode(); if ("401".equals(statusCode) /*&&injectContext==null*/) { mapping.getResolveDomain(); String authentication = responseHeader.getHeader(HeaderParser.WWW_AUTHENTICATE_HEADER); if (authentication == null) { return; } Matcher matcher; synchronized (authenticationPattern) { matcher = authenticationPattern.matcher(authentication); } if (!matcher.find()) { return; // Digestはここでチェックあうと } String realm = matcher.group(1); // 自分の持っている代理ログイン情報で、domain,realmに合致するものはないか? String resolveDomain = mapping.getResolveDomain(); CommissionAuth basicCommissionAuth = portalSession.getBasicAuth(resolveDomain, realm); if (WebAuthReplaceMark == null && !portalSession.startBasicProcess(resolveUrl, basicCommissionAuth)) { return; } if (basicCommissionAuth == null || basicCommissionAuth.isEnabled()) { String authrization = requestHeader.getHeader(HeaderParser.WWW_AUTHORIZATION_HEADER); if (WebAuthReplaceMark == null) { // ブラウザから直接出されたリクエスト responseHeader.setStatusCode("200"); proxyHandler.removeResponseHeader(HeaderParser.WWW_AUTHENTICATE_HEADER); portalSession.putRealm(resolveUrl, realm); proxyHandler.setReplace(true); injectContext = helper.getReplaceContext("WebAuthReplace.html"); proxyHandler.addResponseHeader( HeaderParser.CONTENT_TYPE_HEADER, "text/html; charset=utf-8"); proxyHandler.addResponseHeader("Pragma", "no-cache"); proxyHandler.addResponseHeader("Cache-Control", "no-cache"); proxyHandler.addResponseHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); } else if (authrization != null) { // ajaxからuser/passをつけているのに401が返却された=>認証情報が無効 responseHeader.setStatusCode("200"); proxyHandler.removeResponseHeader(HeaderParser.WWW_AUTHENTICATE_HEADER); proxyHandler.addResponseHeader("WebAuthRealm", realm); proxyHandler.setReplace(true); injectContext = helper.getReplaceContext("WebAuthFail.html"); proxyHandler.addResponseHeader(HeaderParser.CONTENT_TYPE_HEADER, "text/plain"); proxyHandler.addResponseHeader("Pragma", "no-cache"); proxyHandler.addResponseHeader("Cache-Control", "no-cache"); proxyHandler.addResponseHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); } } } else if ("200".equals(statusCode) || "404".equals(statusCode)) { String contentType = responseHeader.getContentType(); if (contentType != null && contentType.startsWith("text/html")) { injectContext = helper.getInsertContext("PortalInject.txt"); } } } public ByteBuffer[] onResponseBody(ByteBuffer[] body) { InjectionHelper helper = config.getInjectionHelper(); return helper.inject(injectContext, body); } public void term() { unref(); } public long getInjectLength() { if (injectContext != null) { InjectionHelper helper = config.getInjectionHelper(); return helper.getInjectContentsLength(injectContext); } return 0; } public boolean isInject() { return (injectContext != null); } }