ruby-ajp 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/example/dump-server.rb +2 -2
- data/lib/net/ajp13/ajp13cgi.rb +187 -0
- data/lib/net/{ajp13client.rb → ajp13/client.rb} +0 -0
- data/lib/net/{ajp13server.rb → ajp13/server.rb} +25 -19
- data/lib/net/ajp13.rb +8 -8
- data/ruby-ajp.gemspec +2 -3
- data/test/net/test_ajp13cgi.rb +104 -0
- data/test/net/test_ajp13client.rb +1 -1
- data/test/net/test_ajp13request.rb +2 -2
- data/test/net/test_ajp13server.rb +2 -2
- metadata +7 -4
data/Rakefile
CHANGED
data/example/dump-server.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
|
-
require 'net/
|
2
|
+
require 'net/ajp13/server'
|
3
3
|
require 'erb'
|
4
4
|
|
5
5
|
class DumpServer < Net::AJP13::Server
|
@@ -58,7 +58,7 @@ __END__
|
|
58
58
|
<% if req.body_stream %>
|
59
59
|
<% body = req.body_stream.read %>
|
60
60
|
<% if %r(\Atext/) =~ req['content-type'] or
|
61
|
-
req['content-type'] == 'application/x-form-
|
61
|
+
req['content-type'] == 'application/x-www-form-urlencoded' %>
|
62
62
|
<pre><%=h body %></pre>
|
63
63
|
<% else %>
|
64
64
|
<pre><%=[body].pack('m')%></pre>
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'net/ajp13'
|
2
|
+
require 'cgi'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
# The adapter to adapt Net::AJP13::Request and Net::AJP13::Response into
|
6
|
+
# CGI's interface.
|
7
|
+
class Net::AJP13::AJP13CGI
|
8
|
+
include ::CGI::QueryExtension
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def initialize(req)
|
12
|
+
@req = req
|
13
|
+
if req.method == "POST" and
|
14
|
+
%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(req['content-type']) then
|
15
|
+
boundary = $1.dup
|
16
|
+
@multipart = true
|
17
|
+
@params = read_multipart(boundary, req.content_length)
|
18
|
+
elsif req.body_stream and
|
19
|
+
req['content-type'] == 'application/x-www-form-urlencoded'
|
20
|
+
@multipart = false
|
21
|
+
@params = CGI::parse(req.body = req.body_stream.read)
|
22
|
+
req.body_stream = nil
|
23
|
+
elsif qs = query_string
|
24
|
+
@multipart = false
|
25
|
+
@params = CGI::parse(qs)
|
26
|
+
else
|
27
|
+
@multipart = false
|
28
|
+
@params = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
@env_table = self.method(:env)
|
32
|
+
class << @env_table
|
33
|
+
def include?(key)
|
34
|
+
call(key).nil?
|
35
|
+
end
|
36
|
+
alias :key? :include?
|
37
|
+
end
|
38
|
+
@cookies = CGI::Cookie::parse(req['cookie'])
|
39
|
+
end
|
40
|
+
|
41
|
+
# Created AJP13::Response object.
|
42
|
+
attr_reader :response
|
43
|
+
|
44
|
+
MESSAGE_TO_STATUS = {
|
45
|
+
:OK => [200, "OK"],
|
46
|
+
:PARTIAL_CONTENT => [206, "Partial Content"],
|
47
|
+
:MULTIPLE_CHOICES => [300, "Multiple Choices"],
|
48
|
+
:MOVED => [301, "Moved Permanently"],
|
49
|
+
:REDIRECT => [302, "Found"],
|
50
|
+
:NOT_MODIFIED => [304, "Not Modified"],
|
51
|
+
:BAD_REQUEST => [400, "Bad Request"],
|
52
|
+
:AUTH_REQUIRED => [401, "Authorization Required"],
|
53
|
+
:FORBIDDEN => [403, "Forbidden"],
|
54
|
+
:NOT_FOUND => [404, "Not Found"],
|
55
|
+
:METHOD_NOT_ALLOWED => [405, "Method Not Allowed"],
|
56
|
+
:NOT_ACCEPTABLE => [406, "Not Acceptable"],
|
57
|
+
:LENGTH_REQUIRED => [411, "Length Required"],
|
58
|
+
:PRECONDITION_FAILED => [412, "Rrecondition Failed"],
|
59
|
+
:SERVER_ERROR => [500, "Internal Server Error"],
|
60
|
+
:NOT_IMPLEMENTED => [501, "Method Not Implemented"],
|
61
|
+
:BAD_GATEWAY => [502, "Bad Gateway"],
|
62
|
+
:VARIANT_ALSO_VARIES => [506, "Variant Also Negotiates"],
|
63
|
+
}.freeze
|
64
|
+
|
65
|
+
def header(arg = "text/html")
|
66
|
+
if arg.kind_of? String
|
67
|
+
@response = Net::AJP13::Response.new(200)
|
68
|
+
@response['content-type'] = arg
|
69
|
+
elsif arg.respond_to?(:each) and arg.respond_to?(:[])
|
70
|
+
if status = arg['status']
|
71
|
+
raise ArgumentError, "Unrecognized status line format: #{status}" unless /\A(?:([0-9]{3}) )?(\w+)\Z/ =~ status
|
72
|
+
status_line = $1 ? [$1.to_i, $2] : MESSAGE_TO_STATUS[$2.to_sym]
|
73
|
+
raise ArgumentError, "Unrecognized status line: #{status}" unless status_line
|
74
|
+
@response = Net::AJP13::Response.new(status_line[0], :reason_phrase => status_line[1])
|
75
|
+
else
|
76
|
+
@response = Net::AJP13::Response.new(200)
|
77
|
+
end
|
78
|
+
type = nil; charset = nil
|
79
|
+
arg.each do |name, value|
|
80
|
+
case name.downcase
|
81
|
+
when 'nph', 'status'
|
82
|
+
# do nothing
|
83
|
+
when "type"
|
84
|
+
type = value
|
85
|
+
when "charset"
|
86
|
+
charset = value
|
87
|
+
when 'length'
|
88
|
+
@response['content-length'] = value.to_s
|
89
|
+
when 'language'
|
90
|
+
@response['content-language'] = value
|
91
|
+
when 'cookie'
|
92
|
+
case value
|
93
|
+
when String
|
94
|
+
@respose.add_header('set-cookie', value)
|
95
|
+
when Array, Hash
|
96
|
+
value.each {|val| @response.add_header('set-cookie', val.to_s) }
|
97
|
+
end
|
98
|
+
else
|
99
|
+
@response[name] = value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
type = 'text/html' unless type
|
103
|
+
@response['content-type'] = charset ? ("%s; charset=%s" % [type, charset]) : type
|
104
|
+
else
|
105
|
+
raise ArgumentError, "argument is not a String nor Hash"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def output(arg = 'text/html')
|
111
|
+
content = yield
|
112
|
+
header(arg)
|
113
|
+
@response['content-length'] ||= content.length
|
114
|
+
unless content.nil? or @request.method == 'HEAD'
|
115
|
+
@response.body = content
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Method object that contains #env
|
120
|
+
attr_reader :env_table
|
121
|
+
|
122
|
+
# Simulates environment variable table that Common Gateway Interface defines.
|
123
|
+
def env(name)
|
124
|
+
name = name.downcase
|
125
|
+
key = name.to_sym
|
126
|
+
if [
|
127
|
+
:auth_type, :content_length, :content_type, :gateway_interface,
|
128
|
+
:path_info, :path_translated, :query_string, :remote_addr, :remote_host,
|
129
|
+
:remote_ident, :remote_user, :request_method, :request_url, :script_name,
|
130
|
+
:server_name, :server_port, :server_protocol, :server_software
|
131
|
+
].include?(key) then
|
132
|
+
return __send__(key)
|
133
|
+
elsif /\Ahttp_(\w+)\Z/ =~ name
|
134
|
+
return @req[$1.tr('_', '-')]
|
135
|
+
else
|
136
|
+
return nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
private :env
|
140
|
+
|
141
|
+
def_delegators :@req,
|
142
|
+
:content_length, :remote_addr, :remote_host, :server_name, :server_port
|
143
|
+
|
144
|
+
[
|
145
|
+
:auth_type,
|
146
|
+
# :path_info,
|
147
|
+
:path_translated,
|
148
|
+
:remote_ident, :remote_user,
|
149
|
+
:script_name, :server_software
|
150
|
+
].each do |attr_name|
|
151
|
+
define_method(attr_name) do
|
152
|
+
val = @req.get_attributes(attr_name.to_s)
|
153
|
+
val and val[0]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def content_type
|
158
|
+
@req['content-type']
|
159
|
+
end
|
160
|
+
|
161
|
+
def gateway_interface
|
162
|
+
'AJP/1.3'
|
163
|
+
end
|
164
|
+
|
165
|
+
def path_info
|
166
|
+
#val = @req.get_attributes('path_info')
|
167
|
+
#val && val[0] or @req.path
|
168
|
+
@req.path
|
169
|
+
end
|
170
|
+
|
171
|
+
def query_string
|
172
|
+
qs = @req.get_attributes('query_string')
|
173
|
+
qs and qs.join('&')
|
174
|
+
end
|
175
|
+
|
176
|
+
def request_method
|
177
|
+
@req.method
|
178
|
+
end
|
179
|
+
|
180
|
+
def request_url
|
181
|
+
@req.path
|
182
|
+
end
|
183
|
+
|
184
|
+
def server_protocol
|
185
|
+
@req.protocol
|
186
|
+
end
|
187
|
+
end
|
File without changes
|
@@ -83,7 +83,6 @@ class Net::AJP13::Server
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def start(sock = nil)
|
86
|
-
logger.info("Starting #{self.class}")
|
87
86
|
if sock
|
88
87
|
@sock = sock
|
89
88
|
else
|
@@ -96,13 +95,12 @@ class Net::AJP13::Server
|
|
96
95
|
accepted = @sock.accept
|
97
96
|
Thread.new {
|
98
97
|
begin
|
99
|
-
|
100
|
-
|
101
|
-
end
|
98
|
+
accepted.sync = false
|
99
|
+
process(accepted)
|
102
100
|
rescue StandardError => err
|
103
|
-
logger.error("#{err.message} from #{err.backtrace("\n")}")
|
101
|
+
logger.error("#{err.message} from #{err.backtrace.join("\n")}")
|
104
102
|
rescue Object => err
|
105
|
-
logger.fatal("#{err.message} from #{err.backtrace("\n")}")
|
103
|
+
logger.fatal("#{err.message} from #{err.backtrace.join("\n")}")
|
106
104
|
else
|
107
105
|
logger.debug("closed")
|
108
106
|
ensure
|
@@ -133,18 +131,23 @@ class Net::AJP13::Server
|
|
133
131
|
|
134
132
|
# +conn+:: Accepted connection. +conn+ is an IO object or something like it.
|
135
133
|
def process(conn)
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
134
|
+
loop do
|
135
|
+
break unless c = conn.getc
|
136
|
+
conn.ungetc c
|
137
|
+
|
138
|
+
packet = Net::AJP13::Packet.from_io(conn)
|
139
|
+
case packet.message_type
|
140
|
+
when FORWARD_REQUEST
|
141
|
+
process_forward_request(packet, conn)
|
142
|
+
when SHUTDOWN
|
143
|
+
process_shutdown(packet, conn)
|
144
|
+
when PING
|
145
|
+
process_ping(packet, conn)
|
146
|
+
when CPING
|
147
|
+
process_cping(packet, conn)
|
148
|
+
else
|
149
|
+
raise AJPPacketError, "Unrecognized packet type #{packet.message_type}"
|
150
|
+
end
|
148
151
|
end
|
149
152
|
end
|
150
153
|
|
@@ -178,6 +181,7 @@ class Net::AJP13::Server
|
|
178
181
|
conn.write "\x41\x42#{[message.length + 4].pack('n')}\x03#{[message.length].pack('n')}#{message}\x00"
|
179
182
|
else
|
180
183
|
# SEND_HEADERS packet
|
184
|
+
res ||= Net::AJP13::Response.new(500)
|
181
185
|
res['content-length'] ||= res.body.length.to_s if res.body
|
182
186
|
res.send_to conn
|
183
187
|
|
@@ -241,6 +245,7 @@ class Net::AJP13::Server
|
|
241
245
|
@sock = sock
|
242
246
|
@packet = Net::AJP13::Packet.from_io(sock)
|
243
247
|
@length = length
|
248
|
+
packet_content_length = @packet.read_integer
|
244
249
|
@read_length = 0
|
245
250
|
end
|
246
251
|
|
@@ -346,7 +351,8 @@ class Net::AJP13::Server
|
|
346
351
|
# this means eof
|
347
352
|
break
|
348
353
|
else
|
349
|
-
|
354
|
+
packet_content_length = @packet.read_integer
|
355
|
+
chunk = @packet.read_bytes([length - written_length, packet_content_length].min)
|
350
356
|
buf[written_length, chunk.length] = chunk
|
351
357
|
written_length += chunk.length
|
352
358
|
@read_length += chunk.length
|
data/lib/net/ajp13.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# = Ruby/AJP
|
2
|
-
#
|
2
|
+
# Ruby/AJP is an implementation of AJP(Apache Jserv Protocol) 1.3 in Ruby,
|
3
3
|
# based on http://tomcat.apache.org/connectors-doc/common/ajpv13a.html.
|
4
4
|
#
|
5
5
|
# [Net::AJP13::Client] provides high-level API to implement AJP clients.
|
6
|
-
# The interface of
|
6
|
+
# The interface of this client-side library is similar to
|
7
7
|
# net/http.
|
8
8
|
# see ajp13client.rb[link:files/lib/net/ajp13client_rb.html]
|
9
9
|
# for more detail.
|
@@ -33,9 +33,8 @@
|
|
33
33
|
|
34
34
|
require 'net/http'
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
# :startdoc:
|
36
|
+
module Net #:nodoc:
|
37
|
+
end
|
39
38
|
|
40
39
|
module Net::AJP13
|
41
40
|
module Constants
|
@@ -93,7 +92,7 @@ class Net::AJP13::Request
|
|
93
92
|
}.freeze
|
94
93
|
SC_REQ_HEADER_NAMES.each_key {|k| k.freeze}
|
95
94
|
|
96
|
-
SC_A_REQ_ATTRIBUTE =
|
95
|
+
SC_A_REQ_ATTRIBUTE = 0x0A
|
97
96
|
# Maps request attribute names into their codes
|
98
97
|
SC_A_NAMES = {
|
99
98
|
:context => 0x01,
|
@@ -194,7 +193,7 @@ class Net::AJP13::Request
|
|
194
193
|
else
|
195
194
|
header_name = packet.read_string
|
196
195
|
end
|
197
|
-
req
|
196
|
+
req.add_field(header_name, packet.read_string)
|
198
197
|
end
|
199
198
|
loop do
|
200
199
|
case attr_name = packet.read_byte
|
@@ -252,6 +251,7 @@ class Net::AJP13::Request
|
|
252
251
|
# HTTP-side connection is over SSL or not.
|
253
252
|
attr_accessor :is_ssl
|
254
253
|
alias :is_ssl? :is_ssl
|
254
|
+
alias :ssl? :is_ssl
|
255
255
|
def is_ssl=(value) #:nodoc:
|
256
256
|
@is_ssl = !!value
|
257
257
|
end
|
@@ -562,7 +562,7 @@ end
|
|
562
562
|
class Net::AJP13::AJPPacketError < IOError
|
563
563
|
end
|
564
564
|
|
565
|
-
# :
|
565
|
+
# :enddoc:
|
566
566
|
# Represents AJP1.3 Packet
|
567
567
|
class Net::AJP13::Packet
|
568
568
|
include Net::AJP13::Constants
|
data/ruby-ajp.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "ruby-ajp"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "0.2.0"
|
4
4
|
spec.required_ruby_version = ">= 1.8.3"
|
5
5
|
spec.summary = "An implementation of Apache Jserv Protocol 1.3 in Ruby"
|
6
6
|
spec.author = "Yugui"
|
@@ -20,8 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
"COPYING"
|
21
21
|
spec.files.reject! {|fn| fn.include?('.svn') }
|
22
22
|
spec.test_files = [
|
23
|
-
'packet', 'request',
|
24
|
-
'response', 'client'
|
23
|
+
'packet', 'request', 'response', 'client', 'server'
|
25
24
|
].map{|x| "test/net/test_ajp13#{x}.rb"}
|
26
25
|
spec.has_rdoc = true
|
27
26
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'stringio'
|
3
|
+
require File.dirname(__FILE__) + "/../../lib/net/ajp13/ajp13cgi.rb"
|
4
|
+
|
5
|
+
class Net::AJP13::AJP13CGITest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@encoded_body =
|
8
|
+
"test%5Bfirst%5Fname%5D=foo" +
|
9
|
+
"&test%5blast%5Fname%5D=bar+hoge" +
|
10
|
+
"&test%5Bemail%5D=foo%2Dbar%40yet%2Eanother%2Edomain%2Etest" +
|
11
|
+
"&key+with+SP=huga" +
|
12
|
+
"&nanika=unyuu" +
|
13
|
+
"&last=%5Ce" +
|
14
|
+
""
|
15
|
+
@encoded_body.freeze
|
16
|
+
@qs = "last=%5Cufin.%5Ce"
|
17
|
+
|
18
|
+
req = Net::AJP13::PostRequest.new('/path/to/resource')
|
19
|
+
req.server_name = 'www.domain.test'
|
20
|
+
req.server_port = 8181
|
21
|
+
req.is_ssl = true
|
22
|
+
req.body_stream = StringIO.new(@encoded_body)
|
23
|
+
req['Host'] = 'www.domain.test'
|
24
|
+
req['Content-Length'] = @encoded_body.length.to_s
|
25
|
+
req['Content-Type'] = 'application/x-www-form-urlencoded'
|
26
|
+
req['Content-Language'] = 'ja-JP'
|
27
|
+
req['User-Agent'] = @ua = "testcase #{__FILE__}:#{__LINE__}"
|
28
|
+
req.set_attribute('QUERY_STRING', @qs)
|
29
|
+
|
30
|
+
@cgi = Net::AJP13::AJP13CGI.new(req)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_at
|
34
|
+
assert_equal 'foo', @cgi['test[first_name]']
|
35
|
+
assert_equal 'bar hoge', @cgi['test[last_name]']
|
36
|
+
assert_equal 'foo-bar@yet.another.domain.test', @cgi['test[email]']
|
37
|
+
assert_equal 'huga', @cgi['key with SP']
|
38
|
+
assert_equal 'unyuu', @cgi['nanika']
|
39
|
+
assert_equal '\e', @cgi['last']
|
40
|
+
assert_equal '', @cgi['test[invalid_key]']
|
41
|
+
assert_equal '', @cgi['']
|
42
|
+
|
43
|
+
assert_equal '', @cgi['Test[first_name]'] # case sensitive
|
44
|
+
assert_equal '', @cgi['test[Last_name]'] # case sensitive
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_has_key?
|
48
|
+
assert @cgi.has_key?('test[first_name]')
|
49
|
+
assert @cgi.has_key?('test[last_name]')
|
50
|
+
assert @cgi.has_key?('test[email]')
|
51
|
+
assert @cgi.has_key?('key with SP')
|
52
|
+
assert !@cgi.has_key?('test[invalid_key]')
|
53
|
+
assert !@cgi.has_key?('')
|
54
|
+
|
55
|
+
assert !@cgi.has_key?('Test[first_name]')
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_env_table
|
59
|
+
assert_equal @encoded_body.length, @cgi.env_table['CONTENT_LENGTH']
|
60
|
+
assert_equal 8181, @cgi.env_table['SERVER_PORT']
|
61
|
+
assert_equal 'www.domain.test', @cgi.env_table['HTTP_HOST']
|
62
|
+
assert_equal @qs, @cgi.env_table['Query_String']
|
63
|
+
assert_equal 'application/x-www-form-urlencoded', @cgi.env_table['content_type']
|
64
|
+
assert_equal 'AJP/1.3', @cgi.env_table['gateway_interface']
|
65
|
+
assert_equal @ua, @cgi.env_table['HTTP_USER_AGENT']
|
66
|
+
assert_equal 'ja-JP', @cgi.env_table['HTTP_CONTENT_LANGUAGE']
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_params
|
70
|
+
assert_equal ['foo'], @cgi.params['test[first_name]']
|
71
|
+
assert_equal ['bar hoge'], @cgi.params['test[last_name]']
|
72
|
+
assert_equal ['foo-bar@yet.another.domain.test'], @cgi.params['test[email]']
|
73
|
+
assert_equal ['huga'], @cgi.params['key with SP']
|
74
|
+
assert_equal ['unyuu'], @cgi.params['nanika']
|
75
|
+
assert_equal ['\e'], @cgi.params['last']
|
76
|
+
assert_equal [], @cgi.params['test[invalid_key]']
|
77
|
+
assert_equal [], @cgi.params['']
|
78
|
+
|
79
|
+
assert_equal [], @cgi.params['Test[first_name]'] # case sensitive
|
80
|
+
assert_equal [], @cgi.params['test[Last_name]'] # case sensitive
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_header_0
|
84
|
+
assert_nil @cgi.response
|
85
|
+
@cgi.header
|
86
|
+
assert_equal 'text/html', @cgi.response['Content-Type']
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_header_1
|
90
|
+
assert_nil @cgi.response
|
91
|
+
@cgi.header('text/plain')
|
92
|
+
assert_equal 'text/plain', @cgi.response['Content-Type']
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_header
|
96
|
+
assert_nil @cgi.response
|
97
|
+
@cgi.header(
|
98
|
+
"status" => "200 OK",
|
99
|
+
"charset" => "EUC-KR"
|
100
|
+
)
|
101
|
+
assert_equal 'text/html; charset=EUC-KR', @cgi.response['Content-Type']
|
102
|
+
assert_equal 'OK', @cgi.response.message
|
103
|
+
end
|
104
|
+
end
|
@@ -159,8 +159,8 @@ class Net::AJP13::RequestTest < Test::Unit::TestCase
|
|
159
159
|
assert_equal "deflate, gzip, x-gzip, identity, *;q=0", value
|
160
160
|
when 'cookie'
|
161
161
|
assert_block {
|
162
|
-
"JSESSIONID=
|
163
|
-
|
162
|
+
"JSESSIONID=54104A3A775650CEF8967D263F1A7193, $Version=1" == value or
|
163
|
+
"$Version=1, JSESSIONID=54104A3A775650CEF8967D263F1A7193" == value
|
164
164
|
}
|
165
165
|
when 'cache-control'
|
166
166
|
assert_equal "no-cache", value
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'stringio'
|
3
|
-
require File.dirname(__FILE__) + '/../../lib/net/
|
3
|
+
require File.dirname(__FILE__) + '/../../lib/net/ajp13/server'
|
4
4
|
|
5
5
|
class Net::AJP13::Server
|
6
6
|
unless method_defined?(:fcall)
|
@@ -26,7 +26,7 @@ class Net::AJP13::Server::BodyInputTest < Test::Unit::TestCase
|
|
26
26
|
class MockSocket
|
27
27
|
def initialize(contents)
|
28
28
|
@bodies = (
|
29
|
-
contents.map{|c|
|
29
|
+
contents.map{|c|"\x12\x34#{[c.length+2, c.length].pack('nn')}" + c } <<
|
30
30
|
"\x12\x34\x00\x00"
|
31
31
|
).map {|str| StringIO.new(str)}
|
32
32
|
@write_buf = ''
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-ajp
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-01-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2006-01-24 00:00:00 +09:00
|
8
8
|
summary: An implementation of Apache Jserv Protocol 1.3 in Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -28,9 +28,11 @@ cert_chain:
|
|
28
28
|
authors:
|
29
29
|
- Yugui
|
30
30
|
files:
|
31
|
-
- lib/net/ajp13server.rb
|
32
31
|
- lib/net/ajp13.rb
|
33
|
-
- lib/net/
|
32
|
+
- lib/net/ajp13/server.rb
|
33
|
+
- lib/net/ajp13/ajp13cgi.rb
|
34
|
+
- lib/net/ajp13/client.rb
|
35
|
+
- test/net/test_ajp13cgi.rb
|
34
36
|
- test/net/test_ajp13request.rb
|
35
37
|
- test/net/test_ajp13server.rb
|
36
38
|
- test/net/test_ajp13response.rb
|
@@ -59,6 +61,7 @@ test_files:
|
|
59
61
|
- test/net/test_ajp13request.rb
|
60
62
|
- test/net/test_ajp13response.rb
|
61
63
|
- test/net/test_ajp13client.rb
|
64
|
+
- test/net/test_ajp13server.rb
|
62
65
|
rdoc_options: []
|
63
66
|
|
64
67
|
extra_rdoc_files: []
|