Class: Fishwife::RackServlet
- Inherits:
-
HttpServlet
- Object
- HttpServlet
- Fishwife::RackServlet
- Defined in:
- lib/fishwife/rack_servlet.rb
Overview
Wraps a Rack application in a Java servlet.
Relevant documentation:
Constant Summary collapse
- ASCII_8BIT =
Encoding.find( "ASCII-8BIT" )
Instance Method Summary collapse
-
#initialize(app, opts = {}) ⇒ RackServlet
constructor
A new instance of RackServlet.
-
#service(request, response) ⇒ Object
Takes an incoming request (as a Java Servlet) and dispatches it to the rack application setup via [rackup].
Constructor Details
#initialize(app, opts = {}) ⇒ RackServlet
Returns a new instance of RackServlet.
45 46 47 48 49 50 51 52 |
# File 'lib/fishwife/rack_servlet.rb', line 45 def initialize( app, opts = {} ) super() @log = RJack::SLF4J[ self.class ] @app = app @request_body_ram = opts[:request_body_ram] || 256 * 1024 @request_body_tmpdir = opts[:request_body_tmpdir] || Dir.tmpdir @request_body_max = opts[:request_body_max] || 8 * 1024 * 1024 end |
Instance Method Details
#service(request, response) ⇒ Object
Takes an incoming request (as a Java Servlet) and dispatches it to the rack application setup via [rackup]. All this really involves is translating the various bits of the Servlet API into the Rack API on the way in, and translating the response back on the way out.
Also, we implement a common extension to the Rack api for asynchronous request processing. We supply an ‘async.callback’ parameter in env to the Rack application. If we catch an :async symbol thrown by the app, we initiate a Jetty continuation.
When ‘async.callback’ gets a response with empty headers and an empty body, we declare the async response finished.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/fishwife/rack_servlet.rb', line 67 def service(request, response) # Turn the ServletRequest into a Rack env hash env = servlet_to_rack(request) # Handle asynchronous responses via Servlet continuations. continuation = ContinuationSupport.getContinuation(request) # If this is an expired connection, do nothing. return if continuation.isExpired # We should never be re-dispatched. raise("Request re-dispatched.") unless continuation.isInitial # Add our own special bits to the rack environment so that Rack # middleware can have access to the Java internals. env['rack.java.servlet'] = true env['rack.java.servlet.request'] = request env['rack.java.servlet.response'] = response env['rack.java.servlet.continuation'] = continuation # Add an callback that can be used to add results to the # response asynchronously. env['async.callback'] = lambda do |rack_response| servlet_response = continuation.getServletResponse rack_to_servlet(rack_response, servlet_response) and continuation.complete end # Execute the Rack request. catch(:async) do rack_response = @app.call(env) # For apps that don't throw :async. unless(rack_response[0] == -1) # Nope, nothing asynchronous here. rack_to_servlet(rack_response, response) return end end # If we got here, this is a continuation. continuation.suspend(response) rescue RequestBodyTooLarge => e @log.warn( "On service: #{e.class.name}: #{e.}" ) response.sendError( 413 ) rescue NativeException => n @log.warn( "On service (native): #{n.cause.to_string}" ) raise n.cause rescue Exception => e @log.error( "On service: #{e}" ) raise e ensure fin = env && env['fishwife.input'] fin.close if fin end |