server_radix.cr 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. require "http/server"
  2. require "json"
  3. require "pg"
  4. require "ecr"
  5. require "radix"
  6. plaintext_handler = ->(context : HTTP::Server::Context) do
  7. response = context.response
  8. response.status_code = 200
  9. response.headers["Content-Type"] = "text/plain"
  10. response.print "Hello, World!"
  11. return response
  12. end
  13. json_handler = ->(context : HTTP::Server::Context) do
  14. response = context.response
  15. response.status_code = 200
  16. response.headers["Content-Type"] = "application/json"
  17. {message: "Hello, World!"}.to_json(response)
  18. return response
  19. end
  20. db_handler = ->(context : HTTP::Server::Context) do
  21. request = context.request
  22. response = context.response
  23. response.status_code = 200
  24. response.headers["Content-Type"] = "application/json"
  25. random_world.to_json(response)
  26. return response
  27. end
  28. queries_handler = ->(context : HTTP::Server::Context) do
  29. request = context.request
  30. response = context.response
  31. response.status_code = 200
  32. response.headers["Content-Type"] = "application/json"
  33. JSON.build(response) do |json|
  34. json.array do
  35. sanitized_query_count(request).times do
  36. random_world.to_json(json)
  37. end
  38. end
  39. end
  40. return response
  41. end
  42. fortunes_handler = ->(context : HTTP::Server::Context) do
  43. request = context.request
  44. response = context.response
  45. response.status_code = 200
  46. response.headers["Content-Type"] = "text/html; charset=UTF-8"
  47. data = fortunes
  48. additional_fortune = {
  49. id: 0,
  50. message: "Additional fortune added at request time.",
  51. }
  52. data.push(additional_fortune)
  53. data.sort! { |f1, f2| f1[:message] <=> f2[:message] }
  54. ECR.embed "views/fortunes.ecr", response
  55. return response
  56. end
  57. updates_handler = ->(context : HTTP::Server::Context) do
  58. request = context.request
  59. response = context.response
  60. response.status_code = 200
  61. response.headers["Content-Type"] = "application/json"
  62. JSON.build(response) do |json|
  63. json.array do
  64. sanitized_query_count(request).times do
  65. world = set_world({id: random_world[:id], randomNumber: rand(1..ID_MAXIMUM)})
  66. world.to_json(json)
  67. end
  68. end
  69. end
  70. return response
  71. end
  72. tree = Radix::Tree(Proc(HTTP::Server::Context, HTTP::Server::Response)).new
  73. tree.add "/plaintext", plaintext_handler
  74. tree.add "/json", json_handler
  75. tree.add "/db", db_handler
  76. tree.add "/queries", queries_handler
  77. tree.add "/fortunes", fortunes_handler
  78. tree.add "/updates", updates_handler
  79. APPDB = DB.open(ENV["DATABASE_URL"])
  80. ID_MAXIMUM = 10_000
  81. server = HTTP::Server.new do |context|
  82. request = context.request
  83. response = context.response
  84. response.headers["Server"] = "Crystal"
  85. response.headers["Date"] = HTTP.format_time(Time.now)
  86. result = tree.find(request.path)
  87. if result.found?
  88. result.payload.call(context)
  89. else
  90. context.response.status_code = 404
  91. end
  92. end
  93. private def random_world
  94. id = rand(1..ID_MAXIMUM)
  95. random_number = APPDB.query_one("SELECT randomNumber FROM world WHERE id = $1", id, as: Int32)
  96. {id: id, randomNumber: random_number}
  97. end
  98. private def set_world(world)
  99. APPDB.exec("UPDATE world SET randomNumber = $1 WHERE id = $2", world[:randomNumber], world[:id])
  100. world
  101. end
  102. private def fortunes
  103. data = Array(NamedTuple(id: Int32, message: String)).new
  104. APPDB.query_each("SELECT id, message FROM Fortune") do |rs|
  105. data.push({id: rs.read(Int32), message: rs.read(String)})
  106. end
  107. data
  108. end
  109. private def sanitized_query_count(request)
  110. queries = request.query_params["queries"].as(String)
  111. queries = queries.to_i? || 1
  112. queries.clamp(1..500)
  113. end
  114. server.listen("0.0.0.0", 8080, reuse_port: true)