Skip to content

Commit 65d5805

Browse files
committed
Merge pull request #14 from moteus/master
Add. `cURL.safe` module.
2 parents 47c3774 + 9127eff commit 65d5805

6 files changed

Lines changed: 342 additions & 359 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Lua-cURLv2 binding has several problems:
3939
## Installation
4040

4141
```
42-
luarocks install lcurl --server=https://rocks.moonscript.org/dev
42+
luarocks install lua-curl --server=https://rocks.moonscript.org/dev
4343
```
4444

4545
## Usage

rockspecs/lua-curl-scm-0.rockspec

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ build = {
5757
},
5858

5959
modules = {
60-
cURL = "src/lua/cURL.lua",
60+
["cURL" ] = "src/lua/cURL.lua",
61+
["cURL.safe" ] = "src/lua/cURL/safe.lua",
62+
["cURL.impl.cURL" ] = "src/lua/cURL/impl/cURL.lua",
63+
6164
lcurl = {
6265
sources = {
6366
"src/l52util.c", "src/lceasy.c", "src/lcerror.c",
@@ -68,4 +71,6 @@ build = {
6871
libdirs = { "$(CURL_LIBDIR)" }
6972
},
7073
}
71-
}
74+
}
75+
76+

src/lua/cURL.lua

Lines changed: 2 additions & 354 deletions
Original file line numberDiff line numberDiff line change
@@ -1,356 +1,4 @@
1-
--
2-
-- Author: Alexey Melnichuk <mimir@newmail.ru>
3-
--
4-
-- Copyright (C) 2014 Alexey Melnichuk <mimir@newmail.ru>
5-
--
6-
-- Licensed according to the included 'LICENSE' document
7-
--
8-
-- This file is part of lua-lcurl library.
9-
--
10-
11-
--
12-
-- Implementation of Lua-cURL http://msva.github.io/lua-curl
13-
--
14-
151
local curl = require "lcurl"
2+
local impl = require "cURL.impl.cURL"
163

17-
local function wrap_function(k)
18-
return function(self, ...)
19-
local ok, err = self._handle[k](self._handle, ...)
20-
if ok == self._handle then return self end
21-
return ok, err
22-
end
23-
end
24-
25-
local function wrap_setopt_flags(k, flags)
26-
k = "setopt_" .. k
27-
return function(self, v)
28-
v = assert(flags[v], "Unsupported value " .. tostring(v))
29-
local ok, err = self._handle[k](self._handle, v)
30-
if ok == self._handle then return self end
31-
return ok, err
32-
end
33-
end
34-
35-
-------------------------------------------
36-
local Easy = {} do
37-
38-
Easy.__index = function(self, k)
39-
local fn = Easy[k]
40-
41-
if not fn and self._handle[k] then
42-
fn = wrap_function(k)
43-
self[k] = fn
44-
end
45-
return fn
46-
end
47-
48-
function Easy:new()
49-
local h, err = curl.easy()
50-
if not h then return nil, err end
51-
52-
local o = setmetatable({
53-
_handle = h
54-
}, self)
55-
56-
return o
57-
end
58-
59-
function Easy:handle()
60-
return self._handle
61-
end
62-
63-
local perform = wrap_function("perform")
64-
local setopt_share = wrap_function("setopt_share")
65-
local setopt_readfunction = wrap_function("setopt_readfunction")
66-
67-
local NONE = {}
68-
69-
function Easy:_call_readfunction(...)
70-
if self._rd_ud == NONE then
71-
return self._rd_fn(...)
72-
end
73-
return self._rd_fn(self._rd_ud, ...)
74-
end
75-
76-
function Easy:setopt_readfunction(fn, ...)
77-
assert(fn)
78-
79-
if select('#', ...) == 0 then
80-
if type(fn) == "function" then
81-
self._rd_fn = fn
82-
self._rd_ud = NONE
83-
else
84-
self._rd_fn = assert(fn.read)
85-
self._rd_ud = fn
86-
end
87-
else
88-
self._rd_fn = fn
89-
self._ud_fn = ...
90-
end
91-
92-
return setopt_readfunction(self, fn, ...)
93-
end
94-
95-
function Easy:perform(opt)
96-
opt = opt or {}
97-
98-
local oerror = opt.errorfunction or function(err) return nil, err end
99-
100-
if opt.readfunction then
101-
local ok, err = self:setopt_readfunction(opt.readfunction)
102-
if not ok then return oerror(err) end
103-
end
104-
105-
if opt.writefunction then
106-
local ok, err = self:setopt_writefunction(opt.writefunction)
107-
if not ok then return oerror(err) end
108-
end
109-
110-
if opt.headerfunction then
111-
local ok, err = self:setopt_headerfunction(opt.headerfunction)
112-
if not ok then return oerror(err) end
113-
end
114-
115-
local ok, err = perform(self)
116-
if not ok then return oerror(err) end
117-
118-
return self
119-
end
120-
121-
function Easy:post(data)
122-
local form = curl.form()
123-
local ok, err = true
124-
125-
for k, v in pairs(data) do
126-
if type(v) == "string" then
127-
ok, err = form:add_content(k, v)
128-
else
129-
assert(type(v) == "table")
130-
if v.stream_length then
131-
local len = assert(tonumber(v.stream_length))
132-
assert(v.file)
133-
if v.stream then
134-
ok, err = form:add_stream(k, v.file, v.type, v.headers, len, v.stream)
135-
else
136-
ok, err = form:add_stream(k, v.file, v.type, v.headers, len, self._call_readfunction, self)
137-
end
138-
elseif v.data then
139-
ok, err = form:add_buffer(k, v.file, v.data, v.type, v.headers)
140-
else
141-
ok, err = form:add_file(k, v.file, v.type, v.filename, v.headers)
142-
end
143-
end
144-
if not ok then break end
145-
end
146-
147-
if not ok then
148-
form:free()
149-
return nil, err
150-
end
151-
152-
ok, err = self:setopt_httppost(form)
153-
if not ok then
154-
form:free()
155-
return nil, err
156-
end
157-
158-
return self
159-
end
160-
161-
function Easy:setopt_share(s)
162-
return setopt_share(self, s:handle())
163-
end
164-
165-
Easy.setopt_proxytype = wrap_setopt_flags("proxytype", {
166-
["HTTP" ] = curl.PROXY_HTTP;
167-
["HTTP_1_0" ] = curl.PROXY_HTTP_1_0;
168-
["SOCKS4" ] = curl.PROXY_SOCKS4;
169-
["SOCKS5" ] = curl.PROXY_SOCKS5;
170-
["SOCKS4A" ] = curl.PROXY_SOCKS4A;
171-
["SOCKS5_HOSTNAME" ] = curl.PROXY_SOCKS5_HOSTNAME;
172-
})
173-
174-
Easy.setopt_httpauth = wrap_setopt_flags("httpauth", {
175-
["NONE" ] = curl.AUTH_NONE;
176-
["BASIC" ] = curl.AUTH_BASIC;
177-
["DIGEST" ] = curl.AUTH_DIGEST;
178-
["GSSNEGOTIATE" ] = curl.AUTH_GSSNEGOTIATE;
179-
["NTLM" ] = curl.AUTH_NTLM;
180-
["DIGEST_IE" ] = curl.AUTH_DIGEST_IE;
181-
["NTLM_WB" ] = curl.AUTH_NTLM_WB;
182-
["ONLY" ] = curl.AUTH_ONLY;
183-
["ANY" ] = curl.AUTH_ANY;
184-
["ANYSAFE" ] = curl.AUTH_ANYSAFE;
185-
["SSH_ANY" ] = curl.SSH_AUTH_ANY;
186-
["SSH_NONE" ] = curl.SSH_AUTH_NONE;
187-
["SSH_PUBLICKEY" ] = curl.SSH_AUTH_PUBLICKEY;
188-
["SSH_PASSWORD" ] = curl.SSH_AUTH_PASSWORD;
189-
["SSH_HOST" ] = curl.SSH_AUTH_HOST;
190-
["SSH_KEYBOARD" ] = curl.SSH_AUTH_KEYBOARD;
191-
["SSH_AGENT" ] = curl.SSH_AUTH_AGENT;
192-
["SSH_DEFAULT" ] = curl.SSH_AUTH_DEFAULT;
193-
})
194-
195-
end
196-
-------------------------------------------
197-
198-
-------------------------------------------
199-
local Multi = {} do
200-
201-
Multi.__index = function(self, k)
202-
local fn = Multi[k]
203-
204-
if not fn and self._handle[k] then
205-
fn = wrap_function(k)
206-
self[k] = fn
207-
end
208-
return fn
209-
end
210-
211-
function Multi:new()
212-
local h, err = curl.multi()
213-
if not h then return nil, err end
214-
215-
local o = setmetatable({
216-
_handle = h;
217-
_easy = {};
218-
}, self)
219-
220-
return o
221-
end
222-
223-
function Multi:handle()
224-
return self._handle
225-
end
226-
227-
local perform = wrap_function("perform")
228-
local add_handle = wrap_function("add_handle")
229-
local remove_handle = wrap_function("remove_handle")
230-
231-
local function make_iterator(self)
232-
local curl = require "lcurl.safe"
233-
234-
local buffers = {resp = {}, _ = {}} do
235-
236-
function buffers:append(e, ...)
237-
local resp = assert(e:getinfo_response_code())
238-
if not self._[e] then self._[e] = {} end
239-
240-
local b = self._[e]
241-
242-
if self.resp[e] ~= resp then
243-
b[#b + 1] = {"response", resp}
244-
self.resp[e] = resp
245-
end
246-
247-
b[#b + 1] = {...}
248-
end
249-
250-
function buffers:next()
251-
for e, t in pairs(self._) do
252-
local m = table.remove(t, 1)
253-
if m then return e, m end
254-
end
255-
end
256-
257-
end
258-
259-
local remain = #self._easy
260-
for _, e in ipairs(self._easy) do
261-
e:setopt_writefunction (function(str) buffers:append(e, "data", str) end)
262-
e:setopt_headerfunction(function(str) buffers:append(e, "header", str) end)
263-
end
264-
265-
assert(perform(self))
266-
267-
return function()
268-
while true do
269-
local e, t = buffers:next()
270-
if t then return t[2], t[1], e end
271-
if remain == 0 then break end
272-
273-
self:wait()
274-
275-
local n, err = assert(perform(self))
276-
277-
if n <= remain then
278-
while true do
279-
local e, ok, err = assert(self:info_read())
280-
if e == 0 then break end
281-
for _, a in ipairs(self._easy) do
282-
if e == a:handle() then e = a break end
283-
end
284-
if ok then buffers:append(e, "done", ok)
285-
else buffers:append(e, "error", err) end
286-
end
287-
remain = n
288-
end
289-
290-
end
291-
end
292-
end
293-
294-
function Multi:perform()
295-
return make_iterator(self)
296-
end
297-
298-
function Multi:add_handle(e)
299-
self._easy[#self._easy + 1] = e
300-
return add_handle(self, e:handle())
301-
end
302-
303-
function Multi:remove_handle(e)
304-
self._easy[#self._easy + 1] = e
305-
return remove_handle(self, e:handle())
306-
end
307-
308-
end
309-
-------------------------------------------
310-
311-
-------------------------------------------
312-
local Share = {} do
313-
314-
Share.__index = function(self, k)
315-
local fn = Share[k]
316-
317-
if not fn and self._handle[k] then
318-
fn = wrap_function(k)
319-
self[k] = fn
320-
end
321-
return fn
322-
end
323-
324-
function Share:new()
325-
local h, err = curl.share()
326-
if not h then return nil, err end
327-
328-
local o = setmetatable({
329-
_handle = h
330-
}, self)
331-
332-
return o
333-
end
334-
335-
function Share:handle()
336-
return self._handle
337-
end
338-
339-
Share.setopt_share = wrap_setopt_flags("share", {
340-
[ "COOKIE" ] = curl.LOCK_DATA_COOKIE;
341-
[ "DNS" ] = curl.LOCK_DATA_DNS;
342-
[ "SSL_SESSION" ] = curl.LOCK_DATA_SSL_SESSION;
343-
})
344-
345-
end
346-
-------------------------------------------
347-
348-
local cURL = setmetatable({}, {__index = curl})
349-
350-
function cURL.easy_init() return Easy:new() end
351-
352-
function cURL.multi_init() return Multi:new() end
353-
354-
function cURL.share_init() return Share:new() end
355-
356-
return cURL
4+
return impl(curl)

0 commit comments

Comments
 (0)