Class: Rubylet::Servlet

Inherits:
Object
  • Object
show all
Includes:
Java::JavaxServlet::Servlet
Defined in:
lib/rubylet/servlet.rb

Overview

Implements the Servlet API in Ruby as a Rack server.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



9
10
11
# File 'lib/rubylet/servlet.rb', line 9

def app
  @app
end

#contextObject (readonly)

Returns the value of attribute context.



9
10
11
# File 'lib/rubylet/servlet.rb', line 9

def context
  @context
end

#servlet_configObject (readonly)

Returns the value of attribute servlet_config.



9
10
11
# File 'lib/rubylet/servlet.rb', line 9

def servlet_config
  @servlet_config
end

Instance Method Details

#destroyObject



41
42
43
# File 'lib/rubylet/servlet.rb', line 41

def destroy
  # no-op
end

#init(servletConfig) ⇒ Object

Parameters:

  • servletConfig (javax.servlet.ServletConfig)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/rubylet/servlet.rb', line 12

def init(servletConfig)
  @servlet_config = servletConfig
  @context = servletConfig.getServletContext
  
  rackup_file = param('rubylet.rackupFile') || 'config.ru'
  @app, _opts = Rack::Builder.parse_file(rackup_file)

  if defined?(Rails) && defined?(Rails::Application) && (@app < Rails::Application)
    servlet_path = @servlet_config.getInitParameter('rubylet.servletPath')
    relative_root = if servlet_path 
                      File.join(@context.context_path, servlet_path)
                    else
                      @context.context_path
                    end
    app.config.action_controller.relative_url_root = relative_root
    ActionController::Base.config.relative_url_root = relative_root
  end
end

#param(name) ⇒ Object

def param(config, name)

config.getInitParameter(name) ||
  config.getServletContext.getInitParameter(name)

end



36
37
38
39
# File 'lib/rubylet/servlet.rb', line 36

def param(name)
  @servlet_config.getInitParameter(name) ||
    @servlet_config.getServletContext.getInitParameter(name)
end

#service(req, resp) ⇒ Object

assumed to be an HttpServletRequest

assumed to be an HttpServletResponse

Parameters:

  • req (javax.servlet.ServletRequest)

    a Java servlet request,

  • resp (javax.servlet.ServletResponse)

    a Java servlet response



56
57
58
59
60
61
62
63
64
65
66
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
# File 'lib/rubylet/servlet.rb', line 56

def service(req, resp)
  env = Environment.new(req, self)
  
  catch(:async) do
    status, headers, body = app.call(env)  # may throw async
    throw :async if status == -1  # alternate means of indicating async
    respond(resp, env, status, headers, body)
    return  # :async not thrown
  end

  # :async was thrown; this only works since Servlet 3.0
  # web.xml must also have <async-supported>true<async-supported> in
  # all servlets and filters in the chain.
  #
  # TODO: this works in proof-of-concept! anything more todo?
  #
  # TODO: Rack async doesn't seem to be standardized yet... In particular,
  # Thin provides an 'async.close' that (I think) can be used to
  # close the response connection after streaming in data asynchronously.
  # For now, this code only allows a one-time deferal of the body (i.e.
  # when 'async.callback' is called, the body is sent out and the
  # connection closed immediately.)
  #
  # TODO: because of the above, there isn't a way to quickly send headers
  # but then delay the body.
  #
  # Example Rack application:
  #
  #    require 'thread'
  #
  #    class AsyncExample
  #      def call(env)
  #        cb = env['async.callback']
  #
  #        Thread.new do
  #          sleep 5                # long task, wait for message, etc.
  #          body = ['Hello, World!']
  #          cb.call [200, {'Content-Type' => 'text/plain'}, body]
  #        end
  #
  #        throw :async
  #      end
  #    end
  async_context = req.startAsync
  env.on_async_callback do |(status, headers, body)|
    resp = async_context.getResponse
    respond(resp, env, status, headers, body)
    async_context.complete
  end
end

#to_sObject Also known as: servlet_info



45
46
47
# File 'lib/rubylet/servlet.rb', line 45

def to_s
  "#<#{self.class} @app=#{@app}>"
end