Software /
code /
prosody
Annotate
util/httpstream.lua @ 3566:75d287daad16
util.httpstream: Added support for an options callback, to allow passing per-message options to the parser.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Sat, 06 Nov 2010 01:54:58 +0500 |
parent | 3565:e2cc09e83a3e |
child | 3567:94828fb2dab8 |
rev | line source |
---|---|
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
1 |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
2 local coroutine = coroutine; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
3 local tonumber = tonumber; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
4 |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
5 local deadroutine = coroutine.create(function() end); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
6 coroutine.resume(deadroutine); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
7 |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
8 module("httpstream") |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
9 |
3566
75d287daad16
util.httpstream: Added support for an options callback, to allow passing per-message options to the parser.
Waqas Hussain <waqas20@gmail.com>
parents:
3565
diff
changeset
|
10 local function parser(success_cb, parser_type, options_cb) |
3565
e2cc09e83a3e
util.httpstream: A little refactoring of the coroutine control flow.
Waqas Hussain <waqas20@gmail.com>
parents:
3564
diff
changeset
|
11 local data = coroutine.yield(); |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
12 local function readline() |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
13 local pos = data:find("\r\n", nil, true); |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
14 while not pos do |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
15 data = data..coroutine.yield(); |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
16 pos = data:find("\r\n", nil, true); |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
17 end |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
18 local r = data:sub(1, pos-1); |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
19 data = data:sub(pos+2); |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
20 return r; |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
21 end |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
22 local function readlength(n) |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
23 while #data < n do |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
24 data = data..coroutine.yield(); |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
25 end |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
26 local r = data:sub(1, n); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
27 data = data:sub(n + 1); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
28 return r; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
29 end |
3562
98f9dca3eb94
util.httpstream: Move HTTP header parsing into its own function.
Waqas Hussain <waqas20@gmail.com>
parents:
3496
diff
changeset
|
30 local function readheaders() |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
31 local headers = {}; -- read headers |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
32 while true do |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
33 local line = readline(); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
34 if line == "" then break; end -- headers done |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
35 local key, val = line:match("^([^%s:]+): *(.*)$"); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
36 if not key then coroutine.yield("invalid-header-line"); end -- TODO handle multi-line and invalid headers |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
37 key = key:lower(); |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
38 headers[key] = headers[key] and headers[key]..","..val or val; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
39 end |
3563
544d9d2e3046
util.httpstream: Fixed a nil variable access introduced in the last commit.
Waqas Hussain <waqas20@gmail.com>
parents:
3562
diff
changeset
|
40 return headers; |
3562
98f9dca3eb94
util.httpstream: Move HTTP header parsing into its own function.
Waqas Hussain <waqas20@gmail.com>
parents:
3496
diff
changeset
|
41 end |
98f9dca3eb94
util.httpstream: Move HTTP header parsing into its own function.
Waqas Hussain <waqas20@gmail.com>
parents:
3496
diff
changeset
|
42 |
3564
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
43 if not parser_type or parser_type == "server" then |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
44 while true do |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
45 -- read status line |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
46 local status_line = readline(); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
47 local method, path, httpversion = status_line:match("^(%S+)%s+(%S+)%s+HTTP/(%S+)$"); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
48 if not method then coroutine.yield("invalid-status-line"); end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
49 -- TODO parse url |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
50 local headers = readheaders(); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
51 |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
52 -- read body |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
53 local len = tonumber(headers["content-length"]); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
54 len = len or 0; -- TODO check for invalid len |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
55 local body = readlength(len); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
56 |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
57 success_cb({ |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
58 method = method; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
59 path = path; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
60 httpversion = httpversion; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
61 headers = headers; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
62 body = body; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
63 }); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
64 end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
65 elseif parser_type == "client" then |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
66 while true do |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
67 -- read status line |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
68 local status_line = readline(); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
69 local httpversion, status_code, reason_phrase = status_line:match("^HTTP/(%S+)%s+(%d%d%d)%s+(.*)$"); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
70 if not httpversion then coroutine.yield("invalid-status-line"); end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
71 local headers = readheaders(); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
72 |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
73 -- read body |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
74 local body; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
75 local len = tonumber(headers["content-length"]); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
76 if len then -- TODO check for invalid len |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
77 body = readlength(len); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
78 else -- read to end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
79 repeat |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
80 local newdata = coroutine.yield(); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
81 data = data..newdata; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
82 until newdata == ""; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
83 body, data = data, ""; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
84 end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
85 |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
86 success_cb({ |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
87 code = status_code; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
88 responseversion = httpversion; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
89 responseheaders = headers; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
90 body = body; |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
91 }); |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
92 end |
90f4e6dc1c11
util.httpstream: Added support for HTTP response parsing.
Waqas Hussain <waqas20@gmail.com>
parents:
3563
diff
changeset
|
93 else coroutine.yield("unknown-parser-type"); end |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
94 end |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
95 |
3566
75d287daad16
util.httpstream: Added support for an options callback, to allow passing per-message options to the parser.
Waqas Hussain <waqas20@gmail.com>
parents:
3565
diff
changeset
|
96 function new(success_cb, error_cb, parser_type, options_cb) |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
97 local co = coroutine.create(parser); |
3566
75d287daad16
util.httpstream: Added support for an options callback, to allow passing per-message options to the parser.
Waqas Hussain <waqas20@gmail.com>
parents:
3565
diff
changeset
|
98 coroutine.resume(co, success_cb, parser_type, options_cb) |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
99 return { |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
100 feed = function(self, data) |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
101 if not data then |
3565
e2cc09e83a3e
util.httpstream: A little refactoring of the coroutine control flow.
Waqas Hussain <waqas20@gmail.com>
parents:
3564
diff
changeset
|
102 if parser_type == "client" then coroutine.resume(co, ""); end |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
103 co = deadroutine; |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
104 return error_cb(); |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
105 end |
3565
e2cc09e83a3e
util.httpstream: A little refactoring of the coroutine control flow.
Waqas Hussain <waqas20@gmail.com>
parents:
3564
diff
changeset
|
106 local success, result = coroutine.resume(co, data); |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
107 if result then |
3496
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
108 co = deadroutine; |
9408d1e10e17
util.httpstream: Refactored and simplified code to improve readability.
Waqas Hussain <waqas20@gmail.com>
parents:
3495
diff
changeset
|
109 return error_cb(result); |
3494
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
110 end |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
111 end; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
112 }; |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
113 end |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
114 |
0f185563a4e4
util.httpstream: Initial commit of the new HTTP parser.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
115 return _M; |