Add. cURL urlapi support
parent
315a2d8683
commit
099f748bbb
1
lakefile
1
lakefile
|
@ -35,6 +35,7 @@ target('test', install, function()
|
|||
run_test('test_mime.lua')
|
||||
run_test('test_multi_callback.lua')
|
||||
run_test('test_multi_nested_callback.lua')
|
||||
run_test('test_urlapi.lua')
|
||||
|
||||
if not test_summary() then
|
||||
quit("test fail")
|
||||
|
|
|
@ -61,9 +61,10 @@ build = {
|
|||
|
||||
lcurl = {
|
||||
sources = {
|
||||
"src/l52util.c", "src/lceasy.c", "src/lcerror.c",
|
||||
"src/lchttppost.c", "src/lcurl.c", "src/lcutils.c",
|
||||
"src/lcmulti.c", "src/lcshare.c","src/lcmime.c",
|
||||
"src/l52util.c", "src/lceasy.c", "src/lcerror.c",
|
||||
"src/lchttppost.c", "src/lcurl.c", "src/lcutils.c",
|
||||
"src/lcmulti.c", "src/lcshare.c", "src/lcmime.c",
|
||||
"src/lcurlapi.c",
|
||||
},
|
||||
incdirs = { "$(CURL_INCDIR)" },
|
||||
libdirs = { "$(CURL_LIBDIR)" }
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
ENTRY_PART(fragment, UPART_FRAGMENT , CURLUE_NO_FRAGMENT )
|
||||
ENTRY_PART(host, UPART_HOST , CURLUE_NO_HOST )
|
||||
ENTRY_PART(options, UPART_OPTIONS , CURLUE_NO_OPTIONS )
|
||||
ENTRY_PART(password, UPART_PASSWORD , CURLUE_NO_PASSWORD )
|
||||
ENTRY_PART(path, UPART_PATH , CURLUE_OK )
|
||||
ENTRY_PART(port, UPART_PORT , CURLUE_NO_PORT )
|
||||
ENTRY_PART(query, UPART_QUERY , CURLUE_NO_QUERY )
|
||||
ENTRY_PART(scheme, UPART_SCHEME , CURLUE_NO_SCHEME )
|
||||
ENTRY_PART(url, UPART_URL , CURLUE_OK )
|
||||
ENTRY_PART(user, UPART_USER , CURLUE_NO_USER )
|
||||
|
||||
ENTRY_FLAG(DEFAULT_PORT )
|
||||
ENTRY_FLAG(NO_DEFAULT_PORT )
|
||||
ENTRY_FLAG(DEFAULT_SCHEME )
|
||||
ENTRY_FLAG(NON_SUPPORT_SCHEME )
|
||||
ENTRY_FLAG(PATH_AS_IS )
|
||||
ENTRY_FLAG(DISALLOW_USER )
|
||||
ENTRY_FLAG(URLDECODE )
|
||||
ENTRY_FLAG(URLENCODE )
|
||||
ENTRY_FLAG(APPENDQUERY )
|
||||
ENTRY_FLAG(GUESS_SCHEME )
|
14
src/lcurl.c
14
src/lcurl.c
|
@ -15,6 +15,7 @@
|
|||
#include "lcerror.h"
|
||||
#include "lchttppost.h"
|
||||
#include "lcmime.h"
|
||||
#include "lcurlapi.h"
|
||||
#include "lcutils.h"
|
||||
|
||||
/*export*/
|
||||
|
@ -36,10 +37,14 @@ static int lcurl_share_new_safe(lua_State *L){
|
|||
return lcurl_share_create(L, LCURL_ERROR_RETURN);
|
||||
}
|
||||
|
||||
static int lcurl_hpost_new_safe(lua_State *L){
|
||||
static int lcurl_hpost_new_safe(lua_State *L) {
|
||||
return lcurl_hpost_create(L, LCURL_ERROR_RETURN);
|
||||
}
|
||||
|
||||
static int lcurl_url_new_safe(lua_State *L) {
|
||||
return lcurl_url_create(L, LCURL_ERROR_RETURN);
|
||||
}
|
||||
|
||||
static int lcurl_easy_new(lua_State *L){
|
||||
return lcurl_easy_create(L, LCURL_ERROR_RAISE);
|
||||
}
|
||||
|
@ -56,6 +61,10 @@ static int lcurl_hpost_new(lua_State *L){
|
|||
return lcurl_hpost_create(L, LCURL_ERROR_RAISE);
|
||||
}
|
||||
|
||||
static int lcurl_url_new(lua_State *L) {
|
||||
return lcurl_url_create(L, LCURL_ERROR_RAISE);
|
||||
}
|
||||
|
||||
static int lcurl_version(lua_State *L){
|
||||
lua_pushstring(L, curl_version());
|
||||
return 1;
|
||||
|
@ -170,6 +179,7 @@ static const struct luaL_Reg lcurl_functions[] = {
|
|||
{"easy", lcurl_easy_new },
|
||||
{"multi", lcurl_multi_new },
|
||||
{"share", lcurl_share_new },
|
||||
{"url", lcurl_url_new },
|
||||
{"version", lcurl_version },
|
||||
{"version_info", lcurl_version_info },
|
||||
|
||||
|
@ -182,6 +192,7 @@ static const struct luaL_Reg lcurl_functions_safe[] = {
|
|||
{"easy", lcurl_easy_new_safe },
|
||||
{"multi", lcurl_multi_new_safe },
|
||||
{"share", lcurl_share_new_safe },
|
||||
{"url", lcurl_url_new_safe },
|
||||
{"version", lcurl_version },
|
||||
{"version_info", lcurl_version_info },
|
||||
|
||||
|
@ -258,6 +269,7 @@ static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
|
|||
LCURL_PUSH_NUP(L); lcurl_mime_initlib (L, NUP);
|
||||
LCURL_PUSH_NUP(L); lcurl_multi_initlib(L, NUP);
|
||||
LCURL_PUSH_NUP(L); lcurl_share_initlib(L, NUP);
|
||||
LCURL_PUSH_NUP(L); lcurl_url_initlib (L, NUP);
|
||||
|
||||
LCURL_PUSH_NUP(L);
|
||||
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/******************************************************************************
|
||||
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||
*
|
||||
* Copyright (C) 2018 Alexey Melnichuk <mimir@newmail.ru>
|
||||
*
|
||||
* Licensed according to the included 'LICENSE' document
|
||||
*
|
||||
* This file is part of lua-lcurl library.
|
||||
******************************************************************************/
|
||||
|
||||
#include "lcurlapi.h"
|
||||
#include "lcurl.h"
|
||||
#include "lcerror.h"
|
||||
#include "lcutils.h"
|
||||
#include <memory.h>
|
||||
|
||||
#define LCURL_URL_NAME LCURL_PREFIX" URL"
|
||||
static const char *LCURL_URL = LCURL_URL_NAME;
|
||||
|
||||
#if LCURL_CURL_VER_GE(7,62,0)
|
||||
|
||||
#define lcurl_geturl(L) lcurl_geturl_at(L, 1)
|
||||
|
||||
typedef struct lcurl_url_tag{
|
||||
CURLU *url;
|
||||
|
||||
int storage;
|
||||
int err_mode;
|
||||
}lcurl_url_t;
|
||||
|
||||
int lcurl_url_create(lua_State *L, int error_mode){
|
||||
lcurl_url_t *p;
|
||||
|
||||
p = lutil_newudatap(L, lcurl_url_t, LCURL_URL);
|
||||
|
||||
p->url = curl_url();
|
||||
if(!p->url) return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_URL, CURLUE_OUT_OF_MEMORY);
|
||||
|
||||
p->err_mode = error_mode;
|
||||
|
||||
if (lua_gettop(L) > 1) {
|
||||
const char *url = luaL_checkstring(L, 1);
|
||||
unsigned int flags = 0;
|
||||
CURLUcode code;
|
||||
|
||||
if (lua_gettop(L) > 2) {
|
||||
flags = (unsigned int)lutil_optint64(L, 2, 0);
|
||||
}
|
||||
|
||||
code = curl_url_set(p->url, CURLUPART_URL, url, flags);
|
||||
if (code != CURLUE_OK) {
|
||||
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_URL, code);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static lcurl_url_t *lcurl_geturl_at(lua_State *L, int i){
|
||||
lcurl_url_t *p = (lcurl_url_t *)lutil_checkudatap (L, i, LCURL_URL);
|
||||
luaL_argcheck (L, p != NULL, 1, LCURL_URL_NAME" object expected");
|
||||
return p;
|
||||
}
|
||||
|
||||
static int lcurl_url_cleanup(lua_State *L){
|
||||
lcurl_url_t *p = lcurl_geturl(L);
|
||||
|
||||
if (p->url){
|
||||
curl_url_cleanup(p->url);
|
||||
p->url = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcurl_url_dup(lua_State *L) {
|
||||
lcurl_url_t *r = lcurl_geturl(L);
|
||||
lcurl_url_t *p = lutil_newudatap(L, lcurl_url_t, LCURL_URL);
|
||||
|
||||
p->url = curl_url_dup(r->url);
|
||||
if (!p->url) return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_URL, CURLUE_OUT_OF_MEMORY);
|
||||
|
||||
p->err_mode = r->err_mode;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lcurl_url_set(lua_State *L, CURLUPart what){
|
||||
lcurl_url_t *p = lcurl_geturl(L);
|
||||
CURLUcode code;
|
||||
const char *part;
|
||||
unsigned int flags = 0;
|
||||
|
||||
luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING || lutil_is_null(L, 2), 2, "string expected");
|
||||
|
||||
part = lua_tostring(L, 2);
|
||||
flags = (unsigned int)lutil_optint64(L, 3, 0);
|
||||
|
||||
code = curl_url_set(p->url, what, part, flags);
|
||||
if (code != CURLUE_OK) {
|
||||
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_URL, code);
|
||||
}
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lcurl_url_get(lua_State *L, CURLUPart what, CURLUcode empty) {
|
||||
lcurl_url_t *p = lcurl_geturl(L);
|
||||
CURLUcode code;
|
||||
char *part = NULL;
|
||||
unsigned int flags = 0;
|
||||
|
||||
flags = (unsigned int)lutil_optint64(L, 2, 0);
|
||||
|
||||
code = curl_url_get(p->url, what, &part, flags);
|
||||
if (code != CURLUE_OK) {
|
||||
if (part) {
|
||||
curl_free(part);
|
||||
part = NULL;
|
||||
}
|
||||
|
||||
if (code != empty) {
|
||||
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_URL, code);
|
||||
}
|
||||
}
|
||||
|
||||
if (part == NULL) {
|
||||
lutil_push_null(L);
|
||||
}
|
||||
else {
|
||||
lua_pushstring(L, part);
|
||||
curl_free(part);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ENTRY_PART(N, S, E) static int lcurl_url_set_##N(lua_State *L){\
|
||||
return lcurl_url_set(L, CURL##S);\
|
||||
}
|
||||
#define ENTRY_FLAG(S)
|
||||
|
||||
#include "lcopturl.h"
|
||||
|
||||
#undef ENTRY_PART
|
||||
#undef ENTRY_FLAG
|
||||
|
||||
#define ENTRY_PART(N, S, E) static int lcurl_url_get_##N(lua_State *L){\
|
||||
return lcurl_url_get(L, CURL##S, E);\
|
||||
}
|
||||
#define ENTRY_FLAG(S)
|
||||
|
||||
#include "lcopturl.h"
|
||||
|
||||
#undef ENTRY_PART
|
||||
#undef ENTRY_FLAG
|
||||
|
||||
static const struct luaL_Reg lcurl_url_methods[] = {
|
||||
#define ENTRY_PART(N, S, E) { "set_"#N, lcurl_url_set_##N },
|
||||
#define ENTRY_FLAG(S)
|
||||
#include "lcopturl.h"
|
||||
#undef ENTRY_PART
|
||||
#undef ENTRY_FLAG
|
||||
|
||||
#define ENTRY_PART(N, S, E) { "get_"#N, lcurl_url_get_##N },
|
||||
#define ENTRY_FLAG(S)
|
||||
#include "lcopturl.h"
|
||||
#undef ENTRY_PART
|
||||
#undef ENTRY_FLAG
|
||||
|
||||
{ "dup", lcurl_url_dup },
|
||||
{ "cleanup", lcurl_url_cleanup },
|
||||
{ "__gc", lcurl_url_cleanup },
|
||||
{ "__tostring", lcurl_url_get_url },
|
||||
|
||||
{ NULL,NULL }
|
||||
};
|
||||
|
||||
static const lcurl_const_t lcurl_url_opt[] = {
|
||||
#define ENTRY_PART(N, S, E) { #S, CURL##S },
|
||||
#define ENTRY_FLAG(S) { "U_"#S, CURLU_##S },
|
||||
#include "lcopturl.h"
|
||||
#undef ENTRY_PART
|
||||
#undef ENTRY_FLAG
|
||||
{NULL, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
void lcurl_url_initlib(lua_State *L, int nup){
|
||||
#if LCURL_CURL_VER_GE(7,62,0)
|
||||
if(!lutil_createmetap(L, LCURL_URL, lcurl_url_methods, nup))
|
||||
lua_pop(L, nup);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lcurl_util_set_const(L, lcurl_url_opt);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/******************************************************************************
|
||||
* Author: Alexey Melnichuk <mimir@newmail.ru>
|
||||
*
|
||||
* Copyright (C) 2018 Alexey Melnichuk <mimir@newmail.ru>
|
||||
*
|
||||
* Licensed according to the included 'LICENSE' document
|
||||
*
|
||||
* This file is part of lua-lcurl library.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _LURL_H_
|
||||
#define _LURL_H_
|
||||
|
||||
#include "lcurl.h"
|
||||
#include "lcutils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void lcurl_url_initlib(lua_State *L, int nup);
|
||||
|
||||
int lcurl_url_create(lua_State *L, int error_mode);
|
||||
|
||||
#endif
|
|
@ -29,5 +29,6 @@ require "test_easy"
|
|||
require "test_form"
|
||||
require "test_mime"
|
||||
require "test_curl"
|
||||
require "test_urlapi"
|
||||
|
||||
RUN()
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
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 _, luacov = pcall(require, "luacov")
|
||||
local TEST_CASE = assert(lunit.TEST_CASE)
|
||||
local skip = lunit.skip or function() end
|
||||
local curl = require "cURL"
|
||||
local scurl = require "cURL.safe"
|
||||
local utils = require "utils"
|
||||
|
||||
local tostring = tostring
|
||||
|
||||
local ENABLE = true
|
||||
|
||||
local _ENV = TEST_CASE'urlapi' if ENABLE then
|
||||
|
||||
if not curl.E_URL_OK then skip('URL API avaliable since libcurl 7.62.0') else
|
||||
|
||||
local it = setmetatable(_ENV or _M, {__call = function(self, describe, fn)
|
||||
self["test " .. describe] = fn
|
||||
end})
|
||||
|
||||
local url
|
||||
|
||||
local function U(u)
|
||||
url = assert_userdata(curl.url())
|
||||
assert_equal(url, url:set_url(u))
|
||||
return url
|
||||
end
|
||||
|
||||
function teardown()
|
||||
if url then url:cleanup() end
|
||||
url = nil
|
||||
end
|
||||
|
||||
it('should export falgs', function()
|
||||
assert_number(curl.U_DEFAULT_PORT )
|
||||
assert_number(curl.U_NO_DEFAULT_PORT )
|
||||
assert_number(curl.U_DEFAULT_SCHEME )
|
||||
assert_number(curl.U_NON_SUPPORT_SCHEME )
|
||||
assert_number(curl.U_PATH_AS_IS )
|
||||
assert_number(curl.U_DISALLOW_USER )
|
||||
assert_number(curl.U_URLDECODE )
|
||||
assert_number(curl.U_URLENCODE )
|
||||
assert_number(curl.U_APPENDQUERY )
|
||||
assert_number(curl.U_GUESS_SCHEME )
|
||||
end)
|
||||
|
||||
it('should export parts', function()
|
||||
assert_number(curl.UPART_URL )
|
||||
assert_number(curl.UPART_SCHEME )
|
||||
assert_number(curl.UPART_USER )
|
||||
assert_number(curl.UPART_PASSWORD )
|
||||
assert_number(curl.UPART_OPTIONS )
|
||||
assert_number(curl.UPART_HOST )
|
||||
assert_number(curl.UPART_PORT )
|
||||
assert_number(curl.UPART_PATH )
|
||||
assert_number(curl.UPART_QUERY )
|
||||
assert_number(curl.UPART_FRAGMENT )
|
||||
end)
|
||||
|
||||
it('should export methods', function()
|
||||
url = curl.url()
|
||||
assert_function(url.dup )
|
||||
assert_function(url.cleanup )
|
||||
|
||||
assert_function(url.set_url )
|
||||
assert_function(url.set_scheme )
|
||||
assert_function(url.set_user )
|
||||
assert_function(url.set_password )
|
||||
assert_function(url.set_options )
|
||||
assert_function(url.set_host )
|
||||
assert_function(url.set_port )
|
||||
assert_function(url.set_path )
|
||||
assert_function(url.set_query )
|
||||
assert_function(url.set_fragment )
|
||||
|
||||
assert_function(url.get_url )
|
||||
assert_function(url.get_scheme )
|
||||
assert_function(url.get_user )
|
||||
assert_function(url.get_password )
|
||||
assert_function(url.get_options )
|
||||
assert_function(url.get_host )
|
||||
assert_function(url.get_port )
|
||||
assert_function(url.get_path )
|
||||
assert_function(url.get_query )
|
||||
assert_function(url.get_fragment )
|
||||
end)
|
||||
|
||||
it('create and cleanup', function()
|
||||
url = assert_userdata(curl.url())
|
||||
assert_nil(url:cleanup())
|
||||
end)
|
||||
|
||||
it('constructor with parameters', function()
|
||||
url = assert_userdata(curl.url('http://example.com/'))
|
||||
assert_equal('http://example.com/', url:get_url())
|
||||
|
||||
url = assert_userdata(curl.url('example.com', curl.U_GUESS_SCHEME))
|
||||
assert_equal('http://example.com/', url:get_url())
|
||||
end)
|
||||
|
||||
it('dup url', function()
|
||||
url = assert_userdata(curl.url('http://example.com/'))
|
||||
local u2 = url:dup()
|
||||
assert_not_equal(url, u2)
|
||||
assert_equal('http://example.com/', u2:get_url())
|
||||
assert_equal('http://example.com/', url:get_url())
|
||||
url:cleanup()
|
||||
url = u2
|
||||
assert_equal('http://example.com/', url:get_url())
|
||||
end)
|
||||
|
||||
it('should convert to string', function()
|
||||
assert_equal('http://example.com/', tostring(U"http://example.com/"))
|
||||
end)
|
||||
|
||||
it('should decode url', function()
|
||||
url = U"http://example.com"
|
||||
assert_equal('http', url:get_scheme())
|
||||
assert_equal('example.com', url:get_host())
|
||||
assert_equal('/', url:get_path())
|
||||
end)
|
||||
|
||||
it('should cast scheme to lower case', function()
|
||||
url = U"HTTP://Example.com"
|
||||
assert_equal('http', url:get_scheme())
|
||||
assert_equal('Example.com', url:get_host())
|
||||
assert_equal('/', url:get_path())
|
||||
assert_equal("http://Example.com/", url:get_url())
|
||||
end)
|
||||
|
||||
it('should append query', function()
|
||||
url = U"http://example.com"
|
||||
assert_equal(url, url:set_query("a=hello world", curl.U_APPENDQUERY + curl.U_URLENCODE))
|
||||
assert_equal(url, url:set_query("b=A&B", curl.U_APPENDQUERY + curl.U_URLENCODE))
|
||||
assert_equal("http://example.com/?a=hello+world&b=A%26B", url:get_url())
|
||||
end)
|
||||
|
||||
it('should append only one parameter in query per call', function()
|
||||
url = U"http://example.com"
|
||||
assert_equal(url, url:set_query("a=hello world&b=A&B", curl.U_APPENDQUERY + curl.U_URLENCODE))
|
||||
assert_equal("http://example.com/?a=hello+world%26b=A%26B", url:get_url())
|
||||
end)
|
||||
|
||||
it('should set encoded query', function()
|
||||
url = U("http://example.com/?a=hello world&b=d")
|
||||
assert_equal('a=hello world&b=d', url:get_query())
|
||||
end)
|
||||
|
||||
it('should returns NULL as empty value', function()
|
||||
url = curl.url()
|
||||
assert_equal(curl.null, url:get_query())
|
||||
assert_equal(curl.null, url:get_host())
|
||||
assert_equal(curl.null, url:get_port())
|
||||
assert_equal(curl.null, url:get_password())
|
||||
assert_equal(curl.null, url:get_scheme())
|
||||
assert_equal(curl.null, url:get_options())
|
||||
assert_equal(curl.null, url:get_fragment())
|
||||
|
||||
assert_equal('/', url:get_path())
|
||||
end)
|
||||
|
||||
it('should returns nil and error for invalid url in safe mode', function()
|
||||
url = scurl.url()
|
||||
local _, err = assert_nil(url:get_url())
|
||||
assert_equal('CURL-URL', err:cat())
|
||||
end)
|
||||
|
||||
it('should raise error for invalid url', function()
|
||||
url = curl.url()
|
||||
assert_error_match('CURL%-URL', function() url:get_url() end)
|
||||
end)
|
||||
|
||||
-- it('should set encoded query', function()
|
||||
-- url = U"http://example.com"
|
||||
-- assert_equal(url, url:set_query("a=hello world", curl.U_URLENCODE))
|
||||
-- assert_equal("http://example.com/?a=hello+world", url:get_url())
|
||||
-- end)
|
||||
|
||||
end end
|
||||
|
||||
RUN()
|
Loading…
Reference in New Issue