commit
15c10adc2b
50
.travis.yml
50
.travis.yml
@ -9,23 +9,17 @@ env:
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- compiler: ": Lua51-osx"
|
- env: LUA="lua 5.1"
|
||||||
env: LUA="lua 5.1"
|
|
||||||
os: osx
|
os: osx
|
||||||
- compiler: ": Lua51"
|
- env: LUA="lua 5.1"
|
||||||
env: LUA="lua 5.1"
|
|
||||||
os: linux
|
os: linux
|
||||||
- compiler: ": Lua52"
|
- env: LUA="lua 5.2"
|
||||||
env: LUA="lua 5.2"
|
|
||||||
os: linux
|
os: linux
|
||||||
- compiler: ": Lua53"
|
- env: LUA="lua 5.3"
|
||||||
env: LUA="lua 5.3"
|
|
||||||
os: linux
|
os: linux
|
||||||
- compiler: ": LuaJIT20"
|
- env: LUA="luajit 2.0"
|
||||||
env: LUA="luajit 2.0"
|
|
||||||
os: linux
|
os: linux
|
||||||
- compiler: ": LuaJIT21"
|
- env: LUA="luajit 2.1"
|
||||||
env: LUA="luajit 2.1"
|
|
||||||
os: linux
|
os: linux
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
@ -36,25 +30,35 @@ cache:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- curl_mime
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export CC=gcc
|
|
||||||
- gcc --version
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH=$PATH:~/Library/Python/2.7/bin/; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH=$PATH:~/Library/Python/2.7/bin/; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export LCURL_LD_FLAGS="-bundle -undefined dynamic_lookup -all_load --coverage"; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export LCURL_LD_FLAGS="-bundle -undefined dynamic_lookup -all_load --coverage"; fi
|
||||||
- pip install --user cpp-coveralls
|
- pip2 install --user cpp-coveralls
|
||||||
- pip install --user hererocks
|
- pip2 install --user hererocks
|
||||||
- hererocks here -r^ --$LUA
|
- hererocks here -r^ --$LUA
|
||||||
- source here/bin/activate
|
- source here/bin/activate
|
||||||
|
- luarocks show lluv > /dev/null 2>&1 || bash .travis/setup_uv.sh
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- luarocks make rockspecs/lua-curl-scm-0.rockspec CFLAGS="$LCURL_CC_FLAGS" LIBFLAG="$LCURL_LD_FLAGS"
|
- luarocks make rockspecs/lua-curl-scm-0.rockspec CFLAGS="$LCURL_CC_FLAGS" LIBFLAG="$LCURL_LD_FLAGS"
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- luarocks show luacov-coveralls > /dev/null 2>&1 || luarocks install luacov-coveralls
|
- luarocks show luacov-coveralls > /dev/null 2>&1 || luarocks install luacov-coveralls
|
||||||
- luarocks show lunitx > /dev/null 2>&1 || luarocks install lunitx
|
- luarocks show lunitx > /dev/null 2>&1 || luarocks install lunitx
|
||||||
- luarocks show luafilesystem > /dev/null 2>&1 || luarocks install luafilesystem
|
- luarocks show luafilesystem > /dev/null 2>&1 || luarocks install luafilesystem
|
||||||
- luarocks show dkjson > /dev/null 2>&1 || luarocks install dkjson --deps-mode=none
|
- luarocks show dkjson > /dev/null 2>&1 || luarocks install dkjson --deps-mode=none
|
||||||
|
- luarocks show pegasus > /dev/null 2>&1 || luarocks install pegasus http.parser
|
||||||
|
--server=http://luarocks.org/manifests/moteus
|
||||||
|
- luarocks show pegasus-router > /dev/null 2>&1 || luarocks install pegasus-router
|
||||||
|
--server=http://luarocks.org/dev
|
||||||
|
- luarocks show lluv > /dev/null 2>&1 || luarocks install lluv UV_DIR=$TRAVIS_BUILD_DIR/libuv
|
||||||
|
--server=http://luarocks.org/dev
|
||||||
|
- luarocks show lluv-pegasus > /dev/null 2>&1 || luarocks install lluv-pegasus
|
||||||
|
--server=http://luarocks.org/dev --deps-mode=none
|
||||||
|
- lua test/server.lua &
|
||||||
|
- curl -s http://127.0.0.1:7090/get
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cd test
|
- cd test
|
||||||
@ -63,14 +67,12 @@ script:
|
|||||||
- lua test_pause02.c.lua
|
- lua test_pause02.c.lua
|
||||||
- lua test_multi_callback.lua
|
- lua test_multi_callback.lua
|
||||||
- lua test_multi_nested_callback.lua
|
- lua test_multi_nested_callback.lua
|
||||||
# - lunit.sh test_easy.lua
|
|
||||||
# - lunit.sh test_safe.lua
|
|
||||||
# - lunit.sh test_form.lua
|
|
||||||
# - lunit.sh test_curl.lua
|
|
||||||
|
|
||||||
after_success:
|
before_cache:
|
||||||
- coveralls -b .. -r .. --dump c.report.json
|
- coveralls -b .. -r .. --dump c.report.json
|
||||||
- luacov-coveralls -j c.report.json -v
|
- luacov-coveralls -j c.report.json -v
|
||||||
|
- luarocks remove lua-curl
|
||||||
|
- rm -f /home/travis/.cache/pip/log/debug.log
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
15
.travis/platform.sh
Normal file
15
.travis/platform.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
if [ -z "${PLATFORM:-}" ]; then
|
||||||
|
PLATFORM=$TRAVIS_OS_NAME;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PLATFORM" == "osx" ]; then
|
||||||
|
PLATFORM="macosx";
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PLATFORM" ]; then
|
||||||
|
if [ "$(uname)" == "Linux" ]; then
|
||||||
|
PLATFORM="linux";
|
||||||
|
else
|
||||||
|
PLATFORM="macosx";
|
||||||
|
fi;
|
||||||
|
fi
|
25
.travis/setup_uv.sh
Normal file
25
.travis/setup_uv.sh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
source .travis/platform.sh
|
||||||
|
|
||||||
|
cd $TRAVIS_BUILD_DIR
|
||||||
|
|
||||||
|
git clone https://github.com/libuv/libuv.git -b v1.x
|
||||||
|
|
||||||
|
cd libuv
|
||||||
|
|
||||||
|
git checkout v1.19.0
|
||||||
|
|
||||||
|
mkdir -p lib
|
||||||
|
mkdir -p build
|
||||||
|
git clone https://chromium.googlesource.com/external/gyp build/gyp
|
||||||
|
|
||||||
|
if [ "$PLATFORM" == "macosx" ]; then
|
||||||
|
./gyp_uv.py -f xcode && xcodebuild -ARCHS="x86_64" -project uv.xcodeproj -configuration Release -target All
|
||||||
|
cp ./build/Release/libuv.a ./lib;
|
||||||
|
else
|
||||||
|
./gyp_uv.py -f make && BUILDTYPE=Release CFLAGS=-fPIC make -C out
|
||||||
|
cp ./out/Release/libuv.a ./lib;
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $TRAVIS_BUILD_DIR
|
18
appveyor.yml
18
appveyor.yml
@ -7,7 +7,7 @@ shallow_clone: true
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
LR_EXTERNAL: c:\external
|
LR_EXTERNAL: c:\external
|
||||||
CURL_VER: 7.55.1
|
CURL_VER: 7.59.0
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- LUA: "lua 5.1"
|
- LUA: "lua 5.1"
|
||||||
@ -39,6 +39,7 @@ install:
|
|||||||
hererocks c:\hererocks --%LUA% --target %HR_TARGET% -rlatest
|
hererocks c:\hererocks --%LUA% --target %HR_TARGET% -rlatest
|
||||||
)
|
)
|
||||||
- call c:\hererocks\bin\activate
|
- call c:\hererocks\bin\activate
|
||||||
|
- luarocks show luarocks-fetch-gitrec >nul 2>&1 || luarocks install luarocks-fetch-gitrec
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
# external deps
|
# external deps
|
||||||
@ -57,6 +58,12 @@ before_test:
|
|||||||
- luarocks show dkjson >nul 2>&1 || luarocks install dkjson
|
- luarocks show dkjson >nul 2>&1 || luarocks install dkjson
|
||||||
- luarocks show luafilesystem >nul 2>&1 || luarocks install luafilesystem
|
- luarocks show luafilesystem >nul 2>&1 || luarocks install luafilesystem
|
||||||
- luarocks show lua-path >nul 2>&1 || luarocks install lua-path
|
- luarocks show lua-path >nul 2>&1 || luarocks install lua-path
|
||||||
|
- luarocks show pegasus >nul 2>&1 || luarocks install pegasus http.parser
|
||||||
|
--server=http://luarocks.org/manifests/moteus
|
||||||
|
- luarocks show pegasus-router >nul 2>&1 || luarocks install pegasus-router
|
||||||
|
--server=http://luarocks.org/dev
|
||||||
|
- ps: $TestServer = Start-Process lua -ArgumentList test/server.lua -RedirectStandardOutput "$env:APPVEYOR_BUILD_FOLDER\server.stdout.txt" -RedirectStandardError "$env:APPVEYOR_BUILD_FOLDER\server.stderr.txt" -PassThru
|
||||||
|
- curl -s http://127.0.0.1:7090/get
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- echo "Testing..."
|
- echo "Testing..."
|
||||||
@ -69,3 +76,12 @@ test_script:
|
|||||||
after_test:
|
after_test:
|
||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
- .appveyor\pack_artifact.bat lua-curl bin-rock
|
- .appveyor\pack_artifact.bat lua-curl bin-rock
|
||||||
|
|
||||||
|
on_failure:
|
||||||
|
- ps: Stop-Process -Id $TestServer.Id
|
||||||
|
- ps: $path = "$env:APPVEYOR_BUILD_FOLDER\server.stderr.txt"; if (Test-Path $path -PathType Leaf) { Push-AppveyorArtifact $path; } else { echo "File $path does not exist"; }
|
||||||
|
- ps: $path = "$env:APPVEYOR_BUILD_FOLDER\server.stdout.txt"; if (Test-Path $path -PathType Leaf) { Push-AppveyorArtifact $path; } else { echo "File $path does not exist"; }
|
||||||
|
|
||||||
|
on_finish:
|
||||||
|
- curl -s http://127.0.0.1:7090/get
|
||||||
|
- ps: Stop-Process -Id $TestServer.Id
|
||||||
|
85
examples/lcurl/smtp-mime.lua
Normal file
85
examples/lcurl/smtp-mime.lua
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
local curl = require "lcurl"
|
||||||
|
|
||||||
|
local SMTP = {
|
||||||
|
url = "smtp://mail.example.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
local FROM = "<sender@example.org>"
|
||||||
|
local TO = "<addressee@example.net>"
|
||||||
|
local CC = "<info@example.org>"
|
||||||
|
local FILE = "smtp-mime.lua" -- if you send this file do not forget it may have mail password
|
||||||
|
local CT_FILE = "application/lua"
|
||||||
|
|
||||||
|
local DUMP_MIME = false
|
||||||
|
|
||||||
|
local headers = {
|
||||||
|
"Date: Tue, 22 Aug 2017 14:08:43 +0100",
|
||||||
|
"To: " .. TO,
|
||||||
|
"From: " .. FROM .. " (Example User)",
|
||||||
|
"Cc: " .. CC .. " (Another example User)",
|
||||||
|
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@rfcpedant.example.org>",
|
||||||
|
"Subject: example sending a MIME-formatted message",
|
||||||
|
}
|
||||||
|
|
||||||
|
local inline_text = ""
|
||||||
|
.. "This is the inline text message of the e-mail.\r\n"
|
||||||
|
.. "\r\n"
|
||||||
|
.. " It could be a lot of lines that would be displayed in an e-mail\r\n"
|
||||||
|
.. "viewer that is not able to handle HTML.\r\n"
|
||||||
|
|
||||||
|
local inline_html = ""
|
||||||
|
.. "<html><body>\r\n"
|
||||||
|
.. "<p>This is the inline <b>HTML</b> message of the e-mail.</p>"
|
||||||
|
.. "<br />\r\n"
|
||||||
|
.. "<p>It could be a lot of HTML data that would be displayed by "
|
||||||
|
.. "e-mail viewers able to handle HTML.</p>"
|
||||||
|
.. "</body></html>\r\n"
|
||||||
|
|
||||||
|
local function dump_mime(type, data)
|
||||||
|
if type == curl.INFO_DATA_OUT then io.write(data) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local easy = curl.easy()
|
||||||
|
|
||||||
|
local mime = easy:mime() do
|
||||||
|
local alt = easy:mime()
|
||||||
|
alt
|
||||||
|
:addpart()
|
||||||
|
:data(inline_html, "text/html")
|
||||||
|
alt
|
||||||
|
:addpart()
|
||||||
|
:data(inline_text)
|
||||||
|
mime:addpart()
|
||||||
|
:subparts(alt, "multipart/alternative", {
|
||||||
|
"Content-Disposition: inline"
|
||||||
|
})
|
||||||
|
mime
|
||||||
|
:addpart()
|
||||||
|
:filedata(FILE, CT_FILE)
|
||||||
|
end
|
||||||
|
|
||||||
|
easy:setopt{
|
||||||
|
url = SMTP.url,
|
||||||
|
mail_from = FROM,
|
||||||
|
mail_rcpt = {TO, CC},
|
||||||
|
httpheader = headers;
|
||||||
|
mimepost = mime;
|
||||||
|
ssl_verifyhost = false;
|
||||||
|
ssl_verifypeer = false;
|
||||||
|
username = SMTP.user;
|
||||||
|
password = SMTP.password;
|
||||||
|
upload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if DUMP_MIME then
|
||||||
|
easy:setopt{
|
||||||
|
verbose = true;
|
||||||
|
debugfunction = dump_mime;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
easy:perform()
|
||||||
|
|
||||||
|
easy:close()
|
||||||
|
|
||||||
|
mime:free()
|
1
lakefile
1
lakefile
@ -32,6 +32,7 @@ target('test', install, function()
|
|||||||
run_test('test_form.lua')
|
run_test('test_form.lua')
|
||||||
run_test('test_pause02.c.lua')
|
run_test('test_pause02.c.lua')
|
||||||
run_test('test_curl.lua')
|
run_test('test_curl.lua')
|
||||||
|
run_test('test_mime.lua')
|
||||||
run_test('test_multi_callback.lua')
|
run_test('test_multi_callback.lua')
|
||||||
run_test('test_multi_nested_callback.lua')
|
run_test('test_multi_nested_callback.lua')
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="windows-1251"?>
|
<?xml version="1.0" encoding="windows-1251"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9,00"
|
||||||
Name="lcurl"
|
Name="lcurl"
|
||||||
ProjectGUID="{200D5C0C-8123-48F6-9EA0-CF0E6A6943F2}"
|
ProjectGUID="{200D5C0C-8123-48F6-9EA0-CF0E6A6943F2}"
|
||||||
RootNamespace="lcurl"
|
RootNamespace="lcurl"
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="$(CPPLIB_DIR)\curl\7.37.1\include;$(LUA_DIR)\include"
|
AdditionalIncludeDirectories="$(CPPLIB_DIR)\curl\7.56.0\include;$(LUA_DIR)\include"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LCURL_EXPORTS"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LCURL_EXPORTS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@ -63,7 +63,7 @@
|
|||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="lua5.1.lib libcurl.lib ws2_32.lib"
|
AdditionalDependencies="lua5.1.lib libcurl.lib ws2_32.lib"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
AdditionalLibraryDirectories=""$(CPPLIB_DIR)\curl\7.37.1\lib";"$(LUA_DIR)\lib""
|
AdditionalLibraryDirectories=""$(CPPLIB_DIR)\curl\7.56.0\lib";"$(LUA_DIR)\lib""
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
TargetMachine="1"
|
TargetMachine="1"
|
||||||
@ -189,6 +189,10 @@
|
|||||||
RelativePath="..\src\lchttppost.c"
|
RelativePath="..\src\lchttppost.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\lcmime.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\lcmulti.c"
|
RelativePath="..\src\lcmulti.c"
|
||||||
>
|
>
|
||||||
@ -251,6 +255,10 @@
|
|||||||
RelativePath="..\src\lcinfoeasy.h"
|
RelativePath="..\src\lcinfoeasy.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\lcmime.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\lcmulti.h"
|
RelativePath="..\src\lcmulti.h"
|
||||||
>
|
>
|
||||||
|
@ -63,7 +63,7 @@ build = {
|
|||||||
sources = {
|
sources = {
|
||||||
"src/l52util.c", "src/lceasy.c", "src/lcerror.c",
|
"src/l52util.c", "src/lceasy.c", "src/lcerror.c",
|
||||||
"src/lchttppost.c", "src/lcurl.c", "src/lcutils.c",
|
"src/lchttppost.c", "src/lcurl.c", "src/lcutils.c",
|
||||||
"src/lcmulti.c", "src/lcshare.c",
|
"src/lcmulti.c", "src/lcshare.c","src/lcmime.c",
|
||||||
},
|
},
|
||||||
incdirs = { "$(CURL_INCDIR)" },
|
incdirs = { "$(CURL_INCDIR)" },
|
||||||
libdirs = { "$(CURL_LIBDIR)" }
|
libdirs = { "$(CURL_LIBDIR)" }
|
||||||
|
95
src/lceasy.c
95
src/lceasy.c
@ -1,7 +1,7 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Alexey Melnichuk <mimir@newmail.ru>
|
* Copyright (C) 2014-2018 Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Licensed according to the included 'LICENSE' document
|
* Licensed according to the included 'LICENSE' document
|
||||||
*
|
*
|
||||||
@ -15,6 +15,7 @@
|
|||||||
#include "lchttppost.h"
|
#include "lchttppost.h"
|
||||||
#include "lcshare.h"
|
#include "lcshare.h"
|
||||||
#include "lcmulti.h"
|
#include "lcmulti.h"
|
||||||
|
#include "lcmime.h"
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
static const char *LCURL_ERROR_TAG = "LCURL_ERROR_TAG";
|
static const char *LCURL_ERROR_TAG = "LCURL_ERROR_TAG";
|
||||||
@ -29,7 +30,7 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Before call curl_XXX function which can call any callback
|
/* Before call curl_XXX function which can call any callback
|
||||||
* need set Curren Lua thread pointer in easy/multi contexts.
|
* need set Current Lua thread pointer in easy/multi contexts.
|
||||||
* But it also possible that we already in callback call.
|
* But it also possible that we already in callback call.
|
||||||
* E.g. `curl_easy_pause` function may be called from write callback.
|
* E.g. `curl_easy_pause` function may be called from write callback.
|
||||||
* and it even may be called in different thread.
|
* and it even may be called in different thread.
|
||||||
@ -41,7 +42,7 @@ static const char *LCURL_EASY = LCURL_EASY_NAME;
|
|||||||
* ```
|
* ```
|
||||||
* So we have to restore previews Lua state in callback contexts.
|
* So we have to restore previews Lua state in callback contexts.
|
||||||
* But if previews Lua state is NULL then we can just do not set it back.
|
* But if previews Lua state is NULL then we can just do not set it back.
|
||||||
* But set it to NULL make esier debug code.
|
* But set it to NULL make easier to debug code.
|
||||||
*/
|
*/
|
||||||
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){
|
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi){
|
||||||
if(p->multi && assign_multi){
|
if(p->multi && assign_multi){
|
||||||
@ -52,6 +53,11 @@ void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int
|
|||||||
if(p->post){
|
if(p->post){
|
||||||
p->post->L = value;
|
p->post->L = value;
|
||||||
}
|
}
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
if(p->mime){
|
||||||
|
lcurl_mime_set_lua(L, p->mime, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +80,9 @@ int lcurl_easy_create(lua_State *L, int error_mode){
|
|||||||
p->L = NULL;
|
p->L = NULL;
|
||||||
p->post = NULL;
|
p->post = NULL;
|
||||||
p->multi = NULL;
|
p->multi = NULL;
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
p->mime = NULL;
|
||||||
|
#endif
|
||||||
p->storage = lcurl_storage_init(L);
|
p->storage = lcurl_storage_init(L);
|
||||||
p->wr.cb_ref = p->wr.ud_ref = LUA_NOREF;
|
p->wr.cb_ref = p->wr.ud_ref = LUA_NOREF;
|
||||||
p->rd.cb_ref = p->rd.ud_ref = LUA_NOREF;
|
p->rd.cb_ref = p->rd.ud_ref = LUA_NOREF;
|
||||||
@ -125,6 +134,8 @@ static int lcurl_easy_cleanup(lua_State *L){
|
|||||||
|
|
||||||
// In my tests when I cleanup some easy handle.
|
// In my tests when I cleanup some easy handle.
|
||||||
// timerfunction called only for single multi handle.
|
// timerfunction called only for single multi handle.
|
||||||
|
// Also may be this function may call `close` callback
|
||||||
|
// for `curl_mimepart` structure.
|
||||||
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
|
curL = p->L; lcurl__easy_assign_lua(L, p, L, 1);
|
||||||
curl_easy_cleanup(p->curl);
|
curl_easy_cleanup(p->curl);
|
||||||
#ifndef LCURL_RESET_NULL_LUA
|
#ifndef LCURL_RESET_NULL_LUA
|
||||||
@ -135,6 +146,11 @@ static int lcurl_easy_cleanup(lua_State *L){
|
|||||||
p->curl = NULL;
|
p->curl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->post = NULL;
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
p->mime = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(p->storage != LUA_NOREF){
|
if(p->storage != LUA_NOREF){
|
||||||
p->storage = lcurl_storage_free(L, p->storage);
|
p->storage = lcurl_storage_free(L, p->storage);
|
||||||
}
|
}
|
||||||
@ -266,6 +282,15 @@ static int lcurl_easy_reset(lua_State *L){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
|
||||||
|
static int lcurl_easy_mime(lua_State *L){
|
||||||
|
lcurl_easy_t *p = lcurl_geteasy(L);
|
||||||
|
return lcurl_mime_create(L, p->err_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//{ OPTIONS
|
//{ OPTIONS
|
||||||
|
|
||||||
//{ set
|
//{ set
|
||||||
@ -447,6 +472,26 @@ static int lcurl_easy_set_STREAM_DEPENDS_E(lua_State *L){
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
|
||||||
|
static int lcurl_easy_set_MIMEPOST(lua_State *L){
|
||||||
|
lcurl_easy_t *p = lcurl_geteasy(L);
|
||||||
|
lcurl_mime_t *mime = lcurl_getmime_at(L, 2);
|
||||||
|
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_MIMEPOST, mime->mime);
|
||||||
|
if(code != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurl_storage_preserve_iv(L, p->storage, CURLOPT_MIMEPOST, 2);
|
||||||
|
|
||||||
|
p->mime = mime;
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//{ unset
|
//{ unset
|
||||||
@ -775,6 +820,25 @@ static int lcurl_easy_unset_STREAM_DEPENDS_E(lua_State *L){
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
|
||||||
|
static int lcurl_easy_unset_MIMEPOST(lua_State *L){
|
||||||
|
lcurl_easy_t *p = lcurl_geteasy(L);
|
||||||
|
CURLcode code = curl_easy_setopt(p->curl, CURLOPT_MIMEPOST, NULL);
|
||||||
|
if(code != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurl_storage_remove_i(L, p->storage, CURLOPT_MIMEPOST);
|
||||||
|
|
||||||
|
p->mime = NULL;
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//}
|
//}
|
||||||
@ -1004,7 +1068,7 @@ static int lcurl_easy_set_WRITEFUNCTION(lua_State *L){
|
|||||||
|
|
||||||
//{ Reader
|
//{ Reader
|
||||||
|
|
||||||
static size_t lcurl_read_callback(lua_State *L,
|
size_t lcurl_read_callback(lua_State *L,
|
||||||
lcurl_callback_t *rd, lcurl_read_buffer_t *rbuffer,
|
lcurl_callback_t *rd, lcurl_read_buffer_t *rbuffer,
|
||||||
char *buffer, size_t size, size_t nitems
|
char *buffer, size_t size, size_t nitems
|
||||||
){
|
){
|
||||||
@ -1477,6 +1541,9 @@ static int lcurl_easy_setopt(lua_State *L){
|
|||||||
#if LCURL_CURL_VER_GE(7,46,0)
|
#if LCURL_CURL_VER_GE(7,46,0)
|
||||||
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
||||||
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
||||||
|
#endif
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY(mimepost, MIMEPOST, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
@ -1511,6 +1578,9 @@ static int lcurl_easy_unsetopt(lua_State *L){
|
|||||||
#if LCURL_CURL_VER_GE(7,46,0)
|
#if LCURL_CURL_VER_GE(7,46,0)
|
||||||
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
||||||
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
||||||
|
#endif
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY(mimepost, MIMEPOST, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
@ -1582,7 +1652,7 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
|
|||||||
OPT_ENTRY(seekfunction, SEEKFUNCTION, TTT, 0, 0)
|
OPT_ENTRY(seekfunction, SEEKFUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(debugfunction, DEBUGFUNCTION, TTT, 0, 0)
|
OPT_ENTRY(debugfunction, DEBUGFUNCTION, TTT, 0, 0)
|
||||||
#if LCURL_CURL_VER_GE(7,21,0)
|
#if LCURL_CURL_VER_GE(7,21,0)
|
||||||
OPT_ENTRY(fnmatch_function, FNMATCH_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(fnmatch_function, FNMATCH_FUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(chunk_bgn_function, CHUNK_BGN_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(chunk_bgn_function, CHUNK_BGN_FUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(chunk_end_function, CHUNK_END_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(chunk_end_function, CHUNK_END_FUNCTION, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
@ -1590,6 +1660,9 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
|
|||||||
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
||||||
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY(mimepost, MIMEPOST, TTT, 0, 0)
|
||||||
|
#endif
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
|
|
||||||
#define OPT_ENTRY(L, N, T, S, D) { "unsetopt_"#L, lcurl_easy_unset_##N },
|
#define OPT_ENTRY(L, N, T, S, D) { "unsetopt_"#L, lcurl_easy_unset_##N },
|
||||||
@ -1604,7 +1677,7 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
|
|||||||
OPT_ENTRY(seekfunction, SEEKFUNCTION, TTT, 0, 0)
|
OPT_ENTRY(seekfunction, SEEKFUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(debugfunction, DEBUGFUNCTION, TTT, 0, 0)
|
OPT_ENTRY(debugfunction, DEBUGFUNCTION, TTT, 0, 0)
|
||||||
#if LCURL_CURL_VER_GE(7,21,0)
|
#if LCURL_CURL_VER_GE(7,21,0)
|
||||||
OPT_ENTRY(fnmatch_function, FNMATCH_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(fnmatch_function, FNMATCH_FUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(chunk_bgn_function, CHUNK_BGN_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(chunk_bgn_function, CHUNK_BGN_FUNCTION, TTT, 0, 0)
|
||||||
OPT_ENTRY(chunk_end_function, CHUNK_END_FUNCTION, TTT, 0, 0)
|
OPT_ENTRY(chunk_end_function, CHUNK_END_FUNCTION, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
@ -1612,12 +1685,19 @@ static const struct luaL_Reg lcurl_easy_methods[] = {
|
|||||||
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
||||||
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY(mimepost, MIMEPOST, TTT, 0, 0)
|
||||||
|
#endif
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
|
|
||||||
#define OPT_ENTRY(L, N, T, S) { "getinfo_"#L, lcurl_easy_get_##N },
|
#define OPT_ENTRY(L, N, T, S) { "getinfo_"#L, lcurl_easy_get_##N },
|
||||||
#include "lcinfoeasy.h"
|
#include "lcinfoeasy.h"
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
{ "mime", lcurl_easy_mime },
|
||||||
|
#endif
|
||||||
|
|
||||||
{ "pause", lcurl_easy_pause },
|
{ "pause", lcurl_easy_pause },
|
||||||
{ "reset", lcurl_easy_reset },
|
{ "reset", lcurl_easy_reset },
|
||||||
{ "setopt", lcurl_easy_setopt },
|
{ "setopt", lcurl_easy_setopt },
|
||||||
@ -1659,6 +1739,9 @@ static const lcurl_const_t lcurl_easy_opt[] = {
|
|||||||
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
OPT_ENTRY(stream_depends, STREAM_DEPENDS, TTT, 0, 0)
|
||||||
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
OPT_ENTRY(stream_depends_e, STREAM_DEPENDS_E, TTT, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY(mimepost, MIMEPOST, TTT, 0, 0)
|
||||||
|
#endif
|
||||||
#undef OPT_ENTRY
|
#undef OPT_ENTRY
|
||||||
#undef FLG_ENTRY
|
#undef FLG_ENTRY
|
||||||
|
|
||||||
|
21
src/lceasy.h
21
src/lceasy.h
@ -1,7 +1,7 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Alexey Melnichuk <mimir@newmail.ru>
|
* Copyright (C) 2014-2017 Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Licensed according to the included 'LICENSE' document
|
* Licensed according to the included 'LICENSE' document
|
||||||
*
|
*
|
||||||
@ -37,9 +37,16 @@ enum {
|
|||||||
|
|
||||||
#if LCURL_CC_SUPPORT_FORWARD_TYPEDEF
|
#if LCURL_CC_SUPPORT_FORWARD_TYPEDEF
|
||||||
typedef struct lcurl_multi_tag lcurl_multi_t;
|
typedef struct lcurl_multi_tag lcurl_multi_t;
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
typedef struct lcurl_mime_tag lcurl_mime_t;
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
struct lcurl_multi_tag;
|
struct lcurl_multi_tag;
|
||||||
#define lcurl_multi_t struct lcurl_multi_tag
|
#define lcurl_multi_t struct lcurl_multi_tag
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
struct lcurl_mime_tag;
|
||||||
|
#define lcurl_mime_t struct lcurl_mime_tag;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct lcurl_easy_tag{
|
typedef struct lcurl_easy_tag{
|
||||||
@ -53,6 +60,10 @@ typedef struct lcurl_easy_tag{
|
|||||||
|
|
||||||
lcurl_multi_t *multi;
|
lcurl_multi_t *multi;
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
lcurl_mime_t *mime;
|
||||||
|
#endif
|
||||||
|
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
int storage;
|
int storage;
|
||||||
int lists[LCURL_LIST_COUNT];
|
int lists[LCURL_LIST_COUNT];
|
||||||
@ -77,8 +88,16 @@ void lcurl_easy_initlib(lua_State *L, int nup);
|
|||||||
|
|
||||||
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi);
|
void lcurl__easy_assign_lua(lua_State *L, lcurl_easy_t *p, lua_State *value, int assign_multi);
|
||||||
|
|
||||||
|
size_t lcurl_read_callback(lua_State *L,
|
||||||
|
lcurl_callback_t *rd, lcurl_read_buffer_t *rbuffer,
|
||||||
|
char *buffer, size_t size, size_t nitems
|
||||||
|
);
|
||||||
|
|
||||||
#if !LCURL_CC_SUPPORT_FORWARD_TYPEDEF
|
#if !LCURL_CC_SUPPORT_FORWARD_TYPEDEF
|
||||||
#undef lcurl_multi_t
|
#undef lcurl_multi_t
|
||||||
|
#ifdef lcurl_mime_t
|
||||||
|
#undef lcurl_mime_t
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,6 +44,19 @@ static const char *LCURL_HTTPPOST = LCURL_HTTPPOST_NAME;
|
|||||||
# define LCURL_LEN_TYPE long
|
# define LCURL_LEN_TYPE long
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 7.56.0 changed code for `curl_formget` if callback abort write.
|
||||||
|
*
|
||||||
|
* https://github.com/curl/curl/issues/1987#issuecomment-336139060
|
||||||
|
* ... not sure its worth the effort to document its return codes to
|
||||||
|
* any further extent then it currently is. This function is very
|
||||||
|
* rarely used, and the new mime API doesn't even have a version of it.
|
||||||
|
**/
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
# define LCURL_GET_CB_ERROR CURLE_READ_ERROR
|
||||||
|
#else
|
||||||
|
# define LCURL_GET_CB_ERROR (CURLcode)-1
|
||||||
|
#endif
|
||||||
|
|
||||||
//{ stream
|
//{ stream
|
||||||
|
|
||||||
static lcurl_hpost_stream_t *lcurl_hpost_stream_add(lua_State *L, lcurl_hpost_t *p){
|
static lcurl_hpost_stream_t *lcurl_hpost_stream_add(lua_State *L, lcurl_hpost_t *p){
|
||||||
@ -525,7 +538,7 @@ static int lcurl_hpost_get(lua_State *L){
|
|||||||
return lua_error(L);
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((CURLcode)-1 == code){
|
if(LCURL_GET_CB_ERROR == code){
|
||||||
if(((lua_gettop(L) == top+1))&&(lua_isstring(L, -1))){
|
if(((lua_gettop(L) == top+1))&&(lua_isstring(L, -1))){
|
||||||
return lua_error(L);
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
|
686
src/lcmime.c
Normal file
686
src/lcmime.c
Normal file
@ -0,0 +1,686 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Alexey Melnichuk <mimir@newmail.ru>
|
||||||
|
*
|
||||||
|
* Licensed according to the included 'LICENSE' document
|
||||||
|
*
|
||||||
|
* This file is part of lua-lcurl library.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "lcurl.h"
|
||||||
|
#include "lcmime.h"
|
||||||
|
#include "lceasy.h"
|
||||||
|
#include "lcerror.h"
|
||||||
|
#include "lcutils.h"
|
||||||
|
|
||||||
|
/* API Notes.
|
||||||
|
* 1. Each mime can be root or child. If mime is a child (subpart) then curl free it
|
||||||
|
* when parent mime is freed or when remove this part from parent. There no way reuse same mime.
|
||||||
|
* Its not clear is it possible use mime created by one easy handle when do preform in another.
|
||||||
|
* `m=e1:mime() e2:setopt_httpmime(m) e1:close() e2:perform()`
|
||||||
|
*
|
||||||
|
* // Attach child to root (root also can have parent)
|
||||||
|
* curl_mime_subparts(root, child);
|
||||||
|
*
|
||||||
|
* // curl free `child` and all its childs
|
||||||
|
* curl_mime_subparts(root, other_child_or_null);
|
||||||
|
*
|
||||||
|
* // forbidden
|
||||||
|
* curl_mime_free(child);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
|
||||||
|
#define LCURL_MIME_NAME LCURL_PREFIX" MIME"
|
||||||
|
static const char *LCURL_MIME = LCURL_MIME_NAME;
|
||||||
|
|
||||||
|
#define LCURL_MIME_PART_NAME LCURL_PREFIX" MIME Part"
|
||||||
|
static const char *LCURL_MIME_PART = LCURL_MIME_PART_NAME;
|
||||||
|
|
||||||
|
//{ Free mime and subparts
|
||||||
|
|
||||||
|
static void lcurl_mime_part_remove_subparts(lua_State *L, lcurl_mime_part_t *p, int free_it);
|
||||||
|
|
||||||
|
static lcurl_mime_t* lcurl_mime_part_get_subparts(lua_State *L, lcurl_mime_part_t *part){
|
||||||
|
lcurl_mime_t *sub = NULL;
|
||||||
|
|
||||||
|
if(LUA_NOREF != part->subpart_ref){
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, part->subpart_ref);
|
||||||
|
sub = lcurl_getmime_at(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_part_reset(lua_State *L, lcurl_mime_part_t *p){
|
||||||
|
p->part = NULL;
|
||||||
|
|
||||||
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->rd.cb_ref);
|
||||||
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->rd.ud_ref);
|
||||||
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->rbuffer.ref);
|
||||||
|
|
||||||
|
p->headers_ref = p->rbuffer.ref = p->rd.cb_ref = p->rd.ud_ref = LUA_NOREF;
|
||||||
|
|
||||||
|
/*free only if we have no parents*/
|
||||||
|
lcurl_mime_part_remove_subparts(L, p, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_reset(lua_State *L, lcurl_mime_t *p){
|
||||||
|
lcurl_mime_part_t *ptr;
|
||||||
|
|
||||||
|
/* reset all parts*/
|
||||||
|
for(ptr = p->parts; ptr; ptr=ptr->next){
|
||||||
|
lcurl_mime_part_reset(L, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(LUA_NOREF != p->storage){
|
||||||
|
p->storage = lcurl_storage_free(L, p->storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->parts = p->parent = NULL;
|
||||||
|
p->mime = NULL;
|
||||||
|
|
||||||
|
/* remove weak reference to easy */
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_rawsetp(L, LCURL_MIME_EASY, p);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcurl_mime_part_remove_subparts(lua_State *L, lcurl_mime_part_t *p, int free_it){
|
||||||
|
lcurl_mime_t *sub = lcurl_mime_part_get_subparts(L, p);
|
||||||
|
if(sub){
|
||||||
|
assert(LUA_NOREF != p->subpart_ref);
|
||||||
|
/* detach `subpart` mime from current mime part */
|
||||||
|
/* if set `sub->parent = NULL` then gc for mime will try free curl_mime_free. */
|
||||||
|
|
||||||
|
luaL_unref(L, LCURL_LUA_REGISTRY, p->subpart_ref);
|
||||||
|
p->subpart_ref = LUA_NOREF;
|
||||||
|
|
||||||
|
if(p->part && free_it){
|
||||||
|
curl_mime_subparts(p->part, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* seems curl_mime_subparts(h, NULL) free asubparts.
|
||||||
|
so we have to invalidate all reference to all nested objects (part/mime).
|
||||||
|
NOTE. All resources already feed. So just need set all pointers to NULL
|
||||||
|
and free all Lua resources (like references and storages)
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
lcurl_mime_part_t *ptr;
|
||||||
|
/* reset all parts*/
|
||||||
|
for(ptr = sub->parts; ptr; ptr=ptr->next){
|
||||||
|
lcurl_mime_part_remove_subparts(L, p, 0);
|
||||||
|
}
|
||||||
|
lcurl_mime_reset(L, sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
int lcurl_mime_set_lua(lua_State *L, lcurl_mime_t *p, lua_State *v){
|
||||||
|
lcurl_mime_part_t *part;
|
||||||
|
for(part = p->parts; part; part=part->next){
|
||||||
|
lcurl_mime_t *sub = lcurl_mime_part_get_subparts(L, part);
|
||||||
|
if(sub) lcurl_mime_set_lua(L, sub, v);
|
||||||
|
part->L = v;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IS_NILORSTR(L, i) (lua_type(L, i) == LUA_TSTRING) || (lua_type(L, i) == LUA_TNIL)
|
||||||
|
#define IS_TABLE(L, i) lua_type(L, i) == LUA_TTABLE
|
||||||
|
#define IS_FALSE(L, i) (lua_type(L, i) == LUA_TBOOLEAN) && (!lua_toboolean(L, i))
|
||||||
|
#define IS_OPTSTR(L, i) (IS_FALSE(L, i)) || (IS_NILORSTR(L, i))
|
||||||
|
|
||||||
|
static int lutil_isarray(lua_State *L, int i){
|
||||||
|
int ret = 0;
|
||||||
|
i = lua_absindex(L, i);
|
||||||
|
lua_pushnil(L);
|
||||||
|
if(lua_next(L, i)){
|
||||||
|
ret = lua_isnumber(L, -2);
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_part_assign(lua_State *L, int part, const char *method){
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
|
||||||
|
lua_pushvalue(L, part);
|
||||||
|
lua_insert(L, -2);
|
||||||
|
lua_getfield(L, -2, method);
|
||||||
|
lua_insert(L, -3);
|
||||||
|
lua_call(L, 2, LUA_MULTRET);
|
||||||
|
|
||||||
|
return lua_gettop(L) - top + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lcurl_mime_part_fields[] = {
|
||||||
|
"data", "filedata", "name", "filename", "headers", "encoder", "type", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lcurl_mime_part_assing_table(lua_State *L, int part, int t){
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
const char *method; int i;
|
||||||
|
|
||||||
|
part = lua_absindex(L, part);
|
||||||
|
t = lua_absindex(L, t);
|
||||||
|
|
||||||
|
if(lutil_isarray(L, t)){
|
||||||
|
int ret;
|
||||||
|
lua_pushvalue(L, t);
|
||||||
|
ret = lcurl_mime_part_assign(L, part, "headers");
|
||||||
|
if(ret != 1) return ret;
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
assert(top == lua_gettop(L));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for(i=0;method = lcurl_mime_part_fields[i]; ++i){
|
||||||
|
lua_getfield(L, t, method);
|
||||||
|
if(!lua_isnil(L, -1)){
|
||||||
|
int ret = lcurl_mime_part_assign(L, part, method);
|
||||||
|
if(ret != 1) return ret;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
assert(top == lua_gettop(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_getfield(L, t, "subparts");
|
||||||
|
if(!lua_isnil(L, -1)){
|
||||||
|
if(IS_FALSE(L, -1) || lcurl_getmime_at(L, -1)){
|
||||||
|
int ret = lcurl_mime_part_assign(L, part, "subparts");
|
||||||
|
if(ret != 1) return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
assert(top == lua_gettop(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//{ MIME
|
||||||
|
|
||||||
|
static lcurl_mime_part_t* lcurl_mime_parts_append(lcurl_mime_t *m, lcurl_mime_part_t *p){
|
||||||
|
if(!m->parts) m->parts = p;
|
||||||
|
else{
|
||||||
|
lcurl_mime_part_t *ptr = m->parts;
|
||||||
|
while(ptr->next)ptr = ptr->next;
|
||||||
|
ptr->next = p;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lcurl_mime_part_t* lcurl_mime_parts_find(lcurl_mime_t *m, lcurl_mime_part_t *p){
|
||||||
|
lcurl_mime_part_t *ptr;
|
||||||
|
|
||||||
|
for(ptr = m->parts; ptr; ptr = ptr->next){
|
||||||
|
if(ptr == p) return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lcurl_mime_create(lua_State *L, int error_mode){
|
||||||
|
//! @todo make this function as method of easy handle
|
||||||
|
lcurl_easy_t *e = lcurl_geteasy(L);
|
||||||
|
|
||||||
|
lcurl_mime_t *p = lutil_newudatap(L, lcurl_mime_t, LCURL_MIME);
|
||||||
|
|
||||||
|
p->mime = curl_mime_init(e->curl);
|
||||||
|
|
||||||
|
//! @todo return more accurate error category/code
|
||||||
|
if(!p->mime) return lcurl_fail_ex(L, error_mode, LCURL_ERROR_EASY, CURLE_FAILED_INIT);
|
||||||
|
|
||||||
|
p->storage = lcurl_storage_init(L);
|
||||||
|
p->err_mode = error_mode;
|
||||||
|
p->parts = p->parent = NULL;
|
||||||
|
|
||||||
|
/* weak reference from mime to easy handle */
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_rawsetp(L, LCURL_MIME_EASY, (void*)p);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurl_mime_t *lcurl_getmime_at(lua_State *L, int i){
|
||||||
|
lcurl_mime_t *p = (lcurl_mime_t *)lutil_checkudatap (L, i, LCURL_MIME);
|
||||||
|
luaL_argcheck (L, p != NULL, i, LCURL_MIME_NAME" object expected");
|
||||||
|
luaL_argcheck (L, p->mime != NULL, i, LCURL_MIME_NAME" object freed");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_to_s(lua_State *L){
|
||||||
|
lcurl_mime_t *p = (lcurl_mime_t *)lutil_checkudatap (L, 1, LCURL_MIME);
|
||||||
|
luaL_argcheck (L, p != NULL, 1, LCURL_MIME_NAME" object expected");
|
||||||
|
|
||||||
|
lua_pushfstring(L, LCURL_MIME_NAME" (%p)%s", (void*)p,
|
||||||
|
p->mime ? (p->parent ? " (subpart)" : "") : " (freed)"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_free(lua_State *L){
|
||||||
|
lcurl_mime_t *p = (lcurl_mime_t *)lutil_checkudatap (L, 1, LCURL_MIME);
|
||||||
|
luaL_argcheck (L, p != NULL, 1, LCURL_MIME_NAME" object expected");
|
||||||
|
|
||||||
|
if((p->mime) && (NULL == p->parent)){
|
||||||
|
curl_mime_free(p->mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lcurl_mime_reset(L, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_addpart(lua_State *L){
|
||||||
|
lcurl_mime_t *p = lcurl_getmime(L);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lua_settop(L, 2);
|
||||||
|
|
||||||
|
ret = lcurl_mime_part_create(L, p->err_mode);
|
||||||
|
if(ret != 1) return ret;
|
||||||
|
|
||||||
|
/* store mime part in storage */
|
||||||
|
lcurl_storage_preserve_value(L, p->storage, lua_absindex(L, -1));
|
||||||
|
lcurl_mime_parts_append(p, lcurl_getmimepart_at(L, -1));
|
||||||
|
|
||||||
|
if(lua_istable(L, 2)){
|
||||||
|
ret = lcurl_mime_part_assing_table(L, 3, 2);
|
||||||
|
if(ret) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_easy(lua_State *L){
|
||||||
|
lcurl_mime_t *p = lcurl_getmime(L);
|
||||||
|
lua_rawgetp(L, LCURL_MIME_EASY, p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
//{ MIME Part
|
||||||
|
|
||||||
|
int lcurl_mime_part_create(lua_State *L, int error_mode){
|
||||||
|
//! @todo make this function as method of mime handle
|
||||||
|
lcurl_mime_t *m = lcurl_getmime(L);
|
||||||
|
|
||||||
|
lcurl_mime_part_t *p = lutil_newudatap(L, lcurl_mime_part_t, LCURL_MIME_PART);
|
||||||
|
|
||||||
|
p->part = curl_mime_addpart(m->mime);
|
||||||
|
|
||||||
|
//! @todo return more accurate error category/code
|
||||||
|
if(!p->part) return lcurl_fail_ex(L, error_mode, LCURL_ERROR_EASY, CURLE_FAILED_INIT);
|
||||||
|
|
||||||
|
p->rbuffer.ref = p->rd.cb_ref = p->rd.ud_ref = LUA_NOREF;
|
||||||
|
p->err_mode = error_mode;
|
||||||
|
p->subpart_ref = p->headers_ref = LUA_NOREF;
|
||||||
|
p->parent = m;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurl_mime_part_t *lcurl_getmimepart_at(lua_State *L, int i){
|
||||||
|
lcurl_mime_part_t *p = (lcurl_mime_part_t *)lutil_checkudatap (L, i, LCURL_MIME_PART);
|
||||||
|
luaL_argcheck (L, p != NULL, i, LCURL_MIME_PART_NAME" object expected");
|
||||||
|
luaL_argcheck (L, p->part != NULL, i, LCURL_MIME_PART_NAME" object freed");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_part_to_s(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = (lcurl_mime_part_t *)lutil_checkudatap (L, 1, LCURL_MIME_PART);
|
||||||
|
luaL_argcheck (L, p != NULL, 1, LCURL_MIME_PART_NAME" object expected");
|
||||||
|
|
||||||
|
lua_pushfstring(L, LCURL_MIME_PART_NAME" (%p)%s", (void*)p, p->part ? "" : " (freed)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_part_free(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = (lcurl_mime_part_t *)lutil_checkudatap (L, 1, LCURL_MIME_PART);
|
||||||
|
luaL_argcheck (L, p != NULL, 1, LCURL_MIME_PART_NAME" object expected");
|
||||||
|
|
||||||
|
lcurl_mime_part_reset(L, p);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcurl_mime_part_assing_ext(lua_State *L, int part, int i){
|
||||||
|
#define UNSET_VALUE (const char*)-1
|
||||||
|
|
||||||
|
const char *mime_type = NULL, *mime_name = NULL, *mime_fname = NULL;
|
||||||
|
int headers = 0;
|
||||||
|
CURLcode ret;
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart_at(L, part);
|
||||||
|
|
||||||
|
if(IS_TABLE(L, i)) headers = i;
|
||||||
|
else if (IS_OPTSTR(L, i)) {
|
||||||
|
mime_type = IS_FALSE(L, i) ? UNSET_VALUE : lua_tostring(L, i);
|
||||||
|
if(IS_TABLE(L, i+1)) headers = i+1;
|
||||||
|
else if(IS_OPTSTR(L, i+1)){
|
||||||
|
mime_name = IS_FALSE(L, i+1) ? UNSET_VALUE : lua_tostring(L, i+1);
|
||||||
|
if(IS_TABLE(L, i+2)) headers = i+2;
|
||||||
|
else if(IS_OPTSTR(L, i+2)){
|
||||||
|
mime_fname = IS_FALSE(L, i+2) ? UNSET_VALUE : lua_tostring(L, i+2);
|
||||||
|
if(IS_TABLE(L, i+3)) headers = i+3;
|
||||||
|
else if(IS_FALSE(L, i+3)){
|
||||||
|
headers = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mime_type){
|
||||||
|
ret = curl_mime_type(p->part, mime_type == UNSET_VALUE ? NULL : mime_type);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mime_name){
|
||||||
|
ret = curl_mime_name(p->part, mime_name == UNSET_VALUE ? NULL : mime_name);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mime_fname){
|
||||||
|
ret = curl_mime_filename(p->part, mime_fname == UNSET_VALUE ? NULL : mime_fname);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(headers){
|
||||||
|
if(-1 == headers){
|
||||||
|
ret = curl_mime_headers(p->part, NULL, 0);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return lcurl_mime_part_assing_table(L, part, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#undef UNSET_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:data(str[, type[, name[, filename]]][, headers])
|
||||||
|
static int lcurl_mime_part_data(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
size_t len; const char *data;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
data = NULL;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
data = luaL_checklstring(L, 2, &len);
|
||||||
|
/*string too long*/
|
||||||
|
if(len == CURL_ZERO_TERMINATED){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, CURLE_BAD_FUNCTION_ARGUMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* curl_mime_data copies data */
|
||||||
|
ret = curl_mime_data(p->part, data, len);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_gettop(L) > 2){
|
||||||
|
int res = lcurl_mime_part_assing_ext(L, 1, 3);
|
||||||
|
if (res) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:subparts(mime[, type[, name]][, headers])
|
||||||
|
static int lcurl_mime_part_subparts(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
lcurl_mime_t *mime = lcurl_getmime_at(L, 2);
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
/* we can attach mime to only one part */
|
||||||
|
if(mime->parent){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, CURLE_BAD_FUNCTION_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we already have one subpart then libcurl free it so we can not use any references to it */
|
||||||
|
lcurl_mime_part_remove_subparts(L, p, 1);
|
||||||
|
|
||||||
|
ret = curl_mime_subparts(p->part, mime->mime);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushvalue(L, 2);
|
||||||
|
p->subpart_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
|
||||||
|
mime->parent = p;
|
||||||
|
|
||||||
|
if (lua_gettop(L) > 2){
|
||||||
|
int res = lcurl_mime_part_assing_ext(L, 1, 3);
|
||||||
|
if (res) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:filedata(path[, type[, name[, filename]]][, headers])
|
||||||
|
static int lcurl_mime_part_filedata(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
const char *data = luaL_checkstring(L, 2);
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
ret = curl_mime_filedata(p->part, data);
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_gettop(L) > 2){
|
||||||
|
int res = lcurl_mime_part_assing_ext(L, 1, 3);
|
||||||
|
if (res) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:headers(t)
|
||||||
|
static int lcurl_mime_part_headers(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
struct curl_slist *list;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
list = NULL;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
list = lcurl_util_to_slist(L, 2);
|
||||||
|
luaL_argcheck(L, list, 2, "array or nil expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = curl_mime_headers(p->part, list, 1);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:type(t)
|
||||||
|
static int lcurl_mime_part_type(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
const char *mime_type;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
mime_type = NULL;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mime_type = luaL_checkstring(L, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = curl_mime_type(p->part, mime_type);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:name(t)
|
||||||
|
static int lcurl_mime_part_name(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
const char *mime_name;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
mime_name = NULL;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mime_name = luaL_checkstring(L, 2);
|
||||||
|
}
|
||||||
|
ret = curl_mime_name(p->part, mime_name);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:filename(t)
|
||||||
|
static int lcurl_mime_part_filename(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
const char *mime_name;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
mime_name = NULL;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mime_name = luaL_checkstring(L, 2);
|
||||||
|
}
|
||||||
|
ret = curl_mime_filename(p->part, mime_name);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// part:encoder(t)
|
||||||
|
static int lcurl_mime_part_encoder(lua_State *L){
|
||||||
|
lcurl_mime_part_t *p = lcurl_getmimepart(L);
|
||||||
|
const char *mime_encode;
|
||||||
|
CURLcode ret;
|
||||||
|
|
||||||
|
if(IS_FALSE(L, 2)){
|
||||||
|
mime_encode = NULL;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mime_encode = luaL_checkstring(L, 2);
|
||||||
|
}
|
||||||
|
ret = curl_mime_encoder(p->part, mime_encode);
|
||||||
|
|
||||||
|
if(ret != CURLE_OK){
|
||||||
|
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
static const struct luaL_Reg lcurl_mime_methods[] = {
|
||||||
|
|
||||||
|
{"addpart", lcurl_mime_addpart },
|
||||||
|
{"easy", lcurl_mime_easy },
|
||||||
|
|
||||||
|
{"free", lcurl_mime_free },
|
||||||
|
{"__gc", lcurl_mime_free },
|
||||||
|
{"__tostring", lcurl_mime_to_s },
|
||||||
|
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct luaL_Reg lcurl_mime_part_methods[] = {
|
||||||
|
|
||||||
|
{"subparts", lcurl_mime_part_subparts },
|
||||||
|
{"data", lcurl_mime_part_data },
|
||||||
|
{"filedata", lcurl_mime_part_filedata },
|
||||||
|
{"headers", lcurl_mime_part_headers },
|
||||||
|
{"name", lcurl_mime_part_name },
|
||||||
|
{"filename", lcurl_mime_part_filename },
|
||||||
|
{"type", lcurl_mime_part_type },
|
||||||
|
{"encoder", lcurl_mime_part_encoder },
|
||||||
|
|
||||||
|
|
||||||
|
{"free", lcurl_mime_part_free },
|
||||||
|
{"__gc", lcurl_mime_part_free },
|
||||||
|
{"__tostring", lcurl_mime_part_to_s },
|
||||||
|
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lcurl_pushvalues(lua_State *L, int nup) {
|
||||||
|
assert(lua_gettop(L) >= nup);
|
||||||
|
|
||||||
|
if (nup > 0) {
|
||||||
|
int b = lua_absindex(L, -nup);
|
||||||
|
int e = lua_absindex(L, -1);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lua_checkstack(L, nup);
|
||||||
|
|
||||||
|
for(i = b; i <= e; ++i)
|
||||||
|
lua_pushvalue(L, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nup;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void lcurl_mime_initlib(lua_State *L, int nup){
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
lcurl_pushvalues(L, nup);
|
||||||
|
|
||||||
|
if(!lutil_createmetap(L, LCURL_MIME, lcurl_mime_methods, nup))
|
||||||
|
lua_pop(L, nup);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if(!lutil_createmetap(L, LCURL_MIME_PART, lcurl_mime_part_methods, nup))
|
||||||
|
lua_pop(L, nup);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
#else
|
||||||
|
lua_pop(L, nup);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
66
src/lcmime.h
Normal file
66
src/lcmime.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Alexey Melnichuk <mimir@newmail.ru>
|
||||||
|
*
|
||||||
|
* Licensed according to the included 'LICENSE' document
|
||||||
|
*
|
||||||
|
* This file is part of lua-lcurl library.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _LCMIME_H_
|
||||||
|
#define _LCMIME_H_
|
||||||
|
|
||||||
|
#include "lcurl.h"
|
||||||
|
#include "lcutils.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void lcurl_mime_initlib(lua_State *L, int nup);
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
|
||||||
|
typedef struct lcurl_mime_part_tag{
|
||||||
|
lua_State *L;
|
||||||
|
|
||||||
|
lcurl_callback_t rd;
|
||||||
|
lcurl_read_buffer_t rbuffer;
|
||||||
|
|
||||||
|
curl_mimepart *part;
|
||||||
|
|
||||||
|
struct lcurl_mime_tag *parent; /*always set and can not be changed*/
|
||||||
|
|
||||||
|
int subpart_ref;
|
||||||
|
int headers_ref;
|
||||||
|
|
||||||
|
int err_mode;
|
||||||
|
|
||||||
|
struct lcurl_mime_part_tag *next;
|
||||||
|
}lcurl_mime_part_t;
|
||||||
|
|
||||||
|
typedef struct lcurl_mime_tag{
|
||||||
|
curl_mime *mime;
|
||||||
|
|
||||||
|
int storage;
|
||||||
|
int err_mode;
|
||||||
|
|
||||||
|
lcurl_mime_part_t *parts;
|
||||||
|
lcurl_mime_part_t *parent; /*after set there no way change it*/
|
||||||
|
}lcurl_mime_t;
|
||||||
|
|
||||||
|
int lcurl_mime_create(lua_State *L, int error_mode);
|
||||||
|
|
||||||
|
lcurl_mime_t *lcurl_getmime_at(lua_State *L, int i);
|
||||||
|
|
||||||
|
#define lcurl_getmime(L) lcurl_getmime_at((L), 1)
|
||||||
|
|
||||||
|
int lcurl_mime_part_create(lua_State *L, int error_mode);
|
||||||
|
|
||||||
|
lcurl_mime_part_t *lcurl_getmimepart_at(lua_State *L, int i);
|
||||||
|
|
||||||
|
#define lcurl_getmimepart(L) lcurl_getmimepart_at((L), 1)
|
||||||
|
|
||||||
|
int lcurl_mime_set_lua(lua_State *L, lcurl_mime_t *p, lua_State *v);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -401,6 +401,10 @@ OPT_ENTRY( request_target, REQUEST_TARGET, STR, 0, LCURL_DEF
|
|||||||
OPT_ENTRY( socks5_auth, SOCKS5_AUTH, LNG, 0, LCURL_DEFAULT_VALUE)
|
OPT_ENTRY( socks5_auth, SOCKS5_AUTH, LNG, 0, LCURL_DEFAULT_VALUE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
OPT_ENTRY( ssh_compression, SSH_COMPRESSION, LNG, 0, LCURL_DEFAULT_VALUE)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LCURL__TCP_FASTOPEN
|
#ifdef LCURL__TCP_FASTOPEN
|
||||||
# define TCP_FASTOPEN LCURL__TCP_FASTOPEN
|
# define TCP_FASTOPEN LCURL__TCP_FASTOPEN
|
||||||
# undef LCURL__TCP_FASTOPEN
|
# undef LCURL__TCP_FASTOPEN
|
||||||
|
53
src/lcurl.c
53
src/lcurl.c
@ -14,6 +14,7 @@
|
|||||||
#include "lcshare.h"
|
#include "lcshare.h"
|
||||||
#include "lcerror.h"
|
#include "lcerror.h"
|
||||||
#include "lchttppost.h"
|
#include "lchttppost.h"
|
||||||
|
#include "lcmime.h"
|
||||||
#include "lcutils.h"
|
#include "lcutils.h"
|
||||||
|
|
||||||
/*export*/
|
/*export*/
|
||||||
@ -113,6 +114,10 @@ static int lcurl_version_info(lua_State *L){
|
|||||||
#ifdef CURL_VERSION_HTTPS_PROXY
|
#ifdef CURL_VERSION_HTTPS_PROXY
|
||||||
lua_pushliteral(L, "HTTPS_PROXY"); lua_pushboolean(L, data->features & CURL_VERSION_HTTPS_PROXY ); lua_rawset(L, -3);
|
lua_pushliteral(L, "HTTPS_PROXY"); lua_pushboolean(L, data->features & CURL_VERSION_HTTPS_PROXY ); lua_rawset(L, -3);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CURL_VERSION_MULTI_SSL
|
||||||
|
lua_pushliteral(L, "MULTI_SSL"); lua_pushboolean(L, data->features & CURL_VERSION_MULTI_SSL ); lua_rawset(L, -3);
|
||||||
|
#endif
|
||||||
|
|
||||||
lua_setfield(L, -2, "features"); /* bitmask, see defines below */
|
lua_setfield(L, -2, "features"); /* bitmask, see defines below */
|
||||||
|
|
||||||
if(data->ssl_version){lua_pushstring(L, data->ssl_version); lua_setfield(L, -2, "ssl_version");} /* human readable string */
|
if(data->ssl_version){lua_pushstring(L, data->ssl_version); lua_setfield(L, -2, "ssl_version");} /* human readable string */
|
||||||
@ -155,7 +160,7 @@ static const struct luaL_Reg lcurl_functions[] = {
|
|||||||
{"share", lcurl_share_new },
|
{"share", lcurl_share_new },
|
||||||
{"version", lcurl_version },
|
{"version", lcurl_version },
|
||||||
{"version_info", lcurl_version_info },
|
{"version_info", lcurl_version_info },
|
||||||
|
|
||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -184,6 +189,21 @@ static volatile int LCURL_INIT = 0;
|
|||||||
|
|
||||||
static const char* LCURL_REGISTRY = "LCURL Registry";
|
static const char* LCURL_REGISTRY = "LCURL Registry";
|
||||||
static const char* LCURL_USERVAL = "LCURL Uservalues";
|
static const char* LCURL_USERVAL = "LCURL Uservalues";
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
static const char* LCURL_MIME_EASY_MAP = "LCURL Mime easy";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
#define NUP 3
|
||||||
|
#else
|
||||||
|
#define NUP 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
#define LCURL_PUSH_NUP(L) lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);
|
||||||
|
#else
|
||||||
|
#define LCURL_PUSH_NUP(L) lua_pushvalue(L, -NUP-1);lua_pushvalue(L, -NUP-1);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
|
static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
|
||||||
if(!LCURL_INIT){
|
if(!LCURL_INIT){
|
||||||
@ -209,19 +229,32 @@ static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
|
|||||||
lcurl_util_new_weak_table(L, "k");
|
lcurl_util_new_weak_table(L, "k");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
lua_rawgetp(L, LUA_REGISTRYINDEX, LCURL_MIME_EASY_MAP);
|
||||||
|
if(!lua_istable(L, -1)){ /* Mime->Easy */
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lcurl_util_new_weak_table(L, "v");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lua_newtable(L); /* library */
|
lua_newtable(L); /* library */
|
||||||
|
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); luaL_setfuncs(L, func, 2);
|
LCURL_PUSH_NUP(L); luaL_setfuncs(L, func, NUP);
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_error_initlib(L, 2);
|
LCURL_PUSH_NUP(L); lcurl_error_initlib(L, NUP);
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_hpost_initlib(L, 2);
|
LCURL_PUSH_NUP(L); lcurl_hpost_initlib(L, NUP);
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_easy_initlib (L, 2);
|
LCURL_PUSH_NUP(L); lcurl_easy_initlib (L, NUP);
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_multi_initlib(L, 2);
|
LCURL_PUSH_NUP(L); lcurl_mime_initlib (L, NUP);
|
||||||
lua_pushvalue(L, -3); lua_pushvalue(L, -3); lcurl_share_initlib(L, 2);
|
LCURL_PUSH_NUP(L); lcurl_multi_initlib(L, NUP);
|
||||||
|
LCURL_PUSH_NUP(L); lcurl_share_initlib(L, NUP);
|
||||||
|
|
||||||
lua_pushvalue(L, -3); lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_REGISTRY);
|
LCURL_PUSH_NUP(L);
|
||||||
lua_pushvalue(L, -2); lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_USERVAL);
|
|
||||||
|
|
||||||
lua_remove(L, -2); /* registry */
|
#if LCURL_CURL_VER_GE(7,56,0)
|
||||||
|
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_MIME_EASY_MAP);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_USERVAL);
|
||||||
|
lua_rawsetp(L, LUA_REGISTRYINDEX, LCURL_REGISTRY);
|
||||||
|
|
||||||
lcurl_util_set_const(L, lcurl_flags);
|
lcurl_util_set_const(L, lcurl_flags);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Alexey Melnichuk <mimir@newmail.ru>
|
* Copyright (C) 2014-2017 Alexey Melnichuk <mimir@newmail.ru>
|
||||||
*
|
*
|
||||||
* Licensed according to the included 'LICENSE' document
|
* Licensed according to the included 'LICENSE' document
|
||||||
*
|
*
|
||||||
@ -25,4 +25,7 @@
|
|||||||
|
|
||||||
#define LCURL_USERVALUES lua_upvalueindex(2)
|
#define LCURL_USERVALUES lua_upvalueindex(2)
|
||||||
|
|
||||||
|
/* only for `mime` API */
|
||||||
|
#define LCURL_MIME_EASY lua_upvalueindex(3)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,13 +21,21 @@ int lcurl_storage_init(lua_State *L){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lcurl_storage_preserve_value(lua_State *L, int storage, int i){
|
void lcurl_storage_preserve_value(lua_State *L, int storage, int i){
|
||||||
assert(i > 0);
|
assert(i > 0 && i <= lua_gettop(L));
|
||||||
luaL_checkany(L, i);
|
luaL_checkany(L, i);
|
||||||
lua_rawgeti(L, LCURL_LUA_REGISTRY, storage);
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, storage);
|
||||||
lua_pushvalue(L, i); lua_pushboolean(L, 1); lua_rawset(L, -3);
|
lua_pushvalue(L, i); lua_pushboolean(L, 1); lua_rawset(L, -3);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lcurl_storage_remove_value(lua_State *L, int storage, int i){
|
||||||
|
assert(i > 0 && i <= lua_gettop(L));
|
||||||
|
luaL_checkany(L, i);
|
||||||
|
lua_rawgeti(L, LCURL_LUA_REGISTRY, storage);
|
||||||
|
lua_pushvalue(L, i); lua_pushnil(L); lua_rawset(L, -3);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void lcurl_storage_ensure_t(lua_State *L, int t){
|
static void lcurl_storage_ensure_t(lua_State *L, int t){
|
||||||
lua_rawgeti(L, -1, t);
|
lua_rawgeti(L, -1, t);
|
||||||
if(!lua_istable(L, -1)){
|
if(!lua_istable(L, -1)){
|
||||||
@ -256,7 +264,7 @@ int lcurl_utils_apply_options(lua_State *L, int opt, int obj, int do_close,
|
|||||||
while(lua_next(L, opt) != 0){
|
while(lua_next(L, opt) != 0){
|
||||||
int n;
|
int n;
|
||||||
assert(lua_gettop(L) == (top + 2));
|
assert(lua_gettop(L) == (top + 2));
|
||||||
|
|
||||||
if(lua_type(L, -2) == LUA_TNUMBER){ /* [curl.OPT_URL] = "http://localhost" */
|
if(lua_type(L, -2) == LUA_TNUMBER){ /* [curl.OPT_URL] = "http://localhost" */
|
||||||
lua_pushvalue(L, -2);
|
lua_pushvalue(L, -2);
|
||||||
lua_insert(L, -2); /*Stack : opt, obj, k, k, v */
|
lua_insert(L, -2); /*Stack : opt, obj, k, k, v */
|
||||||
|
@ -55,6 +55,8 @@ int lcurl_storage_init(lua_State *L);
|
|||||||
|
|
||||||
void lcurl_storage_preserve_value(lua_State *L, int storage, int i);
|
void lcurl_storage_preserve_value(lua_State *L, int storage, int i);
|
||||||
|
|
||||||
|
void lcurl_storage_remove_value(lua_State *L, int storage, int i);
|
||||||
|
|
||||||
int lcurl_storage_preserve_slist(lua_State *L, int storage, struct curl_slist * list);
|
int lcurl_storage_preserve_slist(lua_State *L, int storage, struct curl_slist * list);
|
||||||
|
|
||||||
struct curl_slist* lcurl_storage_remove_slist(lua_State *L, int storage, int idx);
|
struct curl_slist* lcurl_storage_remove_slist(lua_State *L, int storage, int idx);
|
||||||
|
@ -27,6 +27,7 @@ print("")
|
|||||||
require "test_safe"
|
require "test_safe"
|
||||||
require "test_easy"
|
require "test_easy"
|
||||||
require "test_form"
|
require "test_form"
|
||||||
|
require "test_mime"
|
||||||
require "test_curl"
|
require "test_curl"
|
||||||
|
|
||||||
RUN()
|
RUN()
|
||||||
|
121
test/server.lua
Normal file
121
test/server.lua
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
local function prequire(m)
|
||||||
|
local ok, err = pcall(require, m)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
return err
|
||||||
|
end
|
||||||
|
|
||||||
|
local uv = prequire "lluv"
|
||||||
|
local Pegasus = require (uv and "lluv.pegasus" or "pegasus")
|
||||||
|
local Router = require "pegasus.plugins.router"
|
||||||
|
local json = require "dkjson"
|
||||||
|
-- local pp = require "pp"
|
||||||
|
|
||||||
|
local function decode_form(form)
|
||||||
|
return string.match(form, '\r\nContent%-Disposition:%s*form%-data;%s*name="(.-)".-\r\n\r\n(.-)\r\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function decode_params(str)
|
||||||
|
local params = {}
|
||||||
|
for k, v in string.gmatch(str, '([^=]+)=([^&]+)&?') do
|
||||||
|
params[k] = v
|
||||||
|
end
|
||||||
|
return params
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rand_bytes(n)
|
||||||
|
local res = {}
|
||||||
|
for i = 1, n do
|
||||||
|
res[#res + 1] = string.char(math.random(254))
|
||||||
|
end
|
||||||
|
return table.concat(res)
|
||||||
|
end
|
||||||
|
|
||||||
|
local r = Router:new()
|
||||||
|
|
||||||
|
local server = Pegasus:new{
|
||||||
|
plugins = { r };
|
||||||
|
host = '127.0.0.1', port = 7090, timout = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
local function recvFullBody(request, T1)
|
||||||
|
local body, counter = {}, 0
|
||||||
|
|
||||||
|
local result, status
|
||||||
|
while true do
|
||||||
|
result, status = request:receiveBody()
|
||||||
|
if result then
|
||||||
|
counter = 0
|
||||||
|
body[#body + 1] = result
|
||||||
|
elseif status ~= 'timeout' then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
counter = counter + 1
|
||||||
|
if counter > T1 then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(body), status
|
||||||
|
end
|
||||||
|
|
||||||
|
local function buildResponse(request)
|
||||||
|
local headers = request:headers()
|
||||||
|
local params = request:params()
|
||||||
|
local path = request:path()
|
||||||
|
local ip = request.ip
|
||||||
|
local host = headers and headers.Host or '127.0.0.1'
|
||||||
|
local url = string.format('http://%s%s', host, path)
|
||||||
|
|
||||||
|
return {
|
||||||
|
args = params;
|
||||||
|
headers = headers;
|
||||||
|
origin = ip;
|
||||||
|
url = url;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
r:get('/get', function(request, response)
|
||||||
|
local result = buildResponse(request)
|
||||||
|
result.body = recvFullBody(request, 15)
|
||||||
|
|
||||||
|
response:statusCode(200)
|
||||||
|
response:contentType('application/json')
|
||||||
|
response:write(json.encode(result, {indent = true}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
r:post('/post', function(request, response, params)
|
||||||
|
local result = buildResponse(request)
|
||||||
|
|
||||||
|
local body, status = recvFullBody(request, 15)
|
||||||
|
|
||||||
|
local name, data = decode_form(body)
|
||||||
|
if name then
|
||||||
|
result.form = {[name] = data}
|
||||||
|
else
|
||||||
|
result.form = decode_params(body)
|
||||||
|
end
|
||||||
|
|
||||||
|
response:statusCode(200)
|
||||||
|
response:contentType('application/json')
|
||||||
|
response:write(json.encode(result, {indent = true}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
r:get('/bytes/:size', function(request, response, params)
|
||||||
|
local headers = request:headers()
|
||||||
|
local size = tonumber(params.size) or 1024
|
||||||
|
local result = rand_bytes(size)
|
||||||
|
|
||||||
|
response:statusCode(200)
|
||||||
|
response:addHeader('Connection', 'close')
|
||||||
|
response:contentType('application/octet-stream')
|
||||||
|
response:write(result)
|
||||||
|
end)
|
||||||
|
|
||||||
|
server:start(function(request, response)
|
||||||
|
local headers = request:headers()
|
||||||
|
|
||||||
|
response:statusCode(200)
|
||||||
|
response:addHeader('Content-Type', 'text/plain')
|
||||||
|
response:write('Hello from Pegasus')
|
||||||
|
end)
|
||||||
|
|
||||||
|
if uv then uv.run() end
|
@ -18,6 +18,13 @@ local scurl = require "cURL.safe"
|
|||||||
local json = require "dkjson"
|
local json = require "dkjson"
|
||||||
local fname = "./test.download"
|
local fname = "./test.download"
|
||||||
|
|
||||||
|
local utils = require "utils"
|
||||||
|
|
||||||
|
-- Bug. libcurl 7.56.0 does not add `Content-Type: text/plain`
|
||||||
|
local text_plain = utils.is_curl_eq(7,56,0) and 'test/plain' or 'text/plain'
|
||||||
|
|
||||||
|
local GET_URL = "http://127.0.0.1:7090/get"
|
||||||
|
|
||||||
local ENABLE = true
|
local ENABLE = true
|
||||||
|
|
||||||
local _ENV = TEST_CASE'version' if ENABLE then
|
local _ENV = TEST_CASE'version' if ENABLE then
|
||||||
@ -29,7 +36,7 @@ end
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local _ENV = TEST_CASE'easy' if ENABLE then
|
local _ENV = TEST_CASE'easy' if ENABLE then
|
||||||
|
|
||||||
local e1, e2
|
local e1, e2
|
||||||
function teardown()
|
function teardown()
|
||||||
@ -118,7 +125,7 @@ end
|
|||||||
|
|
||||||
local _ENV = TEST_CASE'multi_iterator' if ENABLE then
|
local _ENV = TEST_CASE'multi_iterator' if ENABLE then
|
||||||
|
|
||||||
local url = "http://httpbin.org/get"
|
local url = GET_URL
|
||||||
|
|
||||||
local c, t, m
|
local c, t, m
|
||||||
|
|
||||||
@ -138,8 +145,7 @@ function teardown()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_add_handle()
|
function test_add_handle()
|
||||||
|
local base_url = url .. '?key='
|
||||||
local base_url = 'http://httpbin.org/get?key='
|
|
||||||
local urls = {
|
local urls = {
|
||||||
base_url .. "1",
|
base_url .. "1",
|
||||||
base_url .. "2",
|
base_url .. "2",
|
||||||
@ -190,7 +196,9 @@ function test_add_handle()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_info_read()
|
function test_info_read()
|
||||||
local url = 'http://httpbin.org/get?key=1'
|
|
||||||
|
local url = GET_URL .. '?key=1'
|
||||||
|
|
||||||
c = assert(curl.easy{url=url, writefunction=function() end})
|
c = assert(curl.easy{url=url, writefunction=function() end})
|
||||||
assert_equal(m, m:add_handle(c))
|
assert_equal(m, m:add_handle(c))
|
||||||
|
|
||||||
@ -222,11 +230,11 @@ function test_content_01()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_content_02()
|
function test_content_02()
|
||||||
post = assert(scurl.form{name02 = {'value02', type = "text/plain"}})
|
post = assert(scurl.form{name02 = {'value02', type = text_plain}})
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue02\r\n", data)
|
assert_match("\r\n\r\nvalue02\r\n", data)
|
||||||
assert_match('name="name02"', data)
|
assert_match('name="name02"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_content_03()
|
function test_content_03()
|
||||||
@ -238,12 +246,12 @@ function test_content_03()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_content_04()
|
function test_content_04()
|
||||||
post = assert(scurl.form{name04 = {'value04', type = "text/plain", headers = {"Content-Encoding: gzip"}}})
|
post = assert(scurl.form{name04 = {'value04', type = text_plain, headers = {"Content-Encoding: gzip"}}})
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue04\r\n", data)
|
assert_match("\r\n\r\nvalue04\r\n", data)
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_buffer_01()
|
function test_buffer_01()
|
||||||
@ -263,14 +271,14 @@ function test_buffer_02()
|
|||||||
post = assert(scurl.form{name02 = {
|
post = assert(scurl.form{name02 = {
|
||||||
name = 'file02',
|
name = 'file02',
|
||||||
data = 'value02',
|
data = 'value02',
|
||||||
type = "text/plain",
|
type = text_plain,
|
||||||
}})
|
}})
|
||||||
|
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue02\r\n", data)
|
assert_match("\r\n\r\nvalue02\r\n", data)
|
||||||
assert_match('name="name02"', data)
|
assert_match('name="name02"', data)
|
||||||
assert_match('filename="file02"', data)
|
assert_match('filename="file02"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -292,7 +300,7 @@ function test_buffer_04()
|
|||||||
post = assert(scurl.form{name04 = {
|
post = assert(scurl.form{name04 = {
|
||||||
name = 'file04',
|
name = 'file04',
|
||||||
data = 'value04',
|
data = 'value04',
|
||||||
type = "text/plain",
|
type = text_plain,
|
||||||
headers = {"Content-Encoding: gzip"},
|
headers = {"Content-Encoding: gzip"},
|
||||||
}})
|
}})
|
||||||
|
|
||||||
@ -300,7 +308,7 @@ function test_buffer_04()
|
|||||||
assert_match("\r\n\r\nvalue04\r\n", data)
|
assert_match("\r\n\r\nvalue04\r\n", data)
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('filename="file04"', data)
|
assert_match('filename="file04"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
@ -331,13 +339,13 @@ function test_stream_03()
|
|||||||
name = 'file03',
|
name = 'file03',
|
||||||
stream = function() end,
|
stream = function() end,
|
||||||
length = 128,
|
length = 128,
|
||||||
type = 'text/plain',
|
type = text_plain,
|
||||||
}})
|
}})
|
||||||
|
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match('name="name03"', data)
|
assert_match('name="name03"', data)
|
||||||
assert_match('filename="file03"', data)
|
assert_match('filename="file03"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_stream_04()
|
function test_stream_04()
|
||||||
@ -345,13 +353,13 @@ function test_stream_04()
|
|||||||
name = 'file04',
|
name = 'file04',
|
||||||
stream = function() end,
|
stream = function() end,
|
||||||
length = 128,
|
length = 128,
|
||||||
type = 'text/plain',
|
type = text_plain,
|
||||||
headers = {"Content-Encoding: gzip"},
|
headers = {"Content-Encoding: gzip"},
|
||||||
}})
|
}})
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('filename="file04"', data)
|
assert_match('filename="file04"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,75 +17,23 @@ local scurl = require "lcurl.safe"
|
|||||||
local json = require "dkjson"
|
local json = require "dkjson"
|
||||||
local path = require "path"
|
local path = require "path"
|
||||||
local upath = require "path".new('/')
|
local upath = require "path".new('/')
|
||||||
local url = "http://example.com"
|
local utils = require "utils"
|
||||||
|
-- local url = "http://127.0.0.1:7090/get"
|
||||||
local fname = "./test.download"
|
local fname = "./test.download"
|
||||||
|
|
||||||
|
-- local GET_URL = "http://example.com"
|
||||||
|
-- local POST_URL = "http://httpbin.org/post"
|
||||||
|
local GET_URL = "http://127.0.0.1:7090/get"
|
||||||
|
local POST_URL = "http://127.0.0.1:7090/post"
|
||||||
|
|
||||||
-- print("------------------------------------")
|
-- print("------------------------------------")
|
||||||
-- print("Lua version: " .. (_G.jit and _G.jit.version or _G._VERSION))
|
-- print("Lua version: " .. (_G.jit and _G.jit.version or _G._VERSION))
|
||||||
-- print("cURL version: " .. curl.version())
|
-- print("cURL version: " .. curl.version())
|
||||||
-- print("------------------------------------")
|
-- print("------------------------------------")
|
||||||
-- print("")
|
-- print("")
|
||||||
|
|
||||||
local function weak_ptr(val)
|
local weak_ptr, gc_collect, is_curl_ge, read_file, stream, Stream =
|
||||||
return setmetatable({value = val},{__mode = 'v'})
|
utils.import('weak_ptr', 'gc_collect', 'is_curl_ge', 'read_file', 'stream', 'Stream')
|
||||||
end
|
|
||||||
|
|
||||||
local function gc_collect()
|
|
||||||
collectgarbage("collect")
|
|
||||||
collectgarbage("collect")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function cver(min, maj, pat)
|
|
||||||
return min * 2^16 + maj * 2^8 + pat
|
|
||||||
end
|
|
||||||
|
|
||||||
local function is_curl_ge(min, maj, pat)
|
|
||||||
assert(0x070908 == cver(7,9,8))
|
|
||||||
return curl.version_info('version_num') >= cver(min, maj, pat)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function read_file(n)
|
|
||||||
local f, e = io.open(n, "r")
|
|
||||||
if not f then return nil, e end
|
|
||||||
local d, e = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
return d, e
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_bin_by(str,n)
|
|
||||||
local pos = 1 - n
|
|
||||||
return function()
|
|
||||||
pos = pos + n
|
|
||||||
return (str:sub(pos,pos+n-1))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function strem(ch, n, m)
|
|
||||||
return n, get_bin_by( (ch):rep(n), m)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function Stream(ch, n, m)
|
|
||||||
local size, reader
|
|
||||||
|
|
||||||
local _stream = {}
|
|
||||||
|
|
||||||
function _stream:read(...)
|
|
||||||
_stream.called_ctx = self
|
|
||||||
_stream.called_co = coroutine.running()
|
|
||||||
return reader(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _stream:size()
|
|
||||||
return size
|
|
||||||
end
|
|
||||||
|
|
||||||
function _stream:reset()
|
|
||||||
size, reader = strem(ch, n, m)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
return _stream:reset()
|
|
||||||
end
|
|
||||||
|
|
||||||
local ENABLE = true
|
local ENABLE = true
|
||||||
|
|
||||||
@ -150,7 +98,7 @@ end
|
|||||||
function test_write_to_file()
|
function test_write_to_file()
|
||||||
f = assert(io.open(fname, "w+b"))
|
f = assert(io.open(fname, "w+b"))
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = f;
|
writefunction = f;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -159,7 +107,7 @@ end
|
|||||||
|
|
||||||
function test_write_abort_01()
|
function test_write_abort_01()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function(str) return #str - 1 end;
|
writefunction = function(str) return #str - 1 end;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -169,7 +117,7 @@ end
|
|||||||
|
|
||||||
function test_write_abort_02()
|
function test_write_abort_02()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function(str) return false end;
|
writefunction = function(str) return false end;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -179,7 +127,7 @@ end
|
|||||||
|
|
||||||
function test_write_abort_03()
|
function test_write_abort_03()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function(str) return nil, "WRITEERROR" end;
|
writefunction = function(str) return nil, "WRITEERROR" end;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -189,7 +137,7 @@ end
|
|||||||
|
|
||||||
function test_write_abort_04()
|
function test_write_abort_04()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function(str) return nil end;
|
writefunction = function(str) return nil end;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -210,7 +158,7 @@ end
|
|||||||
|
|
||||||
function test_write_pass_01()
|
function test_write_pass_01()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function(s) return #s end
|
writefunction = function(s) return #s end
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -219,7 +167,7 @@ end
|
|||||||
|
|
||||||
function test_write_pass_02()
|
function test_write_pass_02()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function() return end
|
writefunction = function() return end
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -228,7 +176,7 @@ end
|
|||||||
|
|
||||||
function test_write_pass_03()
|
function test_write_pass_03()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function() return true end
|
writefunction = function() return true end
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -241,7 +189,7 @@ function test_write_coro()
|
|||||||
|
|
||||||
co1 = coroutine.create(function()
|
co1 = coroutine.create(function()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = function()
|
writefunction = function()
|
||||||
called = coroutine.running()
|
called = coroutine.running()
|
||||||
return true
|
return true
|
||||||
@ -277,7 +225,7 @@ end
|
|||||||
|
|
||||||
function test_abort_01()
|
function test_abort_01()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return false end
|
progressfunction = function() return false end
|
||||||
@ -289,7 +237,7 @@ end
|
|||||||
|
|
||||||
function test_abort_02()
|
function test_abort_02()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return 0 end
|
progressfunction = function() return 0 end
|
||||||
@ -301,7 +249,7 @@ end
|
|||||||
|
|
||||||
function test_abort_03()
|
function test_abort_03()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return nil end
|
progressfunction = function() return nil end
|
||||||
@ -313,7 +261,7 @@ end
|
|||||||
|
|
||||||
function test_abort_04()
|
function test_abort_04()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return nil, "PROGRESSERROR" end
|
progressfunction = function() return nil, "PROGRESSERROR" end
|
||||||
@ -325,7 +273,7 @@ end
|
|||||||
|
|
||||||
function test_abort_05()
|
function test_abort_05()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() error( "PROGRESSERROR" )end
|
progressfunction = function() error( "PROGRESSERROR" )end
|
||||||
@ -338,7 +286,7 @@ end
|
|||||||
|
|
||||||
function test_pass_01()
|
function test_pass_01()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() end
|
progressfunction = function() end
|
||||||
@ -349,7 +297,7 @@ end
|
|||||||
|
|
||||||
function test_pass_02()
|
function test_pass_02()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return true end
|
progressfunction = function() return true end
|
||||||
@ -360,7 +308,7 @@ end
|
|||||||
|
|
||||||
function test_pass_03()
|
function test_pass_03()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url,
|
url = GET_URL,
|
||||||
writefunction = pass,
|
writefunction = pass,
|
||||||
noprogress = false,
|
noprogress = false,
|
||||||
progressfunction = function() return 1 end
|
progressfunction = function() return 1 end
|
||||||
@ -383,7 +331,7 @@ end
|
|||||||
|
|
||||||
function test_header_abort_01()
|
function test_header_abort_01()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function(str) return #str - 1 end;
|
headerfunction = function(str) return #str - 1 end;
|
||||||
})
|
})
|
||||||
@ -394,7 +342,7 @@ end
|
|||||||
|
|
||||||
function test_header_abort_02()
|
function test_header_abort_02()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function(str) return false end;
|
headerfunction = function(str) return false end;
|
||||||
})
|
})
|
||||||
@ -405,7 +353,7 @@ end
|
|||||||
|
|
||||||
function test_header_abort_03()
|
function test_header_abort_03()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function(str) return nil, "WRITEERROR" end;
|
headerfunction = function(str) return nil, "WRITEERROR" end;
|
||||||
})
|
})
|
||||||
@ -416,7 +364,7 @@ end
|
|||||||
|
|
||||||
function test_header_abort_04()
|
function test_header_abort_04()
|
||||||
c = assert(scurl.easy{
|
c = assert(scurl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function(str) return nil end;
|
headerfunction = function(str) return nil end;
|
||||||
})
|
})
|
||||||
@ -438,7 +386,7 @@ end
|
|||||||
|
|
||||||
function test_header_pass_01()
|
function test_header_pass_01()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function(s) return #s end
|
headerfunction = function(s) return #s end
|
||||||
})
|
})
|
||||||
@ -448,7 +396,7 @@ end
|
|||||||
|
|
||||||
function test_header_pass_02()
|
function test_header_pass_02()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function() return end
|
headerfunction = function() return end
|
||||||
})
|
})
|
||||||
@ -458,7 +406,7 @@ end
|
|||||||
|
|
||||||
function test_header_pass_03()
|
function test_header_pass_03()
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = url;
|
url = GET_URL;
|
||||||
writefunction = dummy,
|
writefunction = dummy,
|
||||||
headerfunction = function() return true end
|
headerfunction = function() return true end
|
||||||
})
|
})
|
||||||
@ -473,7 +421,7 @@ local _ENV = TEST_CASE'read_stream_callback' if ENABLE and is_curl_ge(7,30,0) th
|
|||||||
|
|
||||||
-- tested on WinXP(x32)/Win8(x64) libcurl/7.37.1 / libcurl/7.30.0
|
-- tested on WinXP(x32)/Win8(x64) libcurl/7.37.1 / libcurl/7.30.0
|
||||||
|
|
||||||
local url = "http://httpbin.org/post"
|
local url = POST_URL
|
||||||
|
|
||||||
local m, c, f, t
|
local m, c, f, t
|
||||||
|
|
||||||
@ -499,7 +447,7 @@ function teardown()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
assert_equal(f, f:add_stream('SSSSS', strem('X', 128, 13)))
|
assert_equal(f, f:add_stream('SSSSS', stream('X', 128, 13)))
|
||||||
assert_equal(c, c:setopt_httppost(f))
|
assert_equal(c, c:setopt_httppost(f))
|
||||||
|
|
||||||
-- should be called only stream callback
|
-- should be called only stream callback
|
||||||
@ -922,10 +870,10 @@ end
|
|||||||
function test()
|
function test()
|
||||||
|
|
||||||
do local fields = {}
|
do local fields = {}
|
||||||
for i = 1, 100 do fields[#fields + 1] = "key" .. i .. "=value"..i end
|
for i = 1, 100 do fields[#fields + 1] = string.format('key%d=value%d', i, i) end
|
||||||
fields = table.concat(fields, '&')
|
fields = table.concat(fields, '&')
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = "http://httpbin.org/post",
|
url = POST_URL,
|
||||||
postfields = fields,
|
postfields = fields,
|
||||||
writefunction = function()end,
|
writefunction = function()end,
|
||||||
})
|
})
|
||||||
@ -941,10 +889,10 @@ function test_unset()
|
|||||||
local pfields
|
local pfields
|
||||||
|
|
||||||
do local fields = {}
|
do local fields = {}
|
||||||
for i = 1, 100 do fields[#fields + 1] = "key" .. i .. "=value"..i end
|
for i = 1, 100 do fields[#fields + 1] = string.format('key%d=value%d', i, i) end
|
||||||
fields = table.concat(fields, '&')
|
fields = table.concat(fields, '&')
|
||||||
c = assert(curl.easy{
|
c = assert(curl.easy{
|
||||||
url = "http://httpbin.org/post",
|
url = POST_URL,
|
||||||
postfields = fields,
|
postfields = fields,
|
||||||
writefunction = function()end,
|
writefunction = function()end,
|
||||||
})
|
})
|
||||||
|
@ -12,6 +12,11 @@ end
|
|||||||
local TEST_CASE = assert(lunit.TEST_CASE)
|
local TEST_CASE = assert(lunit.TEST_CASE)
|
||||||
local skip = lunit.skip or function() end
|
local skip = lunit.skip or function() end
|
||||||
|
|
||||||
|
local utils = require "utils"
|
||||||
|
|
||||||
|
-- Bug. libcurl 7.56.0 does not add `Content-Type: text/plain`
|
||||||
|
local text_plain = utils.is_curl_eq(7,56,0) and 'test/plain' or 'text/plain'
|
||||||
|
|
||||||
local curl = require "lcurl"
|
local curl = require "lcurl"
|
||||||
|
|
||||||
local _ENV = TEST_CASE'add_content' do
|
local _ENV = TEST_CASE'add_content' do
|
||||||
@ -42,11 +47,11 @@ function test_01()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_02()
|
function test_02()
|
||||||
assert_equal(post, post:add_content('name02', 'value02', "text/plain"))
|
assert_equal(post, post:add_content('name02', 'value02', text_plain))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue02\r\n", data)
|
assert_match("\r\n\r\nvalue02\r\n", data)
|
||||||
assert_match('name="name02"', data)
|
assert_match('name="name02"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_03()
|
function test_03()
|
||||||
@ -58,12 +63,12 @@ function test_03()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_04()
|
function test_04()
|
||||||
assert_equal(post, post:add_content('name04', 'value04', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('name04', 'value04', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue04\r\n", data)
|
assert_match("\r\n\r\nvalue04\r\n", data)
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_error()
|
function test_error()
|
||||||
@ -97,12 +102,12 @@ function test_01()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_02()
|
function test_02()
|
||||||
assert_equal(post, post:add_buffer('name02', 'file02', 'value02', "text/plain"))
|
assert_equal(post, post:add_buffer('name02', 'file02', 'value02', text_plain))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue02\r\n", data)
|
assert_match("\r\n\r\nvalue02\r\n", data)
|
||||||
assert_match('name="name02"', data)
|
assert_match('name="name02"', data)
|
||||||
assert_match('filename="file02"', data)
|
assert_match('filename="file02"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -117,12 +122,12 @@ function test_03()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_04()
|
function test_04()
|
||||||
assert_equal(post, post:add_buffer('name04', 'file04', 'value04', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_buffer('name04', 'file04', 'value04', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match("\r\n\r\nvalue04\r\n", data)
|
assert_match("\r\n\r\nvalue04\r\n", data)
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('filename="file04"', data)
|
assert_match('filename="file04"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
@ -180,19 +185,19 @@ function test_02()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_03()
|
function test_03()
|
||||||
assert_equal(post, post:add_stream('name03', 'file03', 'text/plain', stream()))
|
assert_equal(post, post:add_stream('name03', 'file03', text_plain, stream()))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match('name="name03"', data)
|
assert_match('name="name03"', data)
|
||||||
assert_match('filename="file03"', data)
|
assert_match('filename="file03"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_04()
|
function test_04()
|
||||||
assert_equal(post, post:add_stream('name04', 'file04', 'text/plain', {"Content-Encoding: gzip"}, stream()))
|
assert_equal(post, post:add_stream('name04', 'file04', text_plain, {"Content-Encoding: gzip"}, stream()))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
assert_match('name="name04"', data)
|
assert_match('name="name04"', data)
|
||||||
assert_match('filename="file04"', data)
|
assert_match('filename="file04"', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -290,21 +295,21 @@ function test_01()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_02()
|
function test_02()
|
||||||
assert_equal(post, post:add_file('nameXX', form_path, 'text/plain'))
|
assert_equal(post, post:add_file('nameXX', form_path, text_plain))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
check_form(data)
|
check_form(data)
|
||||||
assert_match('filename="' .. form_file .. '"', data)
|
assert_match('filename="' .. form_file .. '"', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_03()
|
function test_03()
|
||||||
assert_equal(post, post:add_file('nameXX', form_path, 'text/plain', 'renamedfile'))
|
assert_equal(post, post:add_file('nameXX', form_path, text_plain, 'renamedfile'))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
check_form(data)
|
check_form(data)
|
||||||
assert_match('filename="' .. 'renamedfile' .. '"', data)
|
assert_match('filename="' .. 'renamedfile' .. '"', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_04()
|
function test_04()
|
||||||
@ -316,22 +321,22 @@ function test_04()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function test_05()
|
function test_05()
|
||||||
assert_equal(post, post:add_file('nameXX', form_path, 'text/plain', 'renamedfile', {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_file('nameXX', form_path, text_plain, 'renamedfile', {"Content-Encoding: gzip"}))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
check_form(data)
|
check_form(data)
|
||||||
assert_match('filename="' .. 'renamedfile' .. '"', data)
|
assert_match('filename="' .. 'renamedfile' .. '"', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_05()
|
function test_05()
|
||||||
assert_equal(post, post:add_file('nameXX', form_path, 'text/plain', {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_file('nameXX', form_path, text_plain, {"Content-Encoding: gzip"}))
|
||||||
local data = assert_string(post:get())
|
local data = assert_string(post:get())
|
||||||
check_form(data)
|
check_form(data)
|
||||||
assert_match('filename="' .. form_file .. '"', data)
|
assert_match('filename="' .. form_file .. '"', data)
|
||||||
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
assert_not_match('Content%-Type: application/octet%-stream\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -364,7 +369,7 @@ end
|
|||||||
|
|
||||||
function test_error()
|
function test_error()
|
||||||
assert_error(function()
|
assert_error(function()
|
||||||
assert_equal(post, post:add_file('nameXX', 'text/plain', form_path))
|
assert_equal(post, post:add_file('nameXX', text_plain, form_path))
|
||||||
post:get()
|
post:get()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -388,7 +393,7 @@ local function check_form(data)
|
|||||||
assert_match("\r\n\r\nvalueXX\r\n", data)
|
assert_match("\r\n\r\nvalueXX\r\n", data)
|
||||||
assert_match('name="nameXX"', data)
|
assert_match('name="nameXX"', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_writer_01()
|
function test_writer_01()
|
||||||
@ -397,7 +402,7 @@ function test_writer_01()
|
|||||||
assert_equal(0, select("#", ...))
|
assert_equal(0, select("#", ...))
|
||||||
t[#t+1] = str
|
t[#t+1] = str
|
||||||
end
|
end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
assert_equal(post, post:get(writer))
|
assert_equal(post, post:get(writer))
|
||||||
check_form(table.concat(t))
|
check_form(table.concat(t))
|
||||||
end
|
end
|
||||||
@ -409,7 +414,7 @@ function test_writer_02()
|
|||||||
t[#t+1] = str
|
t[#t+1] = str
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
assert_equal(post, post:get(writer))
|
assert_equal(post, post:get(writer))
|
||||||
check_form(table.concat(t))
|
check_form(table.concat(t))
|
||||||
end
|
end
|
||||||
@ -421,7 +426,7 @@ function test_writer_03()
|
|||||||
t[#t+1] = str
|
t[#t+1] = str
|
||||||
return #str
|
return #str
|
||||||
end
|
end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
assert_equal(post, post:get(writer))
|
assert_equal(post, post:get(writer))
|
||||||
check_form(table.concat(t))
|
check_form(table.concat(t))
|
||||||
end
|
end
|
||||||
@ -433,40 +438,40 @@ function test_writer_context()
|
|||||||
assert_equal(0, select("#", ...))
|
assert_equal(0, select("#", ...))
|
||||||
T[#T+1] = str
|
T[#T+1] = str
|
||||||
end
|
end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
assert_equal(post, post:get(writer, t))
|
assert_equal(post, post:get(writer, t))
|
||||||
local data = table.concat(t)
|
local data = table.concat(t)
|
||||||
assert_match("\r\n\r\nvalueXX\r\n", data)
|
assert_match("\r\n\r\nvalueXX\r\n", data)
|
||||||
assert_match('name="nameXX"', data)
|
assert_match('name="nameXX"', data)
|
||||||
assert_match('Content%-Encoding: gzip\r\n', data)
|
assert_match('Content%-Encoding: gzip\r\n', data)
|
||||||
assert_match('Content%-Type: text/plain\r\n', data)
|
assert_match('Content%-Type: ' .. text_plain .. '\r\n', data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_abort_01()
|
function test_abort_01()
|
||||||
local err = {}
|
local err = {}
|
||||||
local function writer() return nil, err end
|
local function writer() return nil, err end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local _, e = assert_nil(post:get(writer))
|
local _, e = assert_nil(post:get(writer))
|
||||||
assert_equal(err, e)
|
assert_equal(err, e)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_abort_02()
|
function test_abort_02()
|
||||||
local function writer() return 0 end
|
local function writer() return 0 end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local _, e = assert_nil(post:get(writer))
|
local _, e = assert_nil(post:get(writer))
|
||||||
assert_nil(e)
|
assert_nil(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_abort_03()
|
function test_abort_03()
|
||||||
local function writer() return nil end
|
local function writer() return nil end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local _, e = assert_nil(post:get(writer))
|
local _, e = assert_nil(post:get(writer))
|
||||||
assert_nil(e)
|
assert_nil(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_abort_04()
|
function test_abort_04()
|
||||||
local function writer() return false end
|
local function writer() return false end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
local _, e = assert_nil(post:get(writer))
|
local _, e = assert_nil(post:get(writer))
|
||||||
assert_nil(e)
|
assert_nil(e)
|
||||||
end
|
end
|
||||||
@ -474,7 +479,7 @@ end
|
|||||||
function test_error()
|
function test_error()
|
||||||
local err = {}
|
local err = {}
|
||||||
local function writer() error("WRITEERROR") end
|
local function writer() error("WRITEERROR") end
|
||||||
assert_equal(post, post:add_content('nameXX', 'valueXX', "text/plain", {"Content-Encoding: gzip"}))
|
assert_equal(post, post:add_content('nameXX', 'valueXX', text_plain, {"Content-Encoding: gzip"}))
|
||||||
assert_error_match("WRITEERROR", function()
|
assert_error_match("WRITEERROR", function()
|
||||||
post:get(writer)
|
post:get(writer)
|
||||||
end)
|
end)
|
||||||
|
481
test/test_mime.lua
Normal file
481
test/test_mime.lua
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
local lunit, RUN = lunit do
|
||||||
|
RUN = lunit and function()end or function ()
|
||||||
|
local res = lunit.run()
|
||||||
|
if res.errors + res.failed > 0 then
|
||||||
|
os.exit(-1)
|
||||||
|
end
|
||||||
|
return os.exit(0)
|
||||||
|
end
|
||||||
|
lunit = require "lunit"
|
||||||
|
end
|
||||||
|
|
||||||
|
local TEST_CASE = assert(lunit.TEST_CASE)
|
||||||
|
local skip = lunit.skip or function() end
|
||||||
|
|
||||||
|
local curl = require "lcurl"
|
||||||
|
local utils = require "utils"
|
||||||
|
|
||||||
|
local weak_ptr, gc_collect, dump_mime_ = utils.import('weak_ptr', 'gc_collect', 'dump_mime')
|
||||||
|
|
||||||
|
local GET_URL = 'http://127.0.0.1:7090/get'
|
||||||
|
|
||||||
|
local function is_freed(c)
|
||||||
|
return not not string.find(tostring(c), '%(freed%)')
|
||||||
|
end
|
||||||
|
|
||||||
|
local _ENV = TEST_CASE'mime lifetime' if not curl.OPT_MIMEPOST then
|
||||||
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
||||||
|
else
|
||||||
|
|
||||||
|
local easy, mime
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
easy = curl.easy()
|
||||||
|
end
|
||||||
|
|
||||||
|
function teardown()
|
||||||
|
if easy then easy:close() end
|
||||||
|
if mime then mime:free() end
|
||||||
|
easy, mime = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_preserve_mime_part_reference()
|
||||||
|
-- mime part stores references to all parts
|
||||||
|
|
||||||
|
local mime, part = easy:mime() do
|
||||||
|
part = weak_ptr(mime:addpart())
|
||||||
|
end
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_not_nil(part.value)
|
||||||
|
|
||||||
|
mime = nil
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_nil(part.value)
|
||||||
|
|
||||||
|
easy:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_free_mime_subparts()
|
||||||
|
-- when free root free all nodes
|
||||||
|
|
||||||
|
-- mime
|
||||||
|
-- +- part3
|
||||||
|
-- +- alt
|
||||||
|
-- +- part1
|
||||||
|
-- +- part2
|
||||||
|
|
||||||
|
local mime, a, p1, p2, p3 = easy:mime() do
|
||||||
|
|
||||||
|
local alt = easy:mime()
|
||||||
|
|
||||||
|
local part1 = alt:addpart()
|
||||||
|
|
||||||
|
local part2 = alt:addpart()
|
||||||
|
|
||||||
|
local part3 = mime:addpart()
|
||||||
|
part3:subparts(alt, "multipart/alternative")
|
||||||
|
|
||||||
|
a = weak_ptr(alt)
|
||||||
|
p1 = weak_ptr(part1)
|
||||||
|
p2 = weak_ptr(part2)
|
||||||
|
p3 = weak_ptr(part3)
|
||||||
|
end
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_not_nil(a.value)
|
||||||
|
assert_not_nil(p1.value)
|
||||||
|
assert_not_nil(p2.value)
|
||||||
|
assert_not_nil(p3.value)
|
||||||
|
|
||||||
|
-- reamove reference to root node
|
||||||
|
mime = nil
|
||||||
|
gc_collect(4)
|
||||||
|
|
||||||
|
assert_nil(a.value)
|
||||||
|
assert_nil(p1.value)
|
||||||
|
assert_nil(p2.value)
|
||||||
|
assert_nil(p3.value)
|
||||||
|
|
||||||
|
easy:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_preserve_mime_subparts()
|
||||||
|
-- if we have references to subnode but we free root
|
||||||
|
-- then all references have to become to invalid
|
||||||
|
|
||||||
|
-- mime
|
||||||
|
-- +- part3
|
||||||
|
-- +- alt
|
||||||
|
-- +- part1
|
||||||
|
-- +- part2
|
||||||
|
|
||||||
|
local easy = curl.easy()
|
||||||
|
|
||||||
|
local mime, a, p1, p2, p3 = easy:mime() do
|
||||||
|
|
||||||
|
local alt = easy:mime()
|
||||||
|
|
||||||
|
local part1 = alt:addpart()
|
||||||
|
|
||||||
|
local part2 = alt:addpart()
|
||||||
|
|
||||||
|
local part3 = mime:addpart()
|
||||||
|
part3:subparts(alt, "multipart/alternative")
|
||||||
|
|
||||||
|
a = weak_ptr(alt)
|
||||||
|
p1 = weak_ptr(part1)
|
||||||
|
p2 = weak_ptr(part2)
|
||||||
|
p3 = weak_ptr(part3)
|
||||||
|
end
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_not_nil(a.value)
|
||||||
|
assert_not_nil(p1.value)
|
||||||
|
assert_not_nil(p2.value)
|
||||||
|
assert_not_nil(p3.value)
|
||||||
|
|
||||||
|
-- save reference to subnode
|
||||||
|
local subnode = a.value
|
||||||
|
|
||||||
|
mime = nil
|
||||||
|
|
||||||
|
-- in this case call `free` to root node.
|
||||||
|
-- there no way to get reference to this node from child
|
||||||
|
-- so there no way to use it.
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
-- libcurl still close all childs
|
||||||
|
-- so all reference are invalid
|
||||||
|
|
||||||
|
assert_not_nil(a.value)
|
||||||
|
assert_not_nil(is_freed(a.value))
|
||||||
|
assert_nil(p1.value)
|
||||||
|
assert_nil(p2.value)
|
||||||
|
assert_nil(p3.value)
|
||||||
|
|
||||||
|
easy:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_preserve_mime_by_easy()
|
||||||
|
|
||||||
|
local mime do
|
||||||
|
mime = weak_ptr(easy:mime())
|
||||||
|
easy:setopt_mimepost(mime.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_not_nil(mime.value)
|
||||||
|
|
||||||
|
easy:unsetopt_mimepost()
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_nil(mime.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_mime_does_not_ref_to_easy()
|
||||||
|
-- exists of mime object does not prevent easy from GC
|
||||||
|
|
||||||
|
local mime = easy:mime()
|
||||||
|
local peasy = weak_ptr(easy)
|
||||||
|
easy = nil
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_nil(peasy.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_mimepost_does_not_ref_to_easy()
|
||||||
|
-- exists of mime object does not prevent easy from GC
|
||||||
|
|
||||||
|
-- create mime and set it as mimepost option
|
||||||
|
local mime = easy:mime()
|
||||||
|
easy:setopt_mimepost(mime)
|
||||||
|
|
||||||
|
local peasy = weak_ptr(easy)
|
||||||
|
easy = nil
|
||||||
|
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
assert_nil(peasy.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local _ENV = TEST_CASE'mime basic' if not curl.OPT_MIMEPOST then
|
||||||
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
||||||
|
else
|
||||||
|
|
||||||
|
local easy, mime
|
||||||
|
|
||||||
|
local function dump_mime(mime)
|
||||||
|
return dump_mime_(easy, mime, GET_URL)
|
||||||
|
end
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
easy = curl.easy()
|
||||||
|
mime = easy:mime()
|
||||||
|
end
|
||||||
|
|
||||||
|
function teardown()
|
||||||
|
if easy then easy:close() end
|
||||||
|
if mime then mime:free() end
|
||||||
|
easy, mime = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data()
|
||||||
|
mime:addpart():data('hello')
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_type()
|
||||||
|
mime:addpart():data('hello', 'test/html')
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_type_name()
|
||||||
|
mime:addpart():data('hello', 'test/html', 'test')
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_name()
|
||||||
|
mime:addpart():data('hello', nil, 'test')
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_filename()
|
||||||
|
mime:addpart():data('hello', nil, nil, 'test.html')
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Disposition:.-%sfilename="test%.html"', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_should_not_unset_on_nil()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
})
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
|
||||||
|
part:data('world', nil, 'test2')
|
||||||
|
info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nworld', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
|
||||||
|
part:data('!!!!!', 'text/xml', nil)
|
||||||
|
info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\n!!!!!', info)
|
||||||
|
assert_match('Content%-Type:%s+text/xml', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
|
||||||
|
part:data('!!!!!!!', 'text/xml', nil, nil)
|
||||||
|
info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\n!!!!!', info)
|
||||||
|
assert_match('Content%-Type:%s+text/xml', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_data_headers()
|
||||||
|
mime:addpart():data('hello', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
})
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_name()
|
||||||
|
mime:addpart():data('hello', 'test/html', 'test'):name(false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_type()
|
||||||
|
mime:addpart():data('hello', 'test/html'):type(false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_not_match('Content%-Type:%s+test/html', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_headers()
|
||||||
|
mime:addpart():data('hello', 'test/html',{
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):headers(false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data()
|
||||||
|
mime:addpart():data('hello', 'test/html', 'test'):data(false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_not_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_type_1()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_not_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_type_2()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', false, nil, nil)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_not_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_name_1()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', nil, false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_name_2()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', nil, false, nil)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_header()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', nil, nil, nil, false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-name="test"', info)
|
||||||
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_unset_data_filename_1()
|
||||||
|
local part = mime:addpart():data('hello', 'test/html', 'test', 'test.html', {
|
||||||
|
'X-Custom-Header: hello'
|
||||||
|
}):data('hello', nil, nil, false)
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\nhello', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
||||||
|
assert_not_match('Content%-Disposition:.-%sname="test%.html"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_fail_pass_nil_as_first_arg()
|
||||||
|
local part = mime:addpart()
|
||||||
|
assert_error(function() part:data() end)
|
||||||
|
assert_error(function() part:data(nil) end)
|
||||||
|
|
||||||
|
assert_error(function() part:name() end)
|
||||||
|
assert_error(function() part:name(nil) end)
|
||||||
|
|
||||||
|
assert_error(function() part:type() end)
|
||||||
|
assert_error(function() part:type(nil) end)
|
||||||
|
|
||||||
|
assert_error(function() part:headers() end)
|
||||||
|
assert_error(function() part:headers(nil) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local _ENV = TEST_CASE'mime addpart' if not curl.OPT_MIMEPOST then
|
||||||
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
||||||
|
else
|
||||||
|
|
||||||
|
local easy, mime
|
||||||
|
|
||||||
|
local function dump_mime(mime)
|
||||||
|
return dump_mime_(easy, mime, GET_URL)
|
||||||
|
end
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
easy = curl.easy()
|
||||||
|
mime = easy:mime()
|
||||||
|
end
|
||||||
|
|
||||||
|
function teardown()
|
||||||
|
if easy then easy:close() end
|
||||||
|
if mime then mime:free() end
|
||||||
|
easy, mime = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_empty_table()
|
||||||
|
assert(mime:addpart{})
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_pass_args()
|
||||||
|
assert(mime:addpart{
|
||||||
|
data = 'hello';
|
||||||
|
encoder = 'base64';
|
||||||
|
name = 'test';
|
||||||
|
filename = 'test.html';
|
||||||
|
type = 'test/html';
|
||||||
|
headers = {
|
||||||
|
'X-Custom-Header: hello';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
local info = assert_string(dump_mime(mime))
|
||||||
|
assert_match('\r\n\r\naGVsbG8=', info)
|
||||||
|
assert_match('Content%-Type:%s+test/html', info)
|
||||||
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
||||||
|
assert_not_match('Content%-Disposition:.-%sname="test%.html"', info)
|
||||||
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
||||||
|
assert_match('Content%-Transfer%-Encoding:%s*base64', info)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
RUN()
|
@ -6,7 +6,8 @@ local curl = require "lcurl"
|
|||||||
local WAIT_COUNT = 15
|
local WAIT_COUNT = 15
|
||||||
|
|
||||||
local SIZE = 10 * 1024
|
local SIZE = 10 * 1024
|
||||||
local RESOURCE_URL = "http://httpbin.org/bytes/" .. SIZE
|
-- local RESOURCE_URL = "http://httpbin.org/bytes/" .. SIZE
|
||||||
|
local RESOURCE_URL = "http://127.0.0.1:7090/bytes/" .. SIZE
|
||||||
|
|
||||||
local State = {
|
local State = {
|
||||||
PAUSE = 0, -- write function should return CURL_WRITEFUNC_PAUSE
|
PAUSE = 0, -- write function should return CURL_WRITEFUNC_PAUSE
|
||||||
|
117
test/utils.lua
Normal file
117
test/utils.lua
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
local curl = require "lcurl"
|
||||||
|
|
||||||
|
local function weak_ptr(val)
|
||||||
|
return setmetatable({value = val},{__mode = 'v'})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function gc_collect()
|
||||||
|
collectgarbage("collect")
|
||||||
|
collectgarbage("collect")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function cver(min, maj, pat)
|
||||||
|
return min * 2^16 + maj * 2^8 + pat
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_curl_ge(min, maj, pat)
|
||||||
|
assert(0x070908 == cver(7,9,8))
|
||||||
|
return curl.version_info('version_num') >= cver(min, maj, pat)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_curl_eq(min, maj, pat)
|
||||||
|
assert(0x070908 == cver(7,9,8))
|
||||||
|
return curl.version_info('version_num') == cver(min, maj, pat)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function read_file(n)
|
||||||
|
local f, e = io.open(n, "r")
|
||||||
|
if not f then return nil, e end
|
||||||
|
local d, e = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
return d, e
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_bin_by(str,n)
|
||||||
|
local pos = 1 - n
|
||||||
|
return function()
|
||||||
|
pos = pos + n
|
||||||
|
return (str:sub(pos,pos+n-1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function stream(ch, n, m)
|
||||||
|
return n, get_bin_by( (ch):rep(n), m)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Stream(ch, n, m)
|
||||||
|
local size, reader
|
||||||
|
|
||||||
|
local _stream = {}
|
||||||
|
|
||||||
|
function _stream:read(...)
|
||||||
|
_stream.called_ctx = self
|
||||||
|
_stream.called_co = coroutine.running()
|
||||||
|
return reader(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _stream:size()
|
||||||
|
return size
|
||||||
|
end
|
||||||
|
|
||||||
|
function _stream:reset()
|
||||||
|
size, reader = stream(ch, n, m)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return _stream:reset()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function easy_dump_mime(easy, mime, url)
|
||||||
|
local buffer = {}
|
||||||
|
|
||||||
|
local function dump_mime(type, data)
|
||||||
|
if type == curl.INFO_DATA_OUT then
|
||||||
|
buffer[#buffer + 1] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = easy:setopt{
|
||||||
|
url = url or "http://127.0.0.1:7090";
|
||||||
|
customrequest = "GET";
|
||||||
|
mimepost = mime;
|
||||||
|
verbose = true;
|
||||||
|
debugfunction = dump_mime;
|
||||||
|
writefunction = function()end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
ok, err = easy:perform()
|
||||||
|
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
return table.concat(buffer)
|
||||||
|
end
|
||||||
|
|
||||||
|
local utils = {
|
||||||
|
weak_ptr = weak_ptr;
|
||||||
|
gc_collect = gc_collect;
|
||||||
|
is_curl_ge = is_curl_ge;
|
||||||
|
is_curl_eq = is_curl_eq;
|
||||||
|
get_bin_by = get_bin_by;
|
||||||
|
read_file = read_file;
|
||||||
|
dump_mime = easy_dump_mime;
|
||||||
|
stream = stream;
|
||||||
|
Stream = Stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.import = function(...)
|
||||||
|
local n, t = select('#', ...), {}
|
||||||
|
for i = 1, n do
|
||||||
|
local name = select(i, ...)
|
||||||
|
t[#t + 1] = assert(utils[name], 'unknown field: ' .. tostring(name))
|
||||||
|
end
|
||||||
|
return (unpack or table.unpack)(t, 1, n)
|
||||||
|
end
|
||||||
|
|
||||||
|
return utils
|
Loading…
x
Reference in New Issue
Block a user