hello_world.rb 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # frozen_string_literal: true
  2. require 'time'
  3. # Our Rack application to be executed by rackup
  4. class HelloWorld
  5. MAX_PK = 10_000
  6. ID_RANGE = (1..10_000).freeze
  7. ALL_IDS = ID_RANGE.to_a
  8. QUERIES_MIN = 1
  9. QUERIES_MAX = 500
  10. CONTENT_TYPE = 'Content-Type'
  11. CONTENT_LENGTH = 'Content-Length'
  12. JSON_TYPE = 'application/json'
  13. HTML_TYPE = 'text/html; charset=utf-8'
  14. PLAINTEXT_TYPE = 'text/plain'
  15. DATE = 'Date'
  16. SERVER = 'Server'
  17. SERVER_STRING = if defined?(PhusionPassenger)
  18. 'Passenger'
  19. elsif defined?(Puma)
  20. 'Puma'
  21. elsif defined?(Iodine)
  22. 'Iodine'
  23. elsif defined?(Unicorn)
  24. 'Unicorn'
  25. else
  26. 'Ruby Rack'
  27. end
  28. def bounded_queries(env)
  29. params = Rack::Utils.parse_query(env['QUERY_STRING'])
  30. queries = params['queries'].to_i
  31. queries.clamp(QUERIES_MIN, QUERIES_MAX)
  32. end
  33. # Return a random number between 1 and MAX_PK
  34. def rand1
  35. rand(MAX_PK).succ
  36. end
  37. def db
  38. World::BY_ID.(id: rand1)
  39. end
  40. def queries(env)
  41. DB.synchronize do
  42. ALL_IDS.sample(bounded_queries(env)).map do |id|
  43. World::BY_ID.(id: id)
  44. end
  45. end
  46. end
  47. def fortunes
  48. fortunes = Fortune.all
  49. fortunes << Fortune.new(
  50. id: 0,
  51. message: 'Additional fortune added at request time.'
  52. )
  53. fortunes.sort_by!(&:message)
  54. html = String.new(<<~'HTML')
  55. <!DOCTYPE html>
  56. <html>
  57. <head>
  58. <title>Fortunes</title>
  59. </head>
  60. <body>
  61. <table>
  62. <tr>
  63. <th>id</th>
  64. <th>message</th>
  65. </tr>
  66. HTML
  67. fortunes.each do |fortune|
  68. html << <<~"HTML"
  69. <tr>
  70. <td>#{fortune.id}</td>
  71. <td>#{Rack::Utils.escape_html(fortune.message)}</td>
  72. </tr>
  73. HTML
  74. end
  75. html << <<~'HTML'
  76. </table>
  77. </body>
  78. </html>
  79. HTML
  80. end
  81. def updates(env)
  82. DB.synchronize do
  83. worlds =
  84. ALL_IDS.sample(bounded_queries(env)).map do |id|
  85. world = World::BY_ID.(id: id)
  86. world[:randomnumber] = rand1
  87. world
  88. end
  89. World.batch_update(worlds)
  90. worlds
  91. end
  92. end
  93. def call(env)
  94. case env['PATH_INFO']
  95. when '/json'
  96. # Test type 1: JSON serialization
  97. respond JSON_TYPE, { message: 'Hello, World!' }.to_json
  98. when '/db'
  99. # Test type 2: Single database query
  100. respond JSON_TYPE, db.to_json
  101. when '/queries'
  102. # Test type 3: Multiple database queries
  103. respond JSON_TYPE, queries(env).to_json
  104. when '/fortunes'
  105. # Test type 4: Fortunes
  106. respond HTML_TYPE, fortunes
  107. when '/updates'
  108. # Test type 5: Database updates
  109. respond JSON_TYPE, updates(env).to_json
  110. when '/plaintext'
  111. # Test type 6: Plaintext
  112. respond PLAINTEXT_TYPE, 'Hello, World!'
  113. end
  114. end
  115. private
  116. def respond(content_type, body)
  117. [
  118. 200,
  119. headers(content_type, body),
  120. [body]
  121. ]
  122. end
  123. if defined?(Unicorn)
  124. def headers(content_type, body)
  125. {
  126. CONTENT_TYPE => content_type,
  127. SERVER => SERVER_STRING,
  128. CONTENT_LENGTH => body.bytesize.to_s
  129. }
  130. end
  131. elsif defined?(Puma)
  132. def headers(content_type, _)
  133. {
  134. CONTENT_TYPE => content_type,
  135. SERVER => SERVER_STRING,
  136. DATE => Time.now.utc.httpdate
  137. }
  138. end
  139. else
  140. def headers(content_type, _)
  141. {
  142. CONTENT_TYPE => content_type,
  143. SERVER => SERVER_STRING
  144. }
  145. end
  146. end
  147. end