require 'rack' require 'rack/rewindable_input' Dir[::File.join(::File.dirname(__FILE__), 'jars', '*.jar')].each { |jar| require jar } module RackJetty class ServletHandler < Java::org.mortbay.jetty.handler.AbstractHandler attr_accessor :handler DefaultRackEnv = { 'rack.version' => ::Rack::VERSION, 'rack.multithread' => true, 'rack.multiprocess' => false, 'rack.run_once' => false, 'rack.errors' => $stderr, 'jruby.version' => JRUBY_VERSION, 'SCRIPT_NAME' => '', } def handle(target, request, response, dispatch) begin env = DefaultRackEnv.merge({ 'rack.input' => Rack::RewindableInput.new(JavaInput.new(request.get_input_stream)), 'rack.url_scheme' => request.get_scheme, 'CONTENT_TYPE' => request.get_content_type, 'CONTENT_LENGTH' => request.get_content_length, # some post-processing done below 'REQUEST_METHOD' => request.get_method || "GET", 'REQUEST_URI' => request.getRequestURI, 'PATH_INFO' => request.get_path_info, 'QUERY_STRING' => request.get_query_string || "", 'SERVER_NAME' => request.get_server_name || "", 'REMOTE_HOST' => request.get_remote_host || "", 'REMOTE_ADDR' => request.get_remote_addr || "", 'REMOTE_USER' => request.get_remote_user || "", 'SERVER_PORT' => request.get_server_port.to_s }) env['CONTENT_LENGTH'] = env['CONTENT_LENGTH'] >= 0? env['CONTENT_LENGTH'].to_s : "0" request.get_header_names.each do |h| next if h =~ /^Content-(Type|Length)$/i k = "HTTP_#{h.upcase.gsub(/-/, '_')}" env[k] = request.getHeader(h) unless env.has_key?(k) end # request.get_content_type returns nil if the Content-Type is not included # and Rack doesn't expect Content-Type => '' - certain methods will issue # a backtrace if it's passed in. # # The correct behaviour is not to include Content-Type in the env hash # if it is blank. # # https://github.com/rack/rack/issues#issue/40 covers the problem from # Rack's end. env.delete('CONTENT_TYPE') if [nil, ''].include?(env['CONTENT_TYPE']) status, headers, output = handler.app.call(env) if (match = %r{^([0-9]{3,3}) +([[:print:]]+)$}.match(status.to_s)) response.set_status(match[1].to_i, match[2].to_s) else response.set_status(status.to_i) end headers.each do |k, v| case k when 'Content-Type' response.set_content_type(v) when 'Content-Length' response.set_content_length(v.to_i) else response.set_header(k, v) end end buffer = response.get_output_stream output.each do |s| buffer.write(s.to_java_bytes) end ensure request.set_handled(true) end end end end