# frozen_string_literal: true
require 'time'
# Our Rack application to be executed by rackup
class HelloWorld
MAX_PK = 10_000
ID_RANGE = (1..10_000).freeze
ALL_IDS = ID_RANGE.to_a
QUERIES_MIN = 1
QUERIES_MAX = 500
CONTENT_TYPE = 'Content-Type'
CONTENT_LENGTH = 'Content-Length'
JSON_TYPE = 'application/json'
HTML_TYPE = 'text/html; charset=utf-8'
PLAINTEXT_TYPE = 'text/plain'
DATE = 'Date'
SERVER = 'Server'
SERVER_STRING = "Rack"
def bounded_queries(env)
params = Rack::Utils.parse_query(env['QUERY_STRING'])
queries = params['queries'].to_i
queries.clamp(QUERIES_MIN, QUERIES_MAX)
end
# Return a random number between 1 and MAX_PK
def rand1
rand(MAX_PK).succ
end
def db
World::BY_ID.(id: rand1)
end
def queries(env)
ids = ALL_IDS.sample(bounded_queries(env))
DB.synchronize do
ids.map do |id|
World::BY_ID.(id: id)
end
end
end
def fortunes
fortunes = Fortune.all
fortunes << Fortune.new(
id: 0,
message: 'Additional fortune added at request time.'
)
fortunes.sort_by!(&:message)
html = String.new(<<~'HTML')
Fortunes
id |
message |
HTML
fortunes.each do |fortune|
html << <<~"HTML"
#{fortune.id} |
#{Rack::Utils.escape_html(fortune.message)} |
HTML
end
html << <<~'HTML'
HTML
end
def updates(env)
ids = ALL_IDS.sample(bounded_queries(env))
DB.synchronize do
worlds =
ids.map do |id|
world = World::BY_ID.(id: id)
world[:randomnumber] = rand1
world
end
World.batch_update(worlds)
worlds
end
end
def call(env)
case env['PATH_INFO']
when '/json'
# Test type 1: JSON serialization
respond JSON_TYPE, { message: 'Hello, World!' }.to_json
when '/db'
# Test type 2: Single database query
respond JSON_TYPE, db.to_json
when '/queries'
# Test type 3: Multiple database queries
respond JSON_TYPE, queries(env).to_json
when '/fortunes'
# Test type 4: Fortunes
respond HTML_TYPE, fortunes
when '/updates'
# Test type 5: Database updates
respond JSON_TYPE, updates(env).to_json
when '/plaintext'
# Test type 6: Plaintext
respond PLAINTEXT_TYPE, 'Hello, World!'
end
end
private
def respond(content_type, body)
[
200,
headers(content_type, body),
[body]
]
end
if defined?(Unicorn)
def headers(content_type, body)
{
CONTENT_TYPE => content_type,
SERVER => SERVER_STRING,
CONTENT_LENGTH => body.bytesize.to_s
}
end
elsif defined?(Puma)
def headers(content_type, _)
{
CONTENT_TYPE => content_type,
SERVER => SERVER_STRING,
DATE => Time.now.utc.httpdate
}
end
else
def headers(content_type, _)
{
CONTENT_TYPE => content_type,
SERVER => SERVER_STRING
}
end
end
end