/test/test_http11.rb

https://github.com/rkh/puma · Ruby · 126 lines · 102 code · 17 blank · 7 comment · 2 complexity · dc98ee7fe7dbf799ae2a4b017d8b33e5 MD5 · raw file

  1. # Copyright (c) 2011 Evan Phoenix
  2. # Copyright (c) 2005 Zed A. Shaw
  3. require 'test/testhelp'
  4. include Puma
  5. class Http11ParserTest < Test::Unit::TestCase
  6. def test_parse_simple
  7. parser = HttpParser.new
  8. req = {}
  9. http = "GET / HTTP/1.1\r\n\r\n"
  10. nread = parser.execute(req, http, 0)
  11. assert nread == http.length, "Failed to parse the full HTTP request"
  12. assert parser.finished?, "Parser didn't finish"
  13. assert !parser.error?, "Parser had error"
  14. assert nread == parser.nread, "Number read returned from execute does not match"
  15. assert_equal '/', req['REQUEST_PATH']
  16. assert_equal 'HTTP/1.1', req['HTTP_VERSION']
  17. assert_equal '/', req['REQUEST_URI']
  18. assert_equal 'GET', req['REQUEST_METHOD']
  19. assert_nil req['FRAGMENT']
  20. assert_nil req['QUERY_STRING']
  21. parser.reset
  22. assert parser.nread == 0, "Number read after reset should be 0"
  23. end
  24. def test_parse_dumbfuck_headers
  25. parser = HttpParser.new
  26. req = {}
  27. should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
  28. nread = parser.execute(req, should_be_good, 0)
  29. assert_equal should_be_good.length, nread
  30. assert parser.finished?
  31. assert !parser.error?
  32. end
  33. def test_parse_error
  34. parser = HttpParser.new
  35. req = {}
  36. bad_http = "GET / SsUTF/1.1"
  37. error = false
  38. begin
  39. parser.execute(req, bad_http, 0)
  40. rescue
  41. error = true
  42. end
  43. assert error, "failed to throw exception"
  44. assert !parser.finished?, "Parser shouldn't be finished"
  45. assert parser.error?, "Parser SHOULD have error"
  46. end
  47. def test_fragment_in_uri
  48. parser = HttpParser.new
  49. req = {}
  50. get = "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
  51. assert_nothing_raised do
  52. parser.execute(req, get, 0)
  53. end
  54. assert parser.finished?
  55. assert_equal '/forums/1/topics/2375?page=1', req['REQUEST_URI']
  56. assert_equal 'posts-17408', req['FRAGMENT']
  57. end
  58. # lame random garbage maker
  59. def rand_data(min, max, readable=true)
  60. count = min + ((rand(max)+1) *10).to_i
  61. res = count.to_s + "/"
  62. if readable
  63. res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
  64. else
  65. res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20)
  66. end
  67. return res
  68. end
  69. def test_horrible_queries
  70. parser = HttpParser.new
  71. # then that large header names are caught
  72. 10.times do |c|
  73. get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
  74. assert_raises Puma::HttpParserError do
  75. parser.execute({}, get, 0)
  76. parser.reset
  77. end
  78. end
  79. # then that large mangled field values are caught
  80. 10.times do |c|
  81. get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
  82. assert_raises Puma::HttpParserError do
  83. parser.execute({}, get, 0)
  84. parser.reset
  85. end
  86. end
  87. # then large headers are rejected too
  88. get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
  89. get << "X-Test: test\r\n" * (80 * 1024)
  90. assert_raises Puma::HttpParserError do
  91. parser.execute({}, get, 0)
  92. parser.reset
  93. end
  94. # finally just that random garbage gets blocked all the time
  95. 10.times do |c|
  96. get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
  97. assert_raises Puma::HttpParserError do
  98. parser.execute({}, get, 0)
  99. parser.reset
  100. end
  101. end
  102. end
  103. end