| Module | ServerSide::HTTP::Parsing |
| In: |
lib/serverside/http/parsing.rb
|
| REQUEST_LINE_RE | = | /([A-Za-z0-9]+)\s(\/[^\/\?]*(?:\/[^\/\?]+)*)\/?(?:\?(.*))?\sHTTP\/(.+)/.freeze |
| HEADER_RE | = | /([^:]+):\s*(.*)/.freeze |
| HYPHEN | = | '-'.freeze |
| UNDERSCORE | = | '_'.freeze |
| AMPERSAND | = | '&'.freeze |
| PARAMETER_RE | = | /^(.{1,64})=(.{0,8192})$/.freeze |
| COOKIE_RE | = | /^(.+)=(.*)$/.freeze |
| SEMICOLON | = | ';'.freeze |
| BOUNDARY_FIX | = | '--'.freeze |
# File lib/serverside/http/parsing.rb, line 25
25: def header_to_sym(h)
26: h.downcase.gsub(HYPHEN, UNDERSCORE).to_sym
27: end
Parses the request body.
# File lib/serverside/http/parsing.rb, line 94
94: def parse_body(body)
95: @body = body
96: case @headers[:content_type]
97: when MULTIPART_FORM_DATA_RE:
98: parse_multi_part(body, BOUNDARY_FIX + $1) # body.dup so we keep the original request body?
99: when FORM_URL_ENCODED:
100: parse_form_url_encoded(body)
101: end
102: end
Parses a cookies header.
# File lib/serverside/http/parsing.rb, line 81
81: def parse_cookies(cookies)
82: cookies.split(SEMICOLON).each do |c|
83: if c.strip =~ COOKIE_RE
84: @cookies[$1.to_sym] = $2.uri_unescape
85: else
86: raise BadRequestError, "Invalid cookie format"
87: end
88: end
89: end
Parses query parameters passed in the body (for POST requests.)
# File lib/serverside/http/parsing.rb, line 152
152: def parse_form_url_encoded(body)
153: @params ||= {}
154: @params.merge!(parse_query_parameters(body))
155: end
Parses an HTTP header.
# File lib/serverside/http/parsing.rb, line 30
30: def parse_header(line)
31: # check header count
32: if (@header_count += 1) > MAX_HEADER_COUNT
33: raise BadRequestError, "Too many headers"
34: end
35:
36: if line =~ HEADER_RE
37: if $1.size > MAX_HEADER_NAME_SIZE
38: raise BadRequestError, "Invalid header size"
39: end
40: k = header_to_sym($1)
41: v = $2.freeze
42: case k
43: when :content_length: @content_length = v.to_i
44: when :connection: @persistent = v == KEEP_ALIVE
45: when :cookie: parse_cookies(v)
46: end
47: @headers[k] = v
48: else
49: raise BadRequestError, "Invalid header format"
50: end
51: end
Parses a multipart request body.
# File lib/serverside/http/parsing.rb, line 105
105: def parse_multi_part(body, boundary)
106: while part = body.get_up_to_boundary_with_crlf(boundary)
107: unless part.empty?
108: parse_part(part)
109: end
110: end
111: end
Parses a part of a multipart body.
# File lib/serverside/http/parsing.rb, line 114
114: def parse_part(part)
115: part_name = nil
116: file_name = nil
117: file_type = nil
118: # part headers
119: while (line = part.get_line)
120: break if line.empty?
121: if line =~ HEADER_RE
122: k = $1.freeze
123: v = $2.freeze
124: case k
125: when CONTENT_DISPOSITION:
126: case v
127: when DISPOSITION_FORM_DATA_RE:
128: p [$1, $2, $3]
129: part_name = $1.to_sym
130: file_name = $3
131: end
132: when CONTENT_TYPE:
133: file_type = v
134: end
135: else
136: raise BadRequestError, "Invalid header in part"
137: end
138: end
139: # check if we got the content name
140: unless part_name
141: raise BadRequestError, "Invalid part content"
142: end
143: # part body
144: part_body = part.chomp! # what's left of it
145: @params ||= {}
146: @params[part_name] = file_name ?
147: {:file_name => file_name, :file_content => part_body, :file_type => file_type} :
148: part_body
149: end
Parses query parameters by splitting the query string and unescaping parameter values.
# File lib/serverside/http/parsing.rb, line 58
58: def parse_query_parameters(query)
59: query.split(AMPERSAND).inject({}) do |m, i|
60: if i =~ PARAMETER_RE
61: k = $1
62: if k.size > MAX_PARAMETER_NAME_SIZE
63: raise BadRequestError, "Invalid parameter size"
64: end
65: v = $2
66: if v.size > MAX_PARAMETER_VALUE_SIZE
67: raise BadRequestError, "Invalid parameter size"
68: end
69: m[k.to_sym] = v.uri_unescape
70: else
71: raise BadRequestError, "Invalid parameter format"
72: end
73: m
74: end
75: end
Parses a request line into a method, URI, query and HTTP version parts. If a query is included, it is parsed into query parameters.
# File lib/serverside/http/parsing.rb, line 7
7: def parse_request_line(line)
8: if line =~ REQUEST_LINE_RE
9: @request_line = line
10: @method, @path, @query, @http_version = $1.downcase.to_sym, $2, $3, $4
11: @params = @query ? parse_query_parameters(@query) : {}
12:
13: # HTTP 1.1 connections are persistent by default.
14: @persistent = @http_version == VERSION_1_1
15: else
16: raise BadRequestError, "Invalid request format"
17: end
18: end