-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
request_processor.cr
72 lines (59 loc) · 1.63 KB
/
request_processor.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
require "../server"
class HTTP::Server::RequestProcessor
def initialize(&@handler : HTTP::Handler::Proc)
@wants_close = false
end
def initialize(@handler : HTTP::Handler | HTTP::Handler::Proc)
@wants_close = false
end
def close
@wants_close = true
end
def process(input, output, error = STDERR)
must_close = true
response = Response.new(output)
begin
until @wants_close
request = HTTP::Request.from_io(input)
# EOF
break unless request
if request.is_a?(HTTP::Request::BadRequest)
response.respond_with_error("Bad Request", 400)
response.close
return
end
response.version = request.version
response.reset
response.headers["Connection"] = "keep-alive" if request.keep_alive?
context = Context.new(request, response)
begin
@handler.call(context)
rescue ex
response.respond_with_error
response.close
error.puts "Unhandled exception on HTTP::Handler"
ex.inspect_with_backtrace(error)
return
end
if response.upgraded?
must_close = false
return
end
response.output.close
output.flush
break unless request.keep_alive?
# Skip request body in case the handler
# didn't read it all, for the next request
request.body.try &.close
end
rescue ex : Errno
# IO-related error, nothing to do
ensure
begin
input.close if must_close
rescue ex : Errno
# IO-related error, nothing to do
end
end
end
end