Software /
code /
prosody
Comparison
net/http.lua @ 3569:f30da46e0add
net.http: Removed old HTTP parser, and updated to use util.httpstream.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Sat, 06 Nov 2010 03:46:00 +0500 |
parent | 3540:bc139431830b |
child | 4338:5d5d6c6d121a |
comparison
equal
deleted
inserted
replaced
3568:51d5578965a5 | 3569:f30da46e0add |
---|---|
8 | 8 |
9 | 9 |
10 local socket = require "socket" | 10 local socket = require "socket" |
11 local mime = require "mime" | 11 local mime = require "mime" |
12 local url = require "socket.url" | 12 local url = require "socket.url" |
13 local httpstream_new = require "util.httpstream".new; | |
13 | 14 |
14 local server = require "net.server" | 15 local server = require "net.server" |
15 | 16 |
16 local connlisteners_get = require "net.connlisteners".get; | 17 local connlisteners_get = require "net.connlisteners".get; |
17 local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); | 18 local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); |
43 t_insert(result, _formencodepart(field.name).."=".._formencodepart(field.value)); | 44 t_insert(result, _formencodepart(field.name).."=".._formencodepart(field.value)); |
44 end | 45 end |
45 return t_concat(result, "&"); | 46 return t_concat(result, "&"); |
46 end | 47 end |
47 | 48 |
48 local function expectbody(reqt, code) | |
49 if reqt.method == "HEAD" then return nil end | |
50 if code == 204 or code == 304 or code == 301 then return nil end | |
51 if code >= 100 and code < 200 then return nil end | |
52 return 1 | |
53 end | |
54 | |
55 local function request_reader(request, data, startpos) | 49 local function request_reader(request, data, startpos) |
56 if not data then | 50 if not request.parser then |
57 if request.body then | 51 local function success_cb(r) |
58 log("debug", "Connection closed, but we have data, calling callback..."); | |
59 request.callback(t_concat(request.body), request.code, request); | |
60 elseif request.state ~= "completed" then | |
61 -- Error.. connection was closed prematurely | |
62 request.callback("connection-closed", 0, request); | |
63 return; | |
64 end | |
65 destroy_request(request); | |
66 request.body = nil; | |
67 request.state = "completed"; | |
68 return; | |
69 end | |
70 if request.state == "body" and request.state ~= "completed" then | |
71 log("debug", "Reading body...") | |
72 if not request.body then request.body = {}; request.havebodylength, request.bodylength = 0, tonumber(request.responseheaders["content-length"]); end | |
73 if startpos then | |
74 data = data:sub(startpos, -1) | |
75 end | |
76 t_insert(request.body, data); | |
77 if request.bodylength then | |
78 request.havebodylength = request.havebodylength + #data; | |
79 if request.havebodylength >= request.bodylength then | |
80 -- We have the body | |
81 log("debug", "Have full body, calling callback"); | |
82 if request.callback then | |
83 request.callback(t_concat(request.body), request.code, request); | |
84 end | |
85 request.body = nil; | |
86 request.state = "completed"; | |
87 else | |
88 log("debug", "Have "..request.havebodylength.." bytes out of "..request.bodylength); | |
89 end | |
90 end | |
91 elseif request.state == "headers" then | |
92 log("debug", "Reading headers...") | |
93 local pos = startpos; | |
94 local headers, headers_complete = request.responseheaders; | |
95 if not headers then | |
96 headers = {}; | |
97 request.responseheaders = headers; | |
98 end | |
99 for line in data:sub(startpos, -1):gmatch("(.-)\r\n") do | |
100 startpos = startpos + #line + 2; | |
101 local k, v = line:match("(%S+): (.+)"); | |
102 if k and v then | |
103 headers[k:lower()] = v; | |
104 --log("debug", "Header: "..k:lower().." = "..v); | |
105 elseif #line == 0 then | |
106 headers_complete = true; | |
107 break; | |
108 else | |
109 log("warn", "Unhandled header line: "..line); | |
110 end | |
111 end | |
112 if not headers_complete then return; end | |
113 -- Reached the end of the headers | |
114 if not expectbody(request, request.code) then | |
115 request.callback(nil, request.code, request); | |
116 return; | |
117 end | |
118 request.state = "body"; | |
119 if #data > startpos then | |
120 return request_reader(request, data, startpos); | |
121 end | |
122 elseif request.state == "status" then | |
123 log("debug", "Reading status...") | |
124 local http, code, text, linelen = data:match("^HTTP/(%S+) (%d+) (.-)\r\n()", startpos); | |
125 code = tonumber(code); | |
126 if not code then | |
127 log("warn", "Invalid HTTP status line, telling callback then closing"); | |
128 local ret = request.callback("invalid-status-line", 0, request); | |
129 destroy_request(request); | |
130 return ret; | |
131 end | |
132 | |
133 request.code, request.responseversion = code, http; | |
134 | |
135 if request.onlystatus then | |
136 if request.callback then | 52 if request.callback then |
137 request.callback(nil, code, request); | 53 for k,v in pairs(r) do request[k] = v; end |
54 request.callback(r.body, r.code, request); | |
55 request.callback = nil; | |
138 end | 56 end |
139 destroy_request(request); | 57 destroy_request(request); |
140 return; | |
141 end | 58 end |
142 | 59 local function error_cb(r) |
143 request.state = "headers"; | 60 if request.callback then |
144 | 61 request.callback(r or "connection-closed", 0, request); |
145 if #data > linelen then | 62 request.callback = nil; |
146 return request_reader(request, data, linelen); | 63 end |
64 destroy_request(request); | |
147 end | 65 end |
66 local function options_cb() | |
67 return request; | |
68 end | |
69 request.parser = httpstream_new(success_cb, error_cb, "client", options_cb); | |
148 end | 70 end |
71 request.parser:feed(data); | |
149 end | 72 end |
150 | 73 |
151 local function handleerr(err) log("error", "Traceback[http]: %s: %s", tostring(err), debug_traceback()); end | 74 local function handleerr(err) log("error", "Traceback[http]: %s: %s", tostring(err), debug_traceback()); end |
152 function request(u, ex, callback) | 75 function request(u, ex, callback) |
153 local req = url.parse(u); | 76 local req = url.parse(u); |