private void handleError( long status, NginxClojureAsynChannel upstream, NginxHttpServerChannel downstream) throws IOException { upstream.close(); if (downstream.getContext() == "sent") { downstream.send( "\r\n************Error Happended************\r\n" + upstream.buildError(status), true, true); log.warn("error happened: %s", upstream.buildError(status)); } else { downstream.sendResponse( new Object[] { 500, ArrayMap.create("Content-Type", "text/html"), upstream.buildError(status) }); } }
private boolean checkDownStreamClosed( NginxClojureAsynChannel upstream, NginxHttpServerChannel downstream) { if (downstream.isClosed()) { log.info("downstream is closed!"); upstream.close(); return true; } return false; }
@Override public Object[] invoke(Map<String, Object> request) { NginxRequest req = (NginxRequest) request; NginxHttpServerChannel downstream = req.hijack(true); downstream.addListener( downstream, new ChannelCloseAdapter<NginxHttpServerChannel>() { @Override public void onClose(NginxHttpServerChannel data) { log.info("***downstream closed!"); } }); final NginxClojureAsynChannel upstream = new NginxClojureAsynChannel(); String url = "www.apache.org:80"; upstream.setTimeout(5000, 20000, 20000); upstream.connect( url, downstream, new CompletionListener<NginxHttpServerChannel>() { @Override public void onError(long code, NginxHttpServerChannel downstream) throws IOException { log.info("connected error : " + code); handleError(code, upstream, downstream); } @Override public void onDone(long status, final NginxHttpServerChannel downstream) { log.info("connected successfully : " + status); if (checkDownStreamClosed(upstream, downstream)) { return; } CharsetEncoder encoder = NginxClojureRT.DEFAULT_ENCODING.newEncoder(); ByteBuffer getCommand; try { getCommand = encoder.encode( CharBuffer.wrap( "GET /dist/httpcomponents/httpclient/RELEASE_NOTES-4.3.x.txt HTTP/1.1\r\n" + "User-Agent: nginx-clojure/0.2.5\r\n" + "Host: www.apache.org\r\nAccept: */*\r\n" + "Connection: close\r\n\r\n")); upstream.write( getCommand, upstream, new CompletionListener<NginxClojureAsynChannel>() { public void onError(long code, NginxClojureAsynChannel attachment) throws IOException { attachment.close(); handleError(code, upstream, downstream); }; @Override public void onDone(long status, final NginxClojureAsynChannel upstream) { log.info("write onDone status : " + status); upstream .getAsynSocket() .shutdown( NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_SHUTDOWN_SOFT_WRITE); if (checkDownStreamClosed(upstream, downstream)) { return; } ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 4); CompletionListener<ByteBuffer> upstreamListener = new CompletionListener<ByteBuffer>() { public void onError(long code, ByteBuffer attachment) throws IOException { handleError(code, upstream, downstream); }; @Override public void onDone(long status, ByteBuffer buffer) throws IOException { log.info("read onDone status : " + status); if (checkDownStreamClosed(upstream, downstream)) { return; } boolean end = buffer.hasRemaining() || status == 0; buffer.flip(); downstream.setContext("sent"); // have sent something downstream.send(buffer, true, end); buffer.clear(); if (!end) { upstream.read(buffer, buffer, this); } else { upstream.close(); } } }; upstream.read(buffer, buffer, upstreamListener); } }); } catch (CharacterCodingException e) { // should not happend! } } }); return null; }