Package org.jruby.jubilee

Source Code of org.jruby.jubilee.RackApplication

package org.jruby.jubilee;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.jubilee.impl.RubyIORackInput;
import org.jruby.jubilee.impl.RubyNullIO;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.vertx.java.core.Handler;
import org.vertx.java.core.VoidHandler;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonObject;
import org.vertx.java.platform.impl.WrappedVertx;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Created with IntelliJ IDEA.
* User: isaiah
* Date: 11/29/12
* Time: 5:40 PM
*/
public class RackApplication {
    private IRubyObject app;
    private boolean ssl;
    private boolean hideErrorStack;
    private Ruby runtime;
    private WrappedVertx vertx;
    private RubyClass rackIOInputClass;
    private RubyClass httpServerResponseClass;
    private RackEnvironment rackEnv;

    public RackApplication(WrappedVertx vertx, ThreadContext context, IRubyObject app, JsonObject config) throws IOException {
        this.app = app;
        this.ssl = config.getBoolean("ssl", false);
        this.hideErrorStack = config.getBoolean("hide_error_stack", false);
        this.vertx = vertx;
        this.runtime = context.runtime;
        // Memorize the ruby classes
        this.rackIOInputClass = (RubyClass) runtime.getClassFromPath("Jubilee::IORackInput");
        this.httpServerResponseClass = (RubyClass) runtime.getClassFromPath("Jubilee::HttpServerResponse");

        this.rackEnv = new RackEnvironment(runtime);
    }

    public void call(final HttpServerRequest request) {
//        String te = request.headers().get(Const.Vertx.TRANSFER_ENCODING);
//        String contentLength;
        final RackInput input;
        // This should be handled by Netty (expose a contentLength methods via HttpRequest,
        // it set the empty content flag when passing the header
//        if ((te != null && te.equals("chunked")) ||
//                ((contentLength = request.headers().get(Const.Vertx.CONTENT_LENGTH)) != null && !contentLength.equals("0"))) {
        final ByteBuf bodyBuf = Unpooled.buffer(0, Integer.MAX_VALUE);
        final AtomicBoolean eof = new AtomicBoolean(false);
        input = new RubyIORackInput(runtime, rackIOInputClass, request, bodyBuf, eof);

        request.dataHandler(new Handler<Buffer>() {
            @Override
            public void handle(Buffer buffer) {
                bodyBuf.writeBytes(buffer.getByteBuf());
            }
        });

        request.endHandler(new VoidHandler() {
            @Override
            protected void handle() {
                eof.set(true);
            }
        });
        request.exceptionHandler(new Handler<Throwable>() {
            @Override
            public void handle(Throwable ignore) {
                eof.set(true);
            }
        });
//        } else {
//            input = nullio;
//        }
        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    // This is a different context, do NOT replace runtime.getCurrentContext()
                    IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", rackEnv.getEnv(request, input, ssl));
                    /*
                    if (request.isHijacked()) {
                        // It's the hijacker's response to close the socket.
                        return;
                    }
                    */
                    RackResponse response = (RackResponse) JavaEmbedUtils.rubyToJava(runtime, result, RackResponse.class);
                    RubyHttpServerResponse resp = new RubyHttpServerResponse(runtime,
                            httpServerResponseClass, request);
                    response.respond(resp);
                } catch (Exception e) {
                    request.response().setStatusCode(500);
                    String message = "Jubilee caught this error: " + e.getMessage() + "\n";
                    StringWriter stringWriter = new StringWriter();
                    PrintWriter printWriter = new PrintWriter(stringWriter);
                    e.printStackTrace(printWriter);
                    if (hideErrorStack) {
                        request.response().end("Internal error.");
                    } else {
                        request.response().end(message + stringWriter.toString());
                    }
                    e.printStackTrace(runtime.getErrorStream());
                }
            }
        };
        vertx.startInBackground(task, false);
    }

}
TOP

Related Classes of org.jruby.jubilee.RackApplication

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.