How to correctly use built-in XMLRPC in Ruby? - ruby

I'm trying to use built-in XMLRPC in Ruby 1.9. Unfortunately, XMLRPC is not documented on ruby-docs.org, so i have tried to build a test code based on examples found by google:
# Server.rb
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )
server.add_handler( "test" ) { |msg| return "responce for #{msg}" }
server.serve()
# Client.rb
require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
server.call( "test", 42 ) == "responce for 42"
Unfortunately, this is not working on both Windows and OSX. Server.rb fails with cryptic error:
C:/Ruby193/lib/ruby/1.9.1/xmlrpc/client.rb:414:in `call': Uncaught exception unexpected return in method test (XMLRPC::FaultException)
from client.rb:6:in `<main>'
Maybe anyone knows what is my error?

Its another way with block:
#server.rb:
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )
server.add_handler('my_test.test') { |msg|"responce for #{msg}" }
#client.rb
require "xmlrpc/client"
client = XMLRPC::Client.new( "localhost", "/", 1234 )
s = client.call('my_test.test','asd')

You got it almost right. Here is a tutorial you can use. Your example needs a little modification, you have to pass an object to add_handler that will be used to serve your RPC calls:
# server.rb
require "xmlrpc/server"
class MyClass
def dosomething(a)
"response for #{a}"
end
end
server = XMLRPC::Server.new( 1234 )
server.add_handler( "test", MyClass.new )
server.serve
# client.rb
require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
puts server.call( "test.dosomething", 42 ) == "response for 42"

Please note: the default xmlrpc/client.rb impl. doesn't support client certificates based https connections. If you want it you must either use different lib or patch client.rb with something like:
# HG changeset patch
# User Anonymous Coward <anonymous#gmail.com>
# Date 1338149770 -10800
# Node ID f0557306c8e4f113507fb3bab8567391949fa302
# Parent 3eae8e8f9e065ff6cdf1c95092ad5cca635c9eac
patch client.rb to support https with client certificate.
diff -r 3eae8e8f9e06 -r f0557306c8e4 client.rb
--- a/client.rb Sun May 27 22:20:18 2012 +0300
+++ b/client.rb Sun May 27 23:16:10 2012 +0300
## -292,8 +292,8 ##
# Constructors -------------------------------------------------------------------
- def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
- user=nil, password=nil, use_ssl=nil, timeout=nil)
+ def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
+ user=nil, password=nil, use_ssl=nil, timeout=nil, cacert=nil, cert=nil, key=nil)
#http_header_extra = nil
#http_last_response = nil
## -311,6 +311,10 ##
if use_ssl
require "net/https"
#port = port || 443
+ #cacert = cacert
+ #cert = cert
+ #key = key
+
else
#port = port || 80
end
## -325,8 +329,19 ##
# HTTP object for synchronous calls
Net::HTTP.version_1_2
- #http = Net::HTTP.new(#host, #port, #proxy_host, #proxy_port)
- #http.use_ssl = #use_ssl if #use_ssl
+ #http = Net::HTTP.new(#host, #port, #proxy_host, #proxy_port)
+ if #use_ssl
+ #http.use_ssl = #use_ssl
+ if nil != #cacert
+ #http.ca_file = #cacert
+ #http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ #http.verify_depth = 5
+ else
+ #http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
+ #http.cert = #cert
+ #http.key = #key
+ end
#http.read_timeout = #timeout
#http.open_timeout = #timeout
## -366,7 +381,7 ##
hash.each { |k,v| h[k.to_s.downcase] = v }
self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'],

I think this could help:
http://www.ntecs.de/ruby/xmlrpc4r/howto.html
#server.rb
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )
class MyHandler
def test(msg)
"message #{msg}"
end
end
server.add_handler(XMLRPC::iPIMethods("my_test"), MyHandler.new)
server.serve
#client.rb
require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
s = server.call('my_test.test','hello!')

Related

ruby `rescue in block in connect': Failed to open TCP connection to api

I am fairly new to ruby and I am having issues using code that I found on this
github. It is meant to use the Whitepages API to use their service and I am using it to do a reverse phone lookup. Here is my whitepages.rb file:
require 'json'
require 'net/https'
require 'uri'
class Whitepages
#Initialize the Whitepages class
# * api_key - The API key obtained from the Whitpages Developer website
def initialize(api_key)
api_version = "1.0"
#api_key = api_key
#base_uri = "http://api.whitepages.com/"
#find_person_uri = #base_uri + "find_person/" + api_version + "/?"
#reverse_phone_uri = #base_uri + "reverse_phone/" + api_version + "/?"
#reverse_address_uri = #base_uri + "reverse_address/" + api_version + "/?"
#uri = URI.parse(#base_uri)
#http = Net::HTTP.new(#uri.host, #uri.port)
end
#Retrieves contact information about a telephone number
#Accepts a hash:
# * phone - May be 7 digits if state provided otherwise 10 (*REQUIRED*)
# * state - Two digit code for the state
#More details may be found here: http://developer.whitepages.com/docs/Methods/reverse_phone
def reverse_phone(options)
resp, data = #http.get(build_uri(options, "reverse_phone"))
if resp.code== 200
return JSON.parse(data)
else
raise Exception,"code",resp.code
end
end
#Build the appropriate URL
def build_uri(options, type)
case type
when "reverse_phone"
built_uri = #reverse_phone_uri
when "reverse_address"
built_uri = #reverse_address_uri
when "find_person"
built_uri = #find_person_uri
end
options.each do |key,value|
if value != nil
built_uri = built_uri + key + "=" + value.gsub(' ', '%20') + ";"
end
end
built_uri = built_uri + "api_key=" + #api_key + ";outputtype=JSON"
return built_uri
end
end
And here is the class I use to test the code:
require 'rubygems'
require './whitepages'
API_KEY = MY ACTUAL API KEY AS A STRING
wp = Whitepages.new(API_KEY)
data = wp.reverse_phone({ "phone" => "4155551212",
"state" => "CA" })
When I run this file, I get the error: rescue in block in connect': Failed to open TCP connection to api.whitepages.com:80 (getaddrinfo: Name or service not known) (SocketError)
I can't find anything online specifically about connecting to APIs that would help me. Please, any help is greatly appreciated. PS: If you need to test the code, it does not take long at all to get a free API key from whitepages.com

How to make persistent HTTP requests using multiple threads in Ruby/Faraday?

I'm using faraday with net-http-persistent adapter to make HTTP requests.
I want to optimise my requests by making them execute asynchronously but as I need a persistent connection I keep getting errors such as too many connections reset which I assume is due to the fact that I have multiple threads creating new connections.
I tried changing my adapter to typhoeus but as the connection is not persistent the final result of executing all request is not as expected.
My goal is to add items to a basket by making this HTTP requests. Without the persistent connection items are not added to the basket.
So, my question is:
Is it possible to make persistent HTTP requests reusing the connection between threads? If so, how can this be achieved?
Here is a piece of my code:
Create the connection:
Faraday.new do |c|
c.use :cookie_jar, jar: cookie_jar
c.options.open_timeout = 5
c.options.timeout = 10
c.request :url_encoded
c.response :logger, logger
c.adapter :net_http_persistent do |http| # yields Net::HTTP::Persistent
http.idle_timeout = 2
end
end
Creating threads and getting the result of each one of them
result = []
threads = []
total_items = items.size
items.each_slice(5) do |sliced_items|
# Create a thread for a batch of 5 items and store its result
threads << Thread.new do
Thread.current[:output] = browser.add_all_items(sliced_items)
end
end
# Wait for all threads to finish their work and store their output into result
threads.each do |t|
t.join
result << t[:output]
end
add_all_items and add_to_cart methods:
# Add a batch of items by the key passed (id, gtin, url)
def add_all_items(items_info, key)
results = []
items_info.each do |item|
begin
add_to_cart(item[key], item[:quantity])
item[:message] = nil
rescue => e
item[:message] = e.message
puts "---------- BACKTRACE -------------- \n #{e.backtrace}"
end
puts "\n--------- MESSAGE = #{item[:message]} --------- \n"
results << item
puts "-------- RESULTS #{results}"
end
results
end
def add_to_cart(url, count = 1)
response = connection.get(url) do |req|
req.headers["User-Agent"] = #user_agent
end
doc = Nokogiri::HTML(response.body)
stoken = doc.search('form.js-oxProductForm input[name=stoken]').attr('value').value
empty_json = '""'
product_id = get_item_id(url)
data = { #removed payload for security reasons }
# Using example.com for question purposes
response = connection.post('https://www.example.com/index.php?') do |req|
req.headers["Origin"] = "https://www.example.com"
req.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
req.headers["Accept"] = "application/json, text/javascript, */*; q=0.01"
req.headers["Referer"] = url
req.headers["Pragma"] = "no-cache"
req.headers["Accept-Language"] = "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"
req.headers["User-Agent"] = #user_agent
req.headers["Cache-Control"] = "no-cache"
req.headers["Connection"] = "keep-alive"
req.headers["DNT"] ="1"
req.headers["Content-Length"] = data.size.to_s
req.headers["Accept"] = "*/*"
req.headers["X-Requested-With"] = "XMLHttpRequest"
req.headers["Connection"] = "keep-alive"
req.body = data
end
begin
json = JSON.parse(response.body)
raise "Could not add item: #{json['message']}" if json['success'] != 1 || json['item'] != product_id
rescue JSON::ParserError => e
puts "JSON Error"
end
end
def get_item_id(url)
response = connection.get(url) do |req|
req.headers["User-Agent"] = #user_agent
end
doc = Nokogiri::HTML(response.body)
doc.search('.js-oxProductForm input[name=aid]').attr('value').value
end
Thanks in advance.

Why won't my server open files?

I've been working on this code and for some reason the server can't open the index file, and I can't understand why. I've checked other people's code and there doesn't look like there is a difference.
Here is my code:
require 'socket'
class Server
def initialize (base, request, server_name, session, charset)
#base = base
#request = request
#charset = charset
#server_name = server_name
#session = session
serve()
end
def serve ()
access_log()
getAddress()
#contentType = getContentType()
#session.print "HTTP/1.1 200 OK\r\nServer: #{#server_name}\r\nContent-Type: #{#contentType}; charset=#{charset}\r\n\r\n"
getFile()
#base = nil
#request = nil
#server_name = nil
#contentType
#session.close
puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#session = nil
end
def access_log ()
log = File.open(#base + "data/access_log.txt", "w")
log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{#session.peeraddr[2]}:#{#session.peeraddr[1]} #{#request}" unless log == nil
log.close
log = nil
end
def getAddress ()
#src = #request
#src.gsub!(/GET /, '').gsub!(/ HTTP.*/, '')
#src.strip
#src = #base + "root" + #src
#src.gsub!('/', '\\')
end
def getContentType ()
ext = nil
ext = File.extname(#src)
return "text/html" if ext == ".html" or ext == ".htm"
return "text/plain" if ext == ".txt"
return "text/css" if ext == ".css"
return "image/jpeg" if ext == ".jpeg" or ext == ".jpg"
return "image/gif" if ext == ".gif"
return "image/bmp" if ext == ".bmp"
return "text/plain" if ext == ".rb"
return "text/xml" if ext == ".xml"
return "text/xml" if ext == ".xsl"
#return "image/x-icon" if ext == ".ico" or ext == ".icon"
return "text/html"
end
def getFile ()
begin
if !File.exist?(#src)
puts "File: #{#src} could not be found"
if #contentType.include?("image")
file = File.open(#base + "root/server_files/broken_image.png", "r").each do |code|
#session.puts code
end
else
file = File.open(#base + "root/server_files/error404.html", "r").each do |code|
#session.puts code
end
end
else
puts "File #{#src} was opened"
file = File.open(#src, "r").each do |code|
#session.puts code
end
end
ensure
file.close unless file == nil
end
end
end
base = "C:\\Base\\"
server_name = "Some Server"
host = "localhost"
port = 80
charset = "UFT-8"
server = TCPServer.new(host, port)
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n"
loop {
Thread.new(server.accept) do |session|
request = session.gets
puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}"
Server.new(base, request, server_name, session, charset)
end
}
p = gets.chomp
server.close
There are problems with the code. I don't know if these directly cause the problem, but there's enough code smell that the following untested changes might help.
Don't use CamelCase method names in Ruby. We use snake_case.
require 'socket'
class Server
def initialize(base, request, server_name, session, charset)
#base = base
#request = request
#charset = charset
#server_name = server_name
#session = session
serve()
end
def serve
access_log
get_address()
#content_type = get_content_type()
#session.print "HTTP/1.1 200 OK\r\nServer: #{#server_name}\r\nContent-Type: #{#content_type}; charset=#{charset}\r\n\r\n"
get_file()
#content_type
#session.close
puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#base = #request = #server_name = #session = nil
end
I don't know why you have #content_type on its own line prior to #session.close. It's not a method call, nor does it look like it's going to return anything to the server or the outgoing data-stream.
def access_log
File.open(File.join(#base, "data/access_log.txt"), "w") do |log|
log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{#session.peeraddr[2]}:#{#session.peeraddr[1]} #{#request}"
end
end
Ruby's File.open takes a block. When the block exits the file will be closed automatically. File.join is the proper way to build a path. Ruby is aware of the proper path delimiters and will use them automatically, helping to make your code more portable.
def get_address
src = #request.gsub(/GET /, '').gsub(/ HTTP.*/, '').strip
#src = (#base + "root" + src).gsub('/', '\\')
end
You're doing a lot of gsub! for no reason. Chain them, combine the string, do a final gsub and move on.
def get_content_type()
ext = File.extname(#src)
content_type = case ext
when /\.html?/
"text/html"
when ".txt"
"text/plain"
when ".css"
"text/css"
when /\.jpe?g/
"image/jpeg"
when ".gif"
"image/gif"
when ".bmp"
"image/bmp"
when ".rb"
"text/plain"
when /\.x[ms]l/
"text/xml"
else
"text/html"
end
content_type
end
It's confusing to have multiple returns in a sub-routine or method, so this cleans it up. The final content_type will be returned as the result of the method call. Using case/when lets you use multiple tests for each when, reducing line-noise.
def get_file()
begin
if !File.exist?(#src)
puts "File: #{#src} could not be found"
if #content_type["image"]
File.open(File.join(#base, "root", "server_files", "broken_image.png"), "rb") do |image|
#session.puts image.read
end
else
File.foreach(File.join(#base, "root", "server_files", "error404.html")) do |li|
#session.puts li
end
end
else
puts "File #{#src} was opened"
File.foreach(#src) do |li|
#session.puts li
end
end
rescue Exception => e
puts e.message
end
end
When you want to read a binary file, such as "broken_image.png", ALWAYS open it in binary mode: "rb". Otherwise, Ruby will assume it's OK to translate line-endings to the native format for the OS, which would corrupt the data. Also, again, use the block-forms of the File methods so they automatically close. And, use File.join for portability. When you're reading a text file, use File.foreach to read it line-by-line, unless you KNOW it will fit into the available memory; "Slurping" your files is bad form because it isn't scalable.
end
base = "C:/Base/"
server_name = "Some Server"
host = "localhost"
port = 80
charset = "UFT-8"
server = TCPServer.new(host, port)
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n"
loop {
Thread.new(server.accept) do |session|
request = session.gets
puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}"
Server.new(base, request, server_name, session, charset)
end
}
p = gets.chomp
server.close
The code changes are available at: https://gist.github.com/anonymous/6515451

Trying to create a simple Ruby server over SSL

I am trying to create a simple SSL client and server in Ruby. But I'm getting a cryptic error message and the documentation is of no help.
Here is my server code:
#!/usr/bin/ruby
require "gserver"
require "openssl"
listeningPort = Integer(ARGV[0])
class Server < GServer
def initialize(listeningPort)
#sslContext = OpenSSL::SSL::SSLContext.new
#sslContext.cert = OpenSSL::X509::Certificate.new(File.open("MyCert.pem"))
super(listeningPort, "0.0.0.0")
end
def serve(io)
begin
ssl = OpenSSL::SSL::SSLSocket.new(io, #sslContext)
ssl.sync_close = true
ssl.connect
while (lineIn = ssl.gets)
lineIn = lineIn.chomp
$stdout.puts "=> " + lineIn
lineOut = "You said: " + lineIn
$stdout.puts "<= " + lineOut
ssl.puts lineOut
end
rescue
$stderr.puts $!
end
end
end
server = Server.new(listeningPort)
server.start
server.join
The client code is similar:
#!/usr/bin/ruby
require "socket"
require "thread"
require "openssl"
host = ARGV[0]
port = Integer(ARGV[1])
socket = TCPSocket.new(host, port)
sslContext = OpenSSL::SSL::SSLContext.new
sslContext.cert = OpenSSL::X509::Certificate.new(File.open("MyCert.pem"))
ssl = OpenSSL::SSL::SSLSocket.new(socket, sslContext)
ssl.sync_close = true
ssl.connect
puts ssl.peer_cert # this is nil
Thread.new {
begin
while lineIn = ssl.gets
lineIn = lineIn.chomp
$stdout.puts lineIn
end
rescue
$stderr.puts "Error in input loop: " + $!
end
}
while (lineOut = $stdin.gets)
lineOut = lineOut.chomp
ssl.puts lineOut
end
When I connect, I get this error on both the server and the client:
in `connect': SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol (OpenSSL::SSL::SSLError)
The problem could be that it doesn't trust the certificate (self-signed). I'm not sure how to tell the client to trust that certificate. Above, I have put the server's cert in the context, but that was just a shot in the dark. I'm not even sure my certificate is in an acceptable format (it is in base64 with the cert and the private key in the file). The documentation is very scant and there doesn't seem to be much on the web in this area either.
Any ideas?
I figured it out, thanks to that link to some decent documentation.
For one thing, SSLSocket.connect() is only meant to be called on the client.
But the main problem is that I'm trying to take a GServer socket and upgrade it to SSL. Instead, I should use OpenSSL::SSL::SSLServer.
Also, I separated my certificate and private key into two files.
Here is the working server:
#!/usr/bin/ruby
require "socket"
require "openssl"
require "thread"
listeningPort = Integer(ARGV[0])
server = TCPServer.new(listeningPort)
sslContext = OpenSSL::SSL::SSLContext.new
sslContext.cert = OpenSSL::X509::Certificate.new(File.open("cert.pem"))
sslContext.key = OpenSSL::PKey::RSA.new(File.open("priv.pem"))
sslServer = OpenSSL::SSL::SSLServer.new(server, sslContext)
puts "Listening on port #{listeningPort}"
loop do
connection = sslServer.accept
Thread.new {
begin
while (lineIn = connection.gets)
lineIn = lineIn.chomp
$stdout.puts "=> " + lineIn
lineOut = "You said: " + lineIn
$stdout.puts "<= " + lineOut
connection.puts lineOut
end
rescue
$stderr.puts $!
end
}
end
And client:
#!/usr/bin/ruby
require "socket"
require "thread"
require "openssl"
host = ARGV[0]
port = Integer(ARGV[1])
socket = TCPSocket.new(host, port)
expectedCert = OpenSSL::X509::Certificate.new(File.open("cert.pem"))
ssl = OpenSSL::SSL::SSLSocket.new(socket)
ssl.sync_close = true
ssl.connect
if ssl.peer_cert.to_s != expectedCert.to_s
stderrr.puts "Unexpected certificate"
exit(1)
end
Thread.new {
begin
while lineIn = ssl.gets
lineIn = lineIn.chomp
$stdout.puts lineIn
end
rescue
$stderr.puts "Error in input loop: " + $!
end
}
while (lineOut = $stdin.gets)
lineOut = lineOut.chomp
ssl.puts lineOut
end
if you need to provide intermediate certificates, set sslContext.extra_chain_cert with them.
If use have letsencrypt certificates, use your fullchain.pem for sslContext.cert, privkey.pem for sslContext.key and ["chain.pem"] for sslContext.extra_chain_cert. Doing so, you can also test the connection to the server from your browser, with full chain verification.
Note: this complements the author's answer https://stackoverflow.com/a/5873796/533510 , but it was rejected by user #joe , because he understands that this is not a complement for the question. If you agree to him, try using this answer as solution to the question!

streaming html from webrick?

Has anyone tried streaming html/text/content from webrick? I've tried assigning an IO to the response body, but webrick is waiting for the stream to be closed first.
found this link by accident (http://redmine.ruby-lang.org/attachments/download/161) which contains webrick patch
# Copyright (C) 2008 Brian Candler, released under Ruby Licence.
#
# A collection of small monkey-patches to webrick.
require 'webrick'
module WEBrick
class HTTPRequest
# Generate HTTP/1.1 100 continue response. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18459
def continue
if self['expect'] == '100-continue' && #config[:HTTPVersion] >= "1.1"
#socket.write "HTTP/#{#config[:HTTPVersion]} 100 continue\r\n\r\n"
#header.delete('expect')
end
end
end
class HTTPResponse
alias :orig_setup_header :setup_header
# Correct termination of streamed HTTP/1.1 responses. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18454 and
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18565
def setup_header
orig_setup_header
unless chunked? || #header['content-length']
#header['connection'] = "close"
#keep_alive = false
end
end
# Allow streaming of zipfile entry. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18460
def send_body(socket)
if #body.respond_to?(:read) then send_body_io(socket)
elsif #body.respond_to?(:call) then send_body_proc(socket)
else send_body_string(socket)
end
end
# If the response body is a proc, then we invoke it and pass in
# an object which supports "write" and "<<" methods. This allows
# arbitary output streaming.
def send_body_proc(socket)
if #request_method == "HEAD"
# do nothing
elsif chunked?
#body.call(ChunkedWrapper.new(socket, self))
_write_data(socket, "0#{CRLF}#{CRLF}")
else
size = #header['content-length'].to_i
#body.call(socket) # TODO: StreamWrapper which supports offset, size
#sent_size = size
end
end
class ChunkedWrapper
def initialize(socket, resp)
#socket = socket
#resp = resp
end
def write(buf)
return if buf.empty?
data = ""
data << format("%x", buf.size) << CRLF
data << buf << CRLF
socket = #socket
#resp.instance_eval {
_write_data(socket, data)
#sent_size += buf.size
}
end
alias :<< :write
end
end
end
if RUBY_VERSION < "1.9"
old_verbose, $VERBOSE = $VERBOSE, nil
# Increase from default of 4K for efficiency, similar to
# http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/lib/net/protocol.rb?r1=11708&r2=12092
# In trunk the default is 64K and can be adjusted using :InputBufferSize,
# :OutputBufferSize
WEBrick::HTTPRequest::BUFSIZE = 16384
WEBrick::HTTPResponse::BUFSIZE = 16384
$VERBOSE = old_verbose
end
to use simply pass a proc to as the response body, like so
res.body = proc { |w|
10.times do
w << Time.now.to_s
sleep(1)
end
}
woot!
I would suggest against using WEBrick for anything really, it's junk. I would say try Mongrel.
I know that wasn't your question, it's just some friendly advice.

Resources