Package nginx.clojure.net

Source Code of nginx.clojure.net.SimpleHandler4TestNginxClojureAsynSocket$AsynHttpContext

package nginx.clojure.net;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Map;

import nginx.clojure.NginxClojureRT;
import nginx.clojure.NginxHttpServerChannel;
import nginx.clojure.NginxRequest;
import nginx.clojure.java.ArrayMap;
import nginx.clojure.java.Constants;
import nginx.clojure.java.NginxJavaRingHandler;
import nginx.clojure.logger.LoggerService;

public class SimpleHandler4TestNginxClojureAsynSocket implements NginxJavaRingHandler {

  public static class AsynHttpContext {
    int rc;
    int wc;
    boolean reqSent;
    byte[] req;
    byte[] buf;
    ByteArrayOutputStream resp;
    NginxHttpServerChannel downstreamChannel;
  }
 
  static LoggerService log;
 
  public SimpleHandler4TestNginxClojureAsynSocket() {
    if (log == null) {
      log = NginxClojureRT.getLog();
    }
  }
 
  @Override
  public Object[] invoke(Map<String, Object> request) {
    NginxRequest req = (NginxRequest) request;
    NginxHttpServerChannel serverChannel = req.handler().hijack(req, false);
    NginxClojureAsynSocket asynSocket = new NginxClojureAsynSocket();
    AsynHttpContext ctx = new AsynHttpContext();
    ctx.rc = ctx.wc = 0;
//    tell server we won't keep-alive, we have two choices :
//    (1) http header  "Connection" = close
//      (2) after send all request, call s.shutdown(NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_SHUTDOWN_WRITE);
//      here we will use choice (1)
//    http://mirror.bit.edu.cn/apache/httpcomponents/httpclient/RELEASE_NOTES-4.3.x.txt
    ctx.req = "GET /apache/httpcomponents/httpclient/RELEASE_NOTES-4.3.x.txt HTTP/1.1\r\nUser-Agent: nginx-clojure/0.2.5\r\nHost: mirror.bit.edu.cn\r\nAccept: */*\r\nConnection: close\r\n\r\n".getBytes();
    ctx.buf = new byte[1024];
    ctx.resp = new ByteArrayOutputStream();
    ctx.downstreamChannel = serverChannel;
    asynSocket.setContext(ctx);
    asynSocket.setHandler(new NginxClojureSocketHandler() {
     
      @Override
      public void onWrite(NginxClojureAsynSocket s, long sc) {
        if (sc != NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_OK) {
          log.error("onWrite error %d", sc);
          s.close();
          AsynHttpContext ctx = s.getContext();
          ctx.downstreamChannel.sendResponse(500);
          return;
        }
        AsynHttpContext ctx = s.getContext();
        if (ctx.reqSent) {
          log.info("after request meet write again, just ignored..........");
          //we don't need to write data now
          s.shutdown(NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_SHUTDOWN_SOFT_WRITE);
          return;
        }
       
        long n = 0;
        //write as much as possible
        do{
          n = s.write(ctx.req, ctx.wc, ctx.req.length-ctx.wc);
          if (n < 0) {
            if (n == NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_ERR_AGAIN) {
              log.info("we 'll try write again");
              return;
            }
            log.error("write error : %s", n);
            s.close();
            ctx.downstreamChannel.sendResponse(500);
            return;
          }else {
            ctx.wc += n;
            log.info("write %d, total %d", n, ctx.wc);
            if (ctx.wc == ctx.req.length) {
              ctx.reqSent = true;
//              s.shutdown(NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_SHUTDOWN_WRITE);
              log.info("fininsh write total write: %d", ctx.wc);
              return;
            }
          }
        }while(n > 0);
      }
     
      @Override
      public void onRelease(NginxClojureAsynSocket s, long sc) {
        log.info("released %d", sc);
      }
     
      @Override
      public void onRead(NginxClojureAsynSocket s, long sc) {
        if (sc != NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_OK) {
          log.error("onRead error %d", sc);
          s.close();
          AsynHttpContext ctx = s.getContext();
          ctx.downstreamChannel.sendResponse(500);
          return;
        }
        AsynHttpContext ctx = s.getContext();
        if (ctx.wc != ctx.req.length) {
          log.warn("we have not write all request!");
        }else {
          long n = 0;
          //read as much as possible
          do {
            n = s.read(ctx.buf, 0, ctx.buf.length);
            if (n < 0) {
              if (n == NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_ERR_AGAIN) {
                log.info("we 'll try read again");
                return;
              }
              log.error("read error : %s", n);
              s.close();
              ctx.downstreamChannel.sendResponse(500);
            }else if (n == 0){
              log.info("fininsh request total read: %d", ctx.rc);
              s.close();
              Object[] resps = new Object[] {
                  200,
                  ArrayMap.create(Constants.CONTENT_TYPE, "text/html"),
                      new ByteArrayInputStream(ctx.resp.toByteArray()) };
              //just for test not for good performance and right behavior for a http proxy
              ctx.downstreamChannel.sendResponse(resps);
            }else {
              ctx.rc += n;
              ctx.resp.write(ctx.buf, 0, (int)n);
              log.info("read %d, total: %d", n, ctx.rc);
            }
          }while (n > 0);
        }
      }
     
      @Override
      public void onConnect(NginxClojureAsynSocket s, long sc) {
        if (sc != NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_OK) {
          log.error("onConnect error %d", sc);
          s.close();
          AsynHttpContext ctx = s.getContext();
          ctx.downstreamChannel.sendResponse(500);
          return;
        }
        log.info("connected now!");
      }
    });
    asynSocket.connect("mirror.bit.edu.cn:80");
    return null;
  }

}
TOP

Related Classes of nginx.clojure.net.SimpleHandler4TestNginxClojureAsynSocket$AsynHttpContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.