forked from jruby/jruby-rack
-
Notifications
You must be signed in to change notification settings - Fork 7
/
servlet.rb
187 lines (158 loc) · 5.31 KB
/
servlet.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#--
# Copyright (c) 2010-2011 Engine Yard, Inc.
# Copyright (c) 2007-2009 Sun Microsystems, Inc.
# This source code is available under the MIT license.
# See the file LICENSE.txt for details.
#++
require 'jruby/rack'
require 'jruby/rack/version'
module Rack
module Handler
class Servlet
def initialize(rack_app)
@rack_app = rack_app
end
def call(servlet_env)
JRuby::Rack::Response.new(@rack_app.call(create_env(servlet_env)))
end
def create_env(servlet_env)
Env.new(servlet_env).to_hash
end
def create_lazy_env(servlet_env)
LazyEnv.new(servlet_env).to_hash
end
end
class Env
BUILTINS = %w(rack.version rack.multithread rack.multiprocess rack.run_once
rack.input rack.errors rack.url_scheme java.servlet_request java.servlet_context
jruby.rack.version jruby.rack.jruby.version jruby.rack.rack.release)
REQUEST = %w(CONTENT_TYPE CONTENT_LENGTH REQUEST_METHOD SCRIPT_NAME REQUEST_URI
PATH_INFO QUERY_STRING SERVER_NAME SERVER_SOFTWARE REMOTE_HOST REMOTE_ADDR REMOTE_USER SERVER_PORT)
def initialize(servlet_env)
@env = populate(LazyEnv.new(servlet_env).to_hash)
end
def populate(lazy_hash)
hash = {}
(BUILTINS + REQUEST).each {|k| lazy_hash[k]} # load builtins and request vars
lazy_hash['HTTP_'] # load headers
lazy_hash.keys.each {|k| hash[k] = lazy_hash[k]}
hash
end
def to_hash
@env
end
end
class LazyEnv
def initialize(servlet_env)
@env = Hash.new {|h,k| load_env_key(h,k)}
@servlet_env = servlet_env
load_servlet_request_attributes
end
def to_hash
@env
end
def load_env_key(env, key)
if respond_to?("load__#{key}")
send("load__#{key}", env)
elsif key =~ /^(rack|java|jruby)/
load_builtin(env, key)
elsif key =~ /^HTTP_/
load_headers(env, key)
end
end
def load_servlet_request_attributes
@servlet_env.getAttributeNames.each do |k|
v = @servlet_env.getAttribute(k)
case k
when "SERVER_PORT", "CONTENT_LENGTH"
@env[k] = v.to_s if v.to_i >= 0
when "CONTENT_TYPE"
@env[k] = v if v
else
if v
@env[k] = v
else
@env[k] = ""
end
end
end
end
def load_headers(env, key)
unless @headers_added
@headers_added = true
@servlet_env.getHeaderNames.each do |h|
next if h =~ /^Content-(Type|Length)$/i
k = "HTTP_#{h.upcase.gsub(/-/, '_')}"
env[k] = @servlet_env.getHeader(h) unless env.has_key?(k)
end
end
if env.has_key?(key)
env[key]
else
nil
end
end
def load_builtin(env, key)
case key
when 'rack.version' then env[key] = ::Rack::VERSION
when 'rack.multithread' then env[key] = true
when 'rack.multiprocess' then env[key] = false
when 'rack.run_once' then env[key] = false
when 'rack.input' then env[key] = @servlet_env.to_io
when 'rack.errors' then env[key] = JRuby::Rack::ServletLog.new
when 'rack.url_scheme'
scheme = env[key] = @servlet_env.getScheme
env['HTTPS'] = 'on' if scheme == 'https'
when 'java.servlet_request' then env[key] = @servlet_env.getRequest rescue @servlet_env
when 'java.servlet_context' then env[key] = $servlet_context
when 'jruby.rack.version' then env[key] = JRuby::Rack::VERSION
when 'jruby.rack.jruby.version' then env[key] = JRUBY_VERSION
when 'jruby.rack.rack.release' then env[key] = ::Rack.release
else
nil
end
end
def load__CONTENT_TYPE(env)
content_type = @servlet_env.getContentType
env["CONTENT_TYPE"] = content_type if content_type
end
def load__CONTENT_LENGTH(env)
content_length = @servlet_env.getContentLength
env["CONTENT_LENGTH"] = content_length.to_s if content_length >= 0
end
def load__REQUEST_METHOD(env)
env["REQUEST_METHOD"] = @servlet_env.getMethod || "GET"
end
def load__SCRIPT_NAME(env)
env["SCRIPT_NAME"] = @servlet_env.getScriptName
end
def load__REQUEST_URI(env)
env["REQUEST_URI"] = @servlet_env.getRequestURI
end
def load__PATH_INFO(env)
env["PATH_INFO"] = @servlet_env.getPathInfo
end
def load__QUERY_STRING(env)
env["QUERY_STRING"] = @servlet_env.getQueryString || ""
end
def load__SERVER_NAME(env)
env["SERVER_NAME"] = @servlet_env.getServerName || ""
end
def load__REMOTE_HOST(env)
env["REMOTE_HOST"] = @servlet_env.getRemoteHost || ""
end
def load__REMOTE_ADDR(env)
env["REMOTE_ADDR"] = @servlet_env.getRemoteAddr || ""
end
def load__REMOTE_USER(env)
env["REMOTE_USER"] = @servlet_env.getRemoteUser || ""
end
def load__SERVER_PORT(env)
env["SERVER_PORT"] = @servlet_env.getServerPort.to_s
end
def load__SERVER_SOFTWARE(env)
env["SERVER_SOFTWARE"] = @servlet_env.context.getServerInfo
end
end
end
end