diff options
| -rw-r--r-- | icespider/core/core.cpp | 62 | ||||
| -rw-r--r-- | icespider/core/core.h | 9 | ||||
| -rw-r--r-- | icespider/core/ihttpRequest.cpp | 19 | ||||
| -rw-r--r-- | icespider/core/ihttpRequest.h | 5 | ||||
| -rw-r--r-- | icespider/fcgi/cgiCore.cpp | 51 | ||||
| -rw-r--r-- | icespider/fcgi/cgiCore.h | 21 | ||||
| -rw-r--r-- | icespider/fcgi/cgiRequestBase.cpp | 13 | ||||
| -rw-r--r-- | icespider/fcgi/cgiRequestBase.h | 3 | ||||
| -rw-r--r-- | icespider/fcgi/main.cpp | 3 | ||||
| -rw-r--r-- | icespider/unittests/Jamfile.jam | 3 | ||||
| -rw-r--r-- | icespider/unittests/testApp.cpp | 26 | ||||
| -rw-r--r-- | icespider/unittests/testFcgi.cpp | 4 | 
12 files changed, 138 insertions, 81 deletions
diff --git a/icespider/core/core.cpp b/icespider/core/core.cpp index ab80b90..117c869 100644 --- a/icespider/core/core.cpp +++ b/icespider/core/core.cpp @@ -10,17 +10,6 @@ INSTANTIATEFACTORY(IceSpider::Plugin, Ice::CommunicatorPtr, Ice::PropertiesPtr);  namespace IceSpider {  	const boost::filesystem::path Core::defaultConfig("config/ice.properties"); -	static -	bool -	operator/=(const PathElements & pathparts, const IRouteHandler * r) -	{ -		auto rpi = r->parts.begin(); -		for (auto ppi = pathparts.begin(); ppi != pathparts.end(); ++ppi, ++rpi) { -			if (!(*rpi)->matches(*ppi)) return false; -		} -		return true; -	} -  	Core::Core(const Ice::StringSeq & args)  	{  		Ice::InitializationData id; @@ -34,18 +23,11 @@ namespace IceSpider {  		// Initialize routes  		for (const auto & rp : AdHoc::PluginManager::getDefault()->getAll<RouteHandlerFactory>()) { -			auto r = rp->implementation()->create(this); -			if (routes.size() <= r->pathElementCount()) { -				routes.resize(r->pathElementCount() + 1); -			} -			auto & lroutes = routes[r->pathElementCount()]; -			lroutes.push_back(r); -		} -		for (auto & l : routes) { -			std::sort(l.begin(), l.end(), [](const auto & a, const auto & b) { -				return a->path < b->path; -			}); +			allRoutes.push_back(rp->implementation()->create(this));  		} +		std::sort(allRoutes.begin(), allRoutes.end(), [](const auto & a, const auto & b) { +			return a->path < b->path; +		});  		// Load plugins  		auto plugins = AdHoc::PluginManager::getDefault()->getAll<PluginFactory>();  		if (!plugins.empty()) { @@ -69,21 +51,19 @@ namespace IceSpider {  			pluginAdapter->deactivate();  			pluginAdapter->destroy();  		} -		// Initialize routes -		for (auto l : routes) { -			for (auto r : l) { -				delete r; -			} +		// Terminate routes +		for (auto r : allRoutes) { +			delete r;  		}  		if (communicator) communicator->destroy();  	}  	void -	Core::process(IHttpRequest * request) const +	Core::process(IHttpRequest * request, const IRouteHandler * route) const  	{  		try { -			findRoute(request)->execute(request); +			(route ? route : findRoute(request))->execute(request);  		}  		catch (const HttpException & he) {  			request->response(he.code, he.message); @@ -96,28 +76,10 @@ namespace IceSpider {  		}  	} -	const IRouteHandler * -	Core::findRoute(const IHttpRequest * request) const +	const IceSpider::IRouteHandler * +	Core::findRoute(const IceSpider::IHttpRequest *) const  	{ -		const auto & pathparts = request->getRequestPath(); -		const auto method = request->getRequestMethod(); -		if (pathparts.size() >= routes.size()) { -			throw Http404_NotFound(); -		} -		const auto & routeSet = routes[pathparts.size()]; -		bool match = false; -		for (const auto & r : routeSet) { -			if (pathparts /= r) { -				if (r->method == method) { -					return r; -				} -				match = true; -			} -		} -		if (!match) { -			throw Http404_NotFound(); -		} -		throw Http405_MethodNotAllowed(); +		throw Http404_NotFound();  	}  	Ice::ObjectPrx diff --git a/icespider/core/core.h b/icespider/core/core.h index 0627e74..d6aa173 100644 --- a/icespider/core/core.h +++ b/icespider/core/core.h @@ -11,14 +11,13 @@  namespace IceSpider {  	class DLL_PUBLIC Core {  		public: -			typedef std::vector<const IRouteHandler *> LengthRoutes; -			typedef std::vector<LengthRoutes> Routes; +			typedef std::vector<const IRouteHandler *> AllRoutes;  			Core(const Ice::StringSeq & = {});  			~Core(); -			void process(IHttpRequest *) const; -			const IRouteHandler * findRoute(const IHttpRequest *) const; +			virtual const IRouteHandler * findRoute(const IHttpRequest *) const; +			void process(IHttpRequest *, const IRouteHandler * = nullptr) const;  			Ice::ObjectPrx getProxy(const char * type) const; @@ -28,7 +27,7 @@ namespace IceSpider {  				return Interface::ProxyType::uncheckedCast(getProxy(typeid(Interface).name()));  			} -			Routes routes; +			AllRoutes allRoutes;  			Ice::CommunicatorPtr communicator;  			Ice::ObjectAdapterPtr pluginAdapter; diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp index 1ca4c38..dea84e0 100644 --- a/icespider/core/ihttpRequest.cpp +++ b/icespider/core/ihttpRequest.cpp @@ -101,8 +101,8 @@ namespace IceSpider {  			const IceUtil::Optional<std::string> & d, const IceUtil::Optional<std::string> & p, bool s,  			IceUtil::Optional<time_t> e)  	{ -		auto & o = getOutputStream(); -		o << "Set-Cookie: " << XWwwFormUrlEncoded::urlencode(name) << +		std::stringstream o; +		o << XWwwFormUrlEncoded::urlencode(name) <<  			'=' << XWwwFormUrlEncoded::urlencode(value);  		if (e) {  			char buf[45]; @@ -115,7 +115,7 @@ namespace IceSpider {  		if (d) o << "; domain=" << *d;  		if (p) o << "; path=" << *p;  		if (s) o << "; secure"; -		o << "\r\n"; +		setHeader("Set-Cookie", o.str());  	}  	template <typename T> @@ -127,17 +127,8 @@ namespace IceSpider {  	void IHttpRequest::responseRedirect(const std::string & url, const IceUtil::Optional<std::string> & statusMsg) const  	{ -		getOutputStream() -			<< "Status: 303 " << (statusMsg ? *statusMsg : "Moved") << "\r\n" -			<< "Location: " << url << "\r\n" -			<< "\r\n"; -	} - -	void IHttpRequest::response(short statusCode, const std::string & statusMsg) const -	{ -		getOutputStream() -			<< "Status: " << statusCode << " " << statusMsg << "\r\n" -			<< "\r\n"; +		setHeader("Location", url); +		response(303, (statusMsg ? *statusMsg : "Moved"));  	} diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 0cd0f8b..d92d549 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -35,6 +35,7 @@ namespace IceSpider {  			virtual ContentTypeSerializer getSerializer(const IRouteHandler *) const;  			virtual std::istream & getInputStream() const = 0;  			virtual std::ostream & getOutputStream() const = 0; +			virtual void setHeader(const std::string &, const std::string &) const = 0;  			template<typename T>  			T getURLParam(unsigned int) const; @@ -70,12 +71,12 @@ namespace IceSpider {  			IceUtil::Optional<T> getHeaderParam(const std::string & key) const;  			template<typename T>  			IceUtil::Optional<T> getCookieParam(const std::string & key) const; -			void response(short, const std::string &) const; +			virtual void response(short, const std::string &) const = 0;  			template<typename T>  			void response(const IRouteHandler * route, const T & t) const  			{  				auto s = getSerializer(route); -				getOutputStream() << "Content-Type: " << s.first.group << "/" << s.first.type << "\r\n"; +				setHeader("Content-Type", s.first.group + "/" + s.first.type);  				response(200, "OK");  				Slicer::SerializeAnyWith<T>(t, s.second);  			} diff --git a/icespider/fcgi/cgiCore.cpp b/icespider/fcgi/cgiCore.cpp new file mode 100644 index 0000000..0adefab --- /dev/null +++ b/icespider/fcgi/cgiCore.cpp @@ -0,0 +1,51 @@ +#include "cgiCore.h" + +namespace IceSpider { +	static +	bool +	operator/=(const PathElements & pathparts, const IRouteHandler * r) +	{ +		auto rpi = r->parts.begin(); +		for (auto ppi = pathparts.begin(); ppi != pathparts.end(); ++ppi, ++rpi) { +			if (!(*rpi)->matches(*ppi)) return false; +		} +		return true; +	} + +	CgiCore::CgiCore(const Ice::StringSeq & opts) : +		Core(opts) +	{ +		for (const auto & r : allRoutes) { +			if (routes.size() <= r->pathElementCount()) { +				routes.resize(r->pathElementCount() + 1); +			} +			auto & lroutes = routes[r->pathElementCount()]; +			lroutes.push_back(r); +		} +	} + +	const IRouteHandler * +	CgiCore::findRoute(const IHttpRequest * request) const +	{ +		const auto & pathparts = request->getRequestPath(); +		const auto method = request->getRequestMethod(); +		if (pathparts.size() >= routes.size()) { +			throw Http404_NotFound(); +		} +		const auto & routeSet = routes[pathparts.size()]; +		bool match = false; +		for (const auto & r : routeSet) { +			if (pathparts /= r) { +				if (r->method == method) { +					return r; +				} +				match = true; +			} +		} +		if (!match) { +			throw Http404_NotFound(); +		} +		throw Http405_MethodNotAllowed(); +	} +} + diff --git a/icespider/fcgi/cgiCore.h b/icespider/fcgi/cgiCore.h new file mode 100644 index 0000000..1915a4d --- /dev/null +++ b/icespider/fcgi/cgiCore.h @@ -0,0 +1,21 @@ +#ifndef ICESPIDER_CGI_CGICORE_H +#define ICESPIDER_CGI_CGICORE_H + +#include <core.h> + +namespace IceSpider { +	class CgiCore : public Core { +		public: +			typedef std::vector<const IRouteHandler *> LengthRoutes; +			typedef std::vector<LengthRoutes> Routes; + +			CgiCore(const Ice::StringSeq & = {}); + +			const IRouteHandler * findRoute(const IHttpRequest *) const override; + +			Routes routes; +	}; +} + +#endif + diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp index a773b07..e820e05 100644 --- a/icespider/fcgi/cgiRequestBase.cpp +++ b/icespider/fcgi/cgiRequestBase.cpp @@ -121,6 +121,19 @@ namespace IceSpider {  		return optionalLookup(("HTTP_" + boost::algorithm::to_upper_copy(key)).c_str(), envmap);  	} +	void CgiRequestBase::response(short statusCode, const std::string & statusMsg) const +	{ +		getOutputStream() +			<< "Status: " << statusCode << " " << statusMsg << "\r\n" +			<< "\r\n"; +	} + +	void +	CgiRequestBase::setHeader(const std::string & header, const std::string & value) const +	{ +		getOutputStream() << header << ": " << value << "\r\n"; +	} +  	bool  	CgiRequestBase::cmp_str::operator()(char const * a, char const * b) const  	{ diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index e613866..ec3d4dd 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -28,6 +28,9 @@ namespace IceSpider {  			OptionalString getCookieParam(const std::string & key) const override;  			OptionalString getEnv(const std::string & key) const override; +			void response(short, const std::string &) const override; +			void setHeader(const std::string &, const std::string &) const override; +  		private:  			static OptionalString optionalLookup(const std::string & key, const VarMap &);  			static OptionalString optionalLookup(const std::string & key, const StringMap &); diff --git a/icespider/fcgi/main.cpp b/icespider/fcgi/main.cpp index 2c543e1..4149cb2 100644 --- a/icespider/fcgi/main.cpp +++ b/icespider/fcgi/main.cpp @@ -1,6 +1,7 @@  #include <visibility.h>  #include "fcgiRequest.h"  #include "cgiRequest.h" +#include "cgiCore.h"  using namespace IceSpider; @@ -8,7 +9,7 @@ DLL_PUBLIC  int  main(int argc, char ** argv, char ** env)  { -	Core core; +	CgiCore core;  	if (!FCGX_IsCGI()) {  		FCGX_Request request; diff --git a/icespider/unittests/Jamfile.jam b/icespider/unittests/Jamfile.jam index 8a0edff..ddc1e4a 100644 --- a/icespider/unittests/Jamfile.jam +++ b/icespider/unittests/Jamfile.jam @@ -64,6 +64,7 @@ run  	testApp.cpp  	base2.cpp  	testRoutes.json +	../fcgi/cgiCore.cpp  	: :  	config/ice.properties  	xslt/transform.xslt @@ -83,12 +84,14 @@ run  	<implicit-dependency>test-api  	<dependency>../compile  	<include>. +	<include>../fcgi  	: testApp ;  run  	testFcgi.cpp  	test-fcgi.ice  	../fcgi/cgiRequestBase.cpp +	../fcgi/cgiCore.cpp  	: : :  	<slicer>yes  	<define>BOOST_TEST_DYN_LINK diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index de5e921..e42a5aa 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -3,7 +3,7 @@  #include <safeMapFind.h>  #include <irouteHandler.h> -#include <core.h> +#include <cgiCore.h>  #include <exceptions.h>  #include <test-api.h>  #include <Ice/ObjectAdapter.h> @@ -84,6 +84,18 @@ class TestRequest : public IHttpRequest {  			return output;  		} +		void response(short statusCode, const std::string & statusMsg) const override +		{ +			getOutputStream() +				<< "Status: " << statusCode << " " << statusMsg << "\r\n" +				<< "\r\n"; +		} + +		void setHeader(const std::string & header, const std::string & value) const override +		{ +			getOutputStream() << header << ": " << value << "\r\n"; +		} +  		typedef std::map<std::string, std::string> MapVars;  		typedef std::vector<std::string> UrlVars;  		UrlVars url; @@ -97,10 +109,10 @@ class TestRequest : public IHttpRequest {  		const HttpMethod method;  }; -class CoreWithProps : public Core { +class CoreWithProps : public CgiCore {  	public:  		CoreWithProps() : -			Core({ +			CgiCore({  				"--Custom.Prop=value"  			})  		{ @@ -119,10 +131,10 @@ BOOST_AUTO_TEST_CASE( properties )  BOOST_AUTO_TEST_SUITE_END(); -class CoreWithFileProps : public Core { +class CoreWithFileProps : public CgiCore {  	public:  		CoreWithFileProps() : -			Core({ +			CgiCore({  				"--IceSpider.Config=config/custom.properties",  				"--Custom.Prop=value"  			}) @@ -144,7 +156,7 @@ BOOST_AUTO_TEST_CASE( properties )  BOOST_AUTO_TEST_SUITE_END(); -BOOST_FIXTURE_TEST_SUITE(defaultProps, Core); +BOOST_FIXTURE_TEST_SUITE(defaultProps, CgiCore);  BOOST_AUTO_TEST_CASE( testCoreSettings )  { @@ -228,7 +240,7 @@ class TestSerice : public TestIceSpider::TestApi {  		}  }; -class TestApp : public Core { +class TestApp : public CgiCore {  	public:  		TestApp() :  			adp(communicator->createObjectAdapterWithEndpoints("test", "default")) diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp index bf8e442..2db9bcf 100644 --- a/icespider/unittests/testFcgi.cpp +++ b/icespider/unittests/testFcgi.cpp @@ -1,7 +1,7 @@  #define BOOST_TEST_MODULE TestApp  #include <boost/test/unit_test.hpp> -#include <core.h> +#include <cgiCore.h>  #include <definedDirs.h>  #include <cgiRequestBase.h>  #include <test-fcgi.h> @@ -87,7 +87,7 @@ namespace std {  	// LCOV_EXCL_STOP  } -BOOST_FIXTURE_TEST_SUITE( CgiRequestBase, IceSpider::Core ); +BOOST_FIXTURE_TEST_SUITE( CgiRequestBase, IceSpider::CgiCore );  BOOST_AUTO_TEST_CASE( NoEnvironment )  {  | 
