Browse Source

Extended url_dispatcher::map to:

- support of up to 8 arguments
- allow specification of booster::regex directly (for example passing flags)
master
Artyom Beilis 8 years ago
parent
commit
2769daafbf
3 changed files with 493 additions and 105 deletions
  1. +383
    -91
      cppcms/url_dispatcher.h
  2. +2
    -2
      src/url_dispatcher.cpp
  3. +108
    -12
      tests/url_mapper_test.cpp

+ 383
- 91
cppcms/url_dispatcher.h View File

@@ -122,95 +122,188 @@ namespace cppcms {
/// Map a callback \a h to a URL matching regular expression \a re and an HTTP \a method
///
/// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param h - handler to execute
///
/// \ver{v1_2}
void map_generic(std::string const &method,std::string const &re,generic_handler const &h);
void map_generic(std::string const &method,booster::regex const &re,generic_handler const &h);
///
/// Map a callback \a h to a URL matching regular expression \a re
///
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param h - handler to execute
///
/// \ver{v1_2}
void map_generic(std::string const &re,generic_handler const &h);
void map_generic(booster::regex const &re,generic_handler const &h);


#ifdef CPPCMS_DOXYGEN_DOCS

///
/// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re and HTTP method \a method
///
/// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param member - member function of application \a app
/// \param app - application that its \a member is called
/// \param groups - matched groups converted to ApplicationMemberArgs
///
/// Note:
///
/// - number of integers in \a groups should match the number of arguments of \a member
/// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
///
/// For exaample
/// \code
/// class foo : public cppcms::application {
/// ...
/// void page(int x,std::string const &name);
/// void update(int x);
/// foo(...)
/// {
/// dispatcher().map("GET","/page/(\\d+)(/(.*))?",&foo::page,this,1,3);
/// dispatcher().map("POST","/update/(\\d+)",&foo::update,this,1);
/// }
/// \endcode
///
/// When the reuqest matches the \a method and regualr expression \a re, \a member of \a app is called, For case of `page` that has two
/// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
///
/// In case of `update` - that has only 1 parameter, a single integer should be passed
///
/// In addition to calling \a member function it calls app->init() before call
/// and app->clean() after the call of the C is derived from cppcms::application
/// and app->clean() after the call if Application is derived from cppcms::application
///
///
/// \ver{v1_2}
template<typename C>
void map(std::string const &method,std::string const &re,void (C::*member)(),C *app)
{
map_generic(method,re,url_binder0<C>(member,app));
}
template<typename Application,typename... ApplicationMemberArgs>
void map(std::string const &method,std::string const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );

///
/// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re
///
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param member - member function of application \a app
/// \param app - application that its \a member is called
/// \param groups - matched groups converted to ApplicationMemberArgs
///
/// Note:
///
/// - number of integers in \a groups should match the number of arguments of \a member
/// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
///
/// For exaample
/// \code
/// class foo : public cppcms::application {
/// ...
/// void page(int x,std::string const &name);
/// void update(int x);
/// foo(...)
/// {
/// dispatcher().map("/page/(\\d+)(/(.*))?",&foo::page,this,1,3);
/// dispatcher().map("/update/(\\d+)",&foo::update,this,1);
/// }
/// \endcode
///
/// When the reuqest URL the regualr expression \a re, \a member of \a app is called, For case of `page` that has two
/// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
///
/// In case of `update` - that has only 1 parameter, a single integer should be passed
///
/// In addition to calling \a member function it calls app->init() before call
/// and app->clean() after the call of the C is derived from cppcms::application
/// and app->clean() after the call if Application is derived from cppcms::application
///
///
/// \ver{v1_2}
template<typename C>
void map(std::string const &re,void (C::*member)(),C *app)
{
map_generic(re,url_binder0<C>(member,app));
}
template<typename Application,typename... ApplicationMemberArgs>
void map(std::string const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );


///
/// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re and HTTP method \a method
///
/// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param member - member function of application \a app
/// \param app - application that its \a member is called
/// \param g1 - a matched group passed as first parameter of \a member after validation and conversion using parse_url_parameter function
/// \param groups - matched groups converted to ApplicationMemberArgs
///
/// Note:
///
/// - number of integers in \a groups should match the number of arguments of \a member
/// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
///
/// For exaample
/// \code
/// class foo : public cppcms::application {
/// ...
/// void page(int x,std::string const &name);
/// void update(int x);
/// foo(...)
/// {
/// using booster::regex;
/// dispatcher().map(regex("/page/(\\d+)(/(.*))?",regex::icase),&foo::page,this,1,3);
/// dispatcher().map("POST","/update/(\\d+)",&foo::update,this,1);
/// }
/// \endcode
///
/// When the reuqest matches the \a method and regualr expression \a re, \a member of \a app is called, For case of `page` that has two
/// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
///
/// In case of `update` - that has only 1 parameter, a single integer should be passed
///
/// In addition to calling \a member function it calls app->init() before call
/// and app->clean() after the call of the C is derived from cppcms::application
/// and app->clean() after the call if Application is derived from cppcms::application
///
///
/// \ver{v1_2}
template<typename C,typename P1>
void map(std::string const &method,std::string const &re,void (C::*member)(P1),C *app,int g1)
{
map_generic(method,re,url_binder1<C,P1>(member,app,g1));
}
template<typename Application,typename... ApplicationMemberArgs>
void map(std::string const &method,booster::regex const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );

///
/// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re and HTTP method \a method
/// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re
///
/// \param re - matched URL
/// \param re - regular expression to match the URL
/// \param member - member function of application \a app
/// \param app - application that its \a member is called
/// \param g1 - a matched group passed as first parameter of \a member after validation and conversion using parse_url_parameter function
/// \param groups - matched groups converted to ApplicationMemberArgs
///
/// Note:
///
/// - number of integers in \a groups should match the number of arguments of \a member
/// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
///
/// For exaample
/// \code
/// class foo : public cppcms::application {
/// ...
/// void page(int x,std::string const &name);
/// void update(int x);
/// foo(...)
/// {
/// using booster::regex;
/// dispatcher().map(regex("/page/(\\d+)(/(.*))?",regex::icase),&foo::page,this,1,3);
/// dispatcher().map("/update/(\\d+)",&foo::update,this,1);
/// }
/// \endcode
///
/// When the reuqest URL the regualr expression \a re, \a member of \a app is called, For case of `page` that has two
/// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
///
/// In case of `update` - that has only 1 parameter, a single integer should be passed
///
/// In addition to calling \a member function it calls app->init() before call
/// and app->clean() after the call of the C is derived from cppcms::application
/// and app->clean() after the call if Application is derived from cppcms::application
///
///
/// \ver{v1_2}
template<typename C,typename P1>
void map(std::string const &re,void (C::*member)(P1),C *app,int g1)
{
map_generic(re,url_binder1<C,P1>(member,app,g1));
}
template<typename Application,typename... ApplicationMemberArgs>
void map(booster::regex const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );



#endif

///
/// Assign \a handler to pattern \a regex thus if URL that matches
/// this pattern requested, \a handler is called with matched results
@@ -579,65 +672,264 @@ namespace cppcms {
}


template<typename C>
struct url_binder0 {
typedef void (C::*member_type)();
member_type member;
C *self;
url_binder0(member_type m,C *s) : member(m),self(s) {}
bool operator()(application &,booster::cmatch const &)
{
page_guard<C> guard(self);
(self->*member)();
return true;
}
};
template<typename C,typename P1>
struct url_binder1 {
typedef void (C::*member_type)(P1);
member_type member;
C *self;
int g1;
url_binder1(member_type m,C *s,int p1) : member(m),self(s),g1(p1) {}
bool operator()(application &app,booster::cmatch const &m)
{
util::const_char_istream s;
setup_stream(app,s);
template<typename F>
struct url_binder;

typename booster::remove_const_reference<P1>::type p1;
bool res = parse(app,s,m,g1,p1);

if(!res) return false;
page_guard<C> guard(self);
(self->*member)(p1);
return true;
}
};
#define CPPCMS_DEFANDPARSE(N) typename booster::remove_const_reference<P##N>::type p##N; \
if(!parse(app,s,m,g##N,p##N)) return false;

#define CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE(N1) CPPCMS_DEFANDPARSE(N2)
#define CPPCMS_DEFANDPARSE3(N1,N2,N3) CPPCMS_DEFANDPARSE(N1) CPPCMS_DEFANDPARSE2(N2,N3)
#define CPPCMS_DEFANDPARSE4(N1,N2,N3,N4) CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE2(N3,N4)
#define CPPCMS_DEFANDPARSE5(N1,N2,N3,N4,N5) CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE3(N3,N4,N5)
template<typename C,typename P1,typename P2>
struct url_binder2 {
typedef void (C::*member_type)(P1,P2);
member_type member;
C *self;
int g1,g2;
url_binder2(member_type m,C *s,int p1,int p2) : member(m),self(s),g1(p1),g2(p2) {}
bool operator()(application &app,booster::cmatch const &m)
{
util::const_char_istream s;
setup_stream(app,s);

typename booster::remove_const_reference<P1>::type p1;
typename booster::remove_const_reference<P2>::type p2;
bool res = parse(app,s,m,g1,p1) && parse(app,s,m,g2,p2);
if(!res) return false;
page_guard<C> guard(self);
(self->*member)(p1,p2);
return true;
}
};

#define CPPCMS_URLBINDER \
private: \
template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
struct url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> { \
typedef void (C::*member_type)(CPPCMS_URLBINDER_MPAR); \
member_type member; C *self; \
CPPCMS_URLBINDER_GPAR \
url_binder( \
member_type m,C *s CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_IPAR \
) : member(m), \
self(s) CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_CPAR \
{} \
bool operator()(application &CPPCMS_URLBINDER_P1,booster::cmatch const &CPPCMS_URLBINDER_P2) { \
CPPCMS_URLBINDER_INIT CPPCMS_URLBINDER_PARSE \
page_guard<C> guard(self); \
(self->*member)(CPPCMS_URLBINDER_PPAR); \
return true; \
} \
}; \
public: \
template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
void map(std::string const &me,std::string const &re, \
void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_IPAR) \
{ \
typedef url_binder<void(C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
map_generic(me,re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
} \
template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
void map(std::string const &re, \
void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_IPAR) \
{ \
typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
map_generic(re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
} \
template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
void map(std::string const &me,booster::regex const &re, \
void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_IPAR) \
{ \
typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
map_generic(me,re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
} \
template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
void map(booster::regex const &re, \
void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
CPPCMS_URLBINDER_IPAR) \
{ \
typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
map_generic(re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
} \
private:


#define CPPCMS_URLBINDER_PRD
#define CPPCMS_URLBINDER_INIT
#define CPPCMS_URLBINDER_TPAR
#define CPPCMS_URLBINDER_MPAR
#define CPPCMS_URLBINDER_PPAR
#define CPPCMS_URLBINDER_GPAR
#define CPPCMS_URLBINDER_IPAR
#define CPPCMS_URLBINDER_CPAR
#define CPPCMS_URLBINDER_PARSE
#define CPPCMS_URLBINDER_P1
#define CPPCMS_URLBINDER_P2

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE

#undef CPPCMS_URLBINDER_INIT
#undef CPPCMS_URLBINDER_PRD
#undef CPPCMS_URLBINDER_P1
#undef CPPCMS_URLBINDER_P2


#define CPPCMS_URLBINDER_PRD ,
#define CPPCMS_URLBINDER_INIT util::const_char_istream s; setup_stream(app,s);
#define CPPCMS_URLBINDER_P1 app
#define CPPCMS_URLBINDER_P2 m

#define CPPCMS_URLBINDER_TPAR typename P1
#define CPPCMS_URLBINDER_MPAR P1
#define CPPCMS_URLBINDER_PPAR p1
#define CPPCMS_URLBINDER_GPAR int g1;
#define CPPCMS_URLBINDER_IPAR int p1
#define CPPCMS_URLBINDER_CPAR g1(p1)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE(1)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE


#define CPPCMS_URLBINDER_TPAR typename P1,typename P2
#define CPPCMS_URLBINDER_MPAR P1,P2
#define CPPCMS_URLBINDER_PPAR p1,p2
#define CPPCMS_URLBINDER_GPAR int g1,g2;
#define CPPCMS_URLBINDER_IPAR int p1,int p2
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE2(1,2)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE


#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3
#define CPPCMS_URLBINDER_MPAR P1,P2,P3
#define CPPCMS_URLBINDER_PPAR p1,p2,p3
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE3(1,2,3)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE


#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4
#define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4
#define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE4(1,2,3,4)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE


#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5
#define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5
#define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE


#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6
#define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6
#define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE(6)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE

#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7
#define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6,P7
#define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6,p7
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6,g7;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6,int p7
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6),g7(p7)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE2(6,7)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE

#define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8
#define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6,P7,P8
#define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6,p7,p8
#define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6,g7,g8;
#define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8
#define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6),g7(p7),g8(p8)
#define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE3(6,7,8)

CPPCMS_URLBINDER

#undef CPPCMS_URLBINDER_TPAR
#undef CPPCMS_URLBINDER_MPAR
#undef CPPCMS_URLBINDER_PPAR
#undef CPPCMS_URLBINDER_GPAR
#undef CPPCMS_URLBINDER_IPAR
#undef CPPCMS_URLBINDER_CPAR
#undef CPPCMS_URLBINDER_PARSE

#undef CPPCMS_URLBINDER
#undef CPPCMS_URLBINDER_INIT
#undef CPPCMS_URLBINDER_PRD
#undef CPPCMS_URLBINDER_P1
#undef CPPCMS_URLBINDER_P2

struct _data;
booster::hold_ptr<_data> d;


+ 2
- 2
src/url_dispatcher.cpp View File

@@ -235,12 +235,12 @@ namespace cppcms {
d->options.push_back(make_handler(expr,h));
}
void url_dispatcher::map_generic(std::string const &method,std::string const &re,generic_handler const &h)
void url_dispatcher::map_generic(std::string const &method,booster::regex const &re,generic_handler const &h)
{
booster::shared_ptr<option> opt(new generic_option(method,re,h));
d->options.push_back(opt);
}
void url_dispatcher::map_generic(std::string const &re,generic_handler const &h)
void url_dispatcher::map_generic(booster::regex const &re,generic_handler const &h)
{
booster::shared_ptr<option> opt(new generic_option(re,h));
d->options.push_back(opt);


+ 108
- 12
tests/url_mapper_test.cpp View File

@@ -76,6 +76,13 @@ public:
ss<<v;
return "to_str(" + ss.str() + ")";
}
template<typename T>
static std::string ts(T v)
{
std::ostringstream ss;
ss<<':'<<v;
return ss.str();
}

void h1_i(int param)
{
@@ -105,6 +112,12 @@ public:
void get_0() { v_="get_0"; }
void get_1(int x) { v_="get_1:" + to_string(x); }
void get_2(int x,int y) { v_="get_2:" + to_string(x) + ":" + to_string(y); }
void get_3(int x,int y,int z) { v_="get_3" + ts(x)+ts(y)+ts(z); }
void get_4(int x,int y,int z,int t) { v_="get_4" + ts(x)+ts(y)+ts(z)+ts(t); }
void get_5(int a,int b,int c,int d,int e) { v_="get_5" + ts(a)+ts(b)+ts(c)+ts(d)+ts(e); }
void get_6(int a,int b,int c,int d,int e,int f) { v_="get_6" + ts(a)+ts(b)+ts(c)+ts(d)+ts(e)+ts(f); }
void get_7(int a,int b,int c,int d,int e,int f,int g) { v_="get_7" + ts(a)+ts(b)+ts(c)+ts(d)+ts(e)+ts(f)+ts(g); }
void get_8(int a,int b,int c,int d,int e,int f,int g,int h) { v_="get_8" + ts(a)+ts(b)+ts(c)+ts(d)+ts(e)+ts(f)+ts(g)+ts(h); }
void p_0() { v_="p_0"; }
void p_1(int x) { v_="p_1:" + to_string(x); }
@@ -127,10 +140,12 @@ public:
dispatcher().assign("h6/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",&disp::h6,this,2,4,6,8,10,12);
dispatcher().map("/h0",&disp::h0,this);
dispatcher().map(booster::regex("/rh0",booster::regex::icase),&disp::h0,this);
dispatcher().map("/h1_num/(.*)",&disp::h1_i,this,1);
dispatcher().map("/h1_num/(.*)",&disp::h1_d,this,1);

dispatcher().map("/h1_s/(\\d+)",&disp::h1_s,this,1);
dispatcher().map(booster::regex("/rh1_s/(\\d+)",booster::regex::icase),&disp::h1_s,this,1);
dispatcher().map("/h1_s_cr/((\\d+))",&disp::h1_s_cr,this,2);
dispatcher().map("/h1_s_r/(\\d+)",&disp::h1_s_r,this,1);
dispatcher().map("/h1_s_c/(\\d+)",&disp::h1_s_c,this,1);
@@ -139,16 +154,68 @@ public:

dispatcher().map("GET","/res",&disp::get_0,this);
dispatcher().map("GET","/res/(a(\\d+))",&disp::get_1,this,2);
//dispatcher().map("GET","/res/(a(\\d+))/(a(\\d+))",&disp::get_2,this,1,2);
dispatcher().map("GET","/res/(a(\\d+))/(a(\\d+))",&disp::get_2,this,2,4);



dispatcher().map("(PUT|POST)","/res",&disp::p_0,this);
dispatcher().map("(PUT|POST)","/res/(a(\\d+))",&disp::p_1,this,2);
//dispatcher().map("(PUT|POST)","/res/(a(\\d+)/(a(\\d+))",&disp::p_2,this,2,4);
dispatcher().map("(PUT|POST)","/res/(a(\\d+))/(a(\\d+))",&disp::p_2,this,2,4);

dispatcher().map("/point/(.*)",&disp::point_m,this,1);
dispatcher().map("/foo/(.*)",&disp::foo_m,this,1);


dispatcher().map("GET" , "/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_3,this,2,4,6);
dispatcher().map( "/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_3,this,2,4,6);
dispatcher().map("GET" ,booster::regex( "/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_3,this,2,4,6);
dispatcher().map( booster::regex( "/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_3,this,2,4,6);


dispatcher().map("GET" , "/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_4,this,2,4,6,8);
dispatcher().map( "/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_4,this,2,4,6,8);
dispatcher().map("GET" ,booster::regex( "/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_4,this,2,4,6,8);
dispatcher().map( booster::regex( "/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_4,this,2,4,6,8);

dispatcher().map("GET" , "/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_5,this,2,4,6,8,10);
dispatcher().map( "/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_5,this,2,4,6,8,10);
dispatcher().map("GET" ,booster::regex( "/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_5,this,2,4,6,8,10);
dispatcher().map( booster::regex( "/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_5,this,2,4,6,8,10);

dispatcher().map("GET" , "/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_6,this,2,4,6,8,10,12);
dispatcher().map( "/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))", &disp::get_6,this,2,4,6,8,10,12);
dispatcher().map("GET" ,booster::regex( "/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_6,this,2,4,6,8,10,12);
dispatcher().map( booster::regex( "/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase), &disp::get_6,this,2,4,6,8,10,12);
dispatcher().map("GET" ,
"/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",
&disp::get_7,this,2,4,6,8,10,12,14);

dispatcher().map("/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",
&disp::get_7,this,2,4,6,8,10,12,14);

dispatcher().map("GET" ,
booster::regex("/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase),
&disp::get_7,this,2,4,6,8,10,12,14);

dispatcher().map(
booster::regex("/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase),
&disp::get_7,this,2,4,6,8,10,12,14);

dispatcher().map("GET" ,
"/res_1/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",
&disp::get_8,this,2,4,6,8,10,12,14,16);

dispatcher().map("/res_2/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",
&disp::get_8,this,2,4,6,8,10,12,14,16);

dispatcher().map("GET" ,
booster::regex("/RES_3/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase),
&disp::get_8,this,2,4,6,8,10,12,14,16);

dispatcher().map(
booster::regex("/RES_4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",booster::regex::icase),
&disp::get_8,this,2,4,6,8,10,12,14,16);
}
#define TESTD(x,y) do { main(x); TEST(v_==y); } while(0)

@@ -166,40 +233,39 @@ public:
TESTD("h6/a1/a2/a3/a4/a5/a6",":1:2:3:4:5:6");


set_context("GET");
std::cout << std::use_facet<booster::locale::info>(context().locale()).encoding() << std::endl;
release_context();

TESTM("GET","/h0","-");
TESTM("GET","/rh0","-");
TESTM("GET","/RH0","-");
TESTM("GET","/h1_num/123.3","h1_d:to_str(123.3)");
TESTM("GET","/h1_num/123","h1_i:to_str(123)");
TESTM("GET","/h1_num/123 23","none");
TESTM("GET","/h1_s/1111","h1_s:1111");
TESTM("GET","/RH1_S/1111","h1_s:1111");
TESTM("GET","/h1_s_c/1111","h1_s_c:1111");
TESTM("GET","/h1_s_r/1111","h1_s_r:1111");
TESTM("GET","/h1_s_cr/1111","h1_s_cr:1111");
TESTM("GET","/h1_s_cr/1111\xFF","none");
TESTM("GET","/h1_s_cr/1111\xFF","none");
TESTM("GET","/name/\\xD7\\xA9\\xD7\\x9C\\xD7\\x95\\xD7\\x9D\\x20\\xE6\\x97\\xA5\\xE6\\x9C\\xAC\\xE8\\xAA\\x9E",
"h1_s:\\xD7\\xA9\\xD7\\x9C\\xD7\\x95\\xD7\\x9D\\x20\\xE6\\x97\\xA5\\xE6\\x9C\\xAC\\xE8\\xAA\\x9E");
TESTM("GET","/name/\xD7\xA9\xD7\x9C\xD7\x95\xD7\x9D\x20\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E",
"h1_s:\xD7\xA9\xD7\x9C\xD7\x95\xD7\x9D\x20\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E");
TESTM("GET","/name/\xFF","none");

TESTM("GET","/res","get_0");
TESTM("GET","/res/a1","get_1:to_str(1)");
//TESTM("GET","/res/a1/a2","get_2:to_str(1):to_str(2)");
TESTM("GET","/res/a1/a2","get_2:to_str(1):to_str(2)");
TESTM("POST","/res","p_0");
TESTM("POST","/res/a1","p_1:to_str(1)");
//TESTM("POST","/res/a1/a2","p_2:to_str(1):to_str(2)");
TESTM("POST","/res/a1/a2","p_2:to_str(1):to_str(2)");

TESTM("PUT","/res","p_0");
TESTM("PUT","/res/a1","p_1:to_str(1)");
//TESTM("PUT","/res/a1/a2","p_2:to_str(1):to_str(2)");
TESTM("PUT","/res/a1/a2","p_2:to_str(1):to_str(2)");

TESTM("DELETE","/res","none");
TESTM("DELETE","/res/a1","none");
//TESTM("DELETE","/res/a1/a2","none");
TESTM("DELETE","/res/a1/a2","none");

TESTM("GET","/point/123,23","point:to_str(123)Xto_str(23)");
TESTM("GET","/point/123","none");
@@ -207,6 +273,36 @@ public:

TESTM("GET","/foo/abcd","foo:to_str(4)");
TESTM("GET","/foo/abcdefg","foo:to_str(7)");
TESTM("GET","/res_1/a1/a2/a3","get_3:1:2:3");
TESTM("GET","/res_2/a1/a2/a3","get_3:1:2:3");
TESTM("GET","/res_3/a1/a2/a3","get_3:1:2:3");
TESTM("GET","/res_4/a1/a2/a3","get_3:1:2:3");
TESTM("GET","/res_1/a1/a2/a3/a4","get_4:1:2:3:4");
TESTM("GET","/res_2/a1/a2/a3/a4","get_4:1:2:3:4");
TESTM("GET","/res_3/a1/a2/a3/a4","get_4:1:2:3:4");
TESTM("GET","/res_4/a1/a2/a3/a4","get_4:1:2:3:4");
TESTM("GET","/res_1/a1/a2/a3/a4/a5","get_5:1:2:3:4:5");
TESTM("GET","/res_2/a1/a2/a3/a4/a5","get_5:1:2:3:4:5");
TESTM("GET","/res_3/a1/a2/a3/a4/a5","get_5:1:2:3:4:5");
TESTM("GET","/res_4/a1/a2/a3/a4/a5","get_5:1:2:3:4:5");

TESTM("GET","/res_1/a1/a2/a3/a4/a5/a6","get_6:1:2:3:4:5:6");
TESTM("GET","/res_2/a1/a2/a3/a4/a5/a6","get_6:1:2:3:4:5:6");
TESTM("GET","/res_3/a1/a2/a3/a4/a5/a6","get_6:1:2:3:4:5:6");
TESTM("GET","/res_4/a1/a2/a3/a4/a5/a6","get_6:1:2:3:4:5:6");
TESTM("GET","/res_1/a1/a2/a3/a4/a5/a6/a7","get_7:1:2:3:4:5:6:7");
TESTM("GET","/res_2/a1/a2/a3/a4/a5/a6/a7","get_7:1:2:3:4:5:6:7");
TESTM("GET","/res_3/a1/a2/a3/a4/a5/a6/a7","get_7:1:2:3:4:5:6:7");
TESTM("GET","/res_4/a1/a2/a3/a4/a5/a6/a7","get_7:1:2:3:4:5:6:7");

TESTM("GET","/res_1/a1/a2/a3/a4/a5/a6/a7/a8","get_8:1:2:3:4:5:6:7:8");
TESTM("GET","/res_2/a1/a2/a3/a4/a5/a6/a7/a8","get_8:1:2:3:4:5:6:7:8");
TESTM("GET","/res_3/a1/a2/a3/a4/a5/a6/a7/a8","get_8:1:2:3:4:5:6:7:8");
TESTM("GET","/res_4/a1/a2/a3/a4/a5/a6/a7/a8","get_8:1:2:3:4:5:6:7:8");
}
void set_context(std::string const &method="GET")
{


Loading…
Cancel
Save