add HttpView to support html backend rendering

This commit is contained in:
an-tao 2018-05-29 17:21:37 +08:00
parent a0f065e684
commit 30ab716c6b
13 changed files with 314 additions and 9 deletions

View File

@ -8,6 +8,7 @@ class CommandHandler:public virtual drogon::DrObjectBase {
public: public:
virtual void handleCommand(std::vector<std::string> &parameters)=0; virtual void handleCommand(std::vector<std::string> &parameters)=0;
virtual bool isTopCommand(){return false;}
virtual std::string script(){return "";} virtual std::string script(){return "";}
virtual ~CommandHandler(){} virtual ~CommandHandler(){}
}; };

View File

@ -15,6 +15,7 @@ namespace drogon_ctl
{ {
public: public:
virtual void handleCommand(std::vector<std::string> &parameters) override; virtual void handleCommand(std::vector<std::string> &parameters) override;
std::string script(){return "create controller or view class files";} virtual std::string script() override {return "create controller or view class files";}
virtual bool isTopCommand() override {return true;}
}; };
} }

View File

@ -15,7 +15,7 @@ namespace drogon_ctl
{ {
public: public:
virtual void handleCommand(std::vector<std::string> &parameters) override; virtual void handleCommand(std::vector<std::string> &parameters) override;
std::string script(){return "create controller or view class files";} std::string script(){return "create controller files";}
protected: protected:
enum ControllerType{ enum ControllerType{

251
drogon_ctl/create_view.cc Executable file
View File

@ -0,0 +1,251 @@
#include "create_view.h"
#include "cmd.h"
#include <iostream>
#include <fstream>
#include <string>
static const std::string cxx_include="<%inc";
static const std::string cxx_end="%>";
static const std::string cxx_lang="<%c++";
static const std::string cxx_view_data="@@";
static const std::string cxx_output="$$";
using namespace drogon_ctl;
static std::string& replace_all(std::string& str,const std::string& old_value,const std::string& new_value)
{
std::string::size_type pos(0);
while(true) {
//std::cout<<str<<endl;
//std::cout<<"pos="<<pos<<endl;
if( (pos=str.find(old_value,pos))!=std::string::npos ) {
str = str.replace(pos, old_value.length(), new_value);
pos += new_value.length()-old_value.length();
pos++;
}
else
break;
}
return str;
}
static void parseCxxLine(std::ofstream &oSrcFile,const std::string line,const std::string streamName,const std::string viewDataName)
{
if(line.length()>0)
{ std::string tmp=line;
replace_all(tmp,cxx_output,streamName);
replace_all(tmp,cxx_view_data,viewDataName);
oSrcFile<<tmp<<"\n";
}
}
static void parseLine(std::ofstream &oSrcFile,std::string& line,const std::string& streamName,const std::string& viewDataName,int &cxx_flag,int returnFlag=1)
{
std::string::size_type pos(0);
if(line.length()==0)
return;
if(cxx_flag==0)
{
//find cxx lang begin
if((pos=line.find(cxx_lang))!=std::string::npos)
{
std::string oldLine=line.substr(0,pos);
parseLine(oSrcFile,oldLine,streamName,viewDataName,cxx_flag,0);
std::string newLine=line.substr(pos+cxx_lang.length());
cxx_flag=1;
parseLine(oSrcFile,newLine,streamName,viewDataName,cxx_flag,returnFlag);
}
else
{
if(line.length()>0)
oSrcFile<<"\t"<<streamName<<" << \""<<replace_all(line,"\"","\\\"");
if(returnFlag)
oSrcFile<<"\\n\";\n";
else
oSrcFile<<"\";\n";
}
}
else
{
if((pos=line.find(cxx_end))!=std::string::npos)
{
std::string newLine=line.substr(0,pos);
parseCxxLine(oSrcFile,newLine,streamName,viewDataName);
std::string oldLine=line.substr(pos+cxx_end.length());
cxx_flag=0;
parseLine(oSrcFile,oldLine,streamName,viewDataName,cxx_flag,returnFlag);
}
else
{
parseCxxLine(oSrcFile,line,streamName,viewDataName);
}
}
}
void create_view::handleCommand(std::vector<std::string> &parameters)
{
for(auto file:parameters)
{
if(file[0]=='-')
{
std::cout<<ARGS_ERROR_STR<<std::endl;
return;
}
}
createViewFiles(parameters);
}
void create_view::createViewFiles(std::vector<std::string> &cspFileNames)
{
for(auto file:cspFileNames)
{
std::cout<<"create view:"<<file<<std::endl;
createViewFile(file);
}
}
int create_view::createViewFile(const std::string &script_filename)
{
std::cout<<"create HttpView Class file by "<<script_filename<<std::endl;
std::ifstream infile(script_filename.c_str(),std::ifstream::in);
if(infile)
{
std::string::size_type pos = script_filename.rfind(".");
if(pos!=std::string::npos)
{
std::string className=script_filename.substr(0,pos);
if((pos=className.rfind("/"))!=std::string::npos)
{
className=className.substr(pos+1);
}
std::cout<<"className="<<className<<std::endl;
std::string headFileName=className+".h";
std::string sourceFilename=className+".cc";
std::ofstream oHeadFile(headFileName.c_str(),std::ofstream::out);
std::ofstream oSourceFile(sourceFilename.c_str(),std::ofstream::out);
if(!oHeadFile||!oSourceFile)
return -1;
newViewHeaderFile(oHeadFile,className);
newViewSourceFile(oSourceFile,className,infile);
}
else
return -1;
}
else
{
std::cerr<<"can't open file "<<script_filename<<std::endl;
return -1;
}
return 0;
}
void create_view::newViewHeaderFile(std::ofstream &file,const std::string &className)
{
file<<"//this file is generated by program automatically,don't modify it!\n";
file<<"#include <drogon/HttpView.h>\n";
file<<"using namespace drogon;\n";
file<<"class "<<className<<":public HttpView<"<<className<<">\n";
file<<"{\npublic:\n\t"<<className<<"(){};\n\tvirtual ~"<<className<<"(){};\n\tprotected:\n\t\
virtual HttpResponse* genHttpResponse(const HttpViewData&)override;\n};";
}
void create_view::newViewSourceFile(std::ofstream &file,const std::string &className,std::ifstream &infile)
{
file << "//this file is generated by program automatically,don't modify it!\n";
file << "#include \"" << className << ".h\"\n";
file <<"#include <string>\n";
file <<"#include <sstream>\n";
file <<"#include <map>\n";
file <<"#include <vector>\n";
file <<"#include <set>\n";
file <<"using namespace std;\n";
std::string buffer;
char line[8192];
int import_flag=0;
while(infile.getline(line,sizeof(line)))
{
buffer=line;
std::string::size_type pos(0);
if(!import_flag)
{
std::string lowerBuffer=buffer;
std::transform(lowerBuffer.begin(), lowerBuffer.end(), lowerBuffer.begin(), ::tolower);
if((pos=lowerBuffer.find(cxx_include))!=std::string::npos)
{
//std::cout<<"haha find it!"<<endl;
std::string newLine=buffer.substr(pos+cxx_include.length());
import_flag=1;
if((pos=newLine.find(cxx_end))!=std::string::npos)
{
newLine=newLine.substr(0,pos);
file<<newLine<<"\n";
break;
}else{
file<<newLine<<"\n";
}
}
}
else
{
//std::cout<<buffer<<endl;
if((pos=buffer.find(cxx_end))!=std::string::npos)
{
std::string newLine=buffer.substr(0,pos);
file<<newLine<<"\n";
break;
}
else
{
//std::cout<<"to source file"<<buffer<<endl;
file<<buffer<<"\n";
}
}
}
//std::cout<<"import_flag="<<import_flag<<std::endl;
if(import_flag==0)
{
infile.clear();
infile.seekg(0,std::ifstream::beg);
}
//std::cout<<"file pos:"<<infile.tellg()<<std::endl;
std::string viewDataName=className+"_view_data";
file <<"HttpResponse* "<<className<<"::genHttpResponse(const HttpViewData& "<<viewDataName<<")\n{\n";
//std::string bodyName=className+"_bodystr";
std::string streamName=className+"_tmp_stream";
//oSrcFile <<"\tstd::string "<<bodyName<<";\n";
file<<"\tstd::stringstream "<<streamName<<";\n";
int cxx_flag=0;
while(infile.getline(line,sizeof(line)))
{
buffer=line;
parseLine(file,buffer,streamName,viewDataName,cxx_flag);
}
file<<"\tauto res = HttpResponse::newHttpResponse();\n";
file<<"\tres->setStatusCode(HttpResponse::k200Ok);\n";
file<<"#ifdef CONTENT_TYPE\n";
file<<"\tres->setContentTypeCode(CONTENT_TYPE);\n";
file<<"#else\n";
file<<"\tres->setContentTypeCode(CT_TEXT_HTML);\n";
file<<"#endif\n";
file<<"\tres->setBody("<<streamName<<".str().c_str());\n\treturn res;\n}\n";
}

27
drogon_ctl/create_view.h Executable file
View File

@ -0,0 +1,27 @@
//
// Copyright 2018, An Tao. All rights reserved.
//
// Use of this source code is governed by a MIT license
// that can be found in the License file.
#pragma once
#include <drogon/DrObject.h>
#include "CommandHandler.h"
using namespace drogon;
namespace drogon_ctl
{
class create_view:public DrObject<create_view>,public CommandHandler
{
public:
virtual void handleCommand(std::vector<std::string> &parameters) override;
virtual std::string script() override {return "create view class files";}
protected:
void createViewFiles(std::vector<std::string> &cspFileNames);
int createViewFile(const std::string &script_filename);
void newViewHeaderFile(std::ofstream &file,const std::string &className);
void newViewSourceFile(std::ofstream &file,const std::string &className,std::ifstream &infile);
};
}

View File

@ -21,6 +21,8 @@ void help::handleCommand(std::vector<std::string> &parameters)
auto cmdHdlPtr=std::dynamic_pointer_cast<CommandHandler>(classPtr); auto cmdHdlPtr=std::dynamic_pointer_cast<CommandHandler>(classPtr);
if(cmdHdlPtr) if(cmdHdlPtr)
{ {
if(!cmdHdlPtr->isTopCommand())
continue;
auto pos=className.rfind("::"); auto pos=className.rfind("::");
if(pos!=std::string::npos) if(pos!=std::string::npos)
{ {

View File

@ -15,6 +15,7 @@ namespace drogon_ctl
{ {
public: public:
virtual void handleCommand(std::vector<std::string> &parameters) override; virtual void handleCommand(std::vector<std::string> &parameters) override;
std::string script(){return "display this message";} virtual std::string script() override {return "display this message";}
virtual bool isTopCommand() override {return true;}
}; };
} }

View File

@ -9,7 +9,8 @@ namespace drogon_ctl
{ {
public: public:
virtual void handleCommand(std::vector<std::string> &parameters) override; virtual void handleCommand(std::vector<std::string> &parameters) override;
std::string script(){return "display version of this tool";} virtual std::string script() override {return "display version of this tool";}
virtual bool isTopCommand() override {return true;}
version(){} version(){}
}; };
} }

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<%c++ std::string title=@@.get<std::string>("title");%>
<head>
<meta charset="UTF-8">
<title><%c++ $$<<title;%></title>
</head>
<body>
<footer>
<span>CopyRight@2017 All Rights Reserved</span>
</footer>
</body>
</html>

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include <drogon/DrObject.h> #include <drogon/DrObject.h>
#include <drogon/HttpResponse.h>
#include <drogon/HttpRequest.h>
#include <drogon/HttpViewBase.h>
namespace drogon { namespace drogon {
class HttpViewBase;
template <typename T> template <typename T>
class HttpView:public DrObject<T>,public HttpViewBase class HttpView:public DrObject<T>,public HttpViewBase
{ {

View File

@ -15,8 +15,8 @@
// that can be found in the License file. // that can be found in the License file.
#include "HttpResponseImpl.h" #include "HttpResponseImpl.h"
#include "HttpViewBase.h"
#include <drogon/HttpViewBase.h>
#include <drogon/HttpViewData.h> #include <drogon/HttpViewData.h>
#include <trantor/utils/Logger.h> #include <trantor/utils/Logger.h>
@ -60,9 +60,9 @@ HttpResponse* HttpResponse::locationRedirectResponse(std::string path)
return res; return res;
} }
newHttpViewResponse(const std::string &viewName,const HttpViewData& data) HttpResponse* HttpResponse::newHttpViewResponse(const std::string &viewName,const HttpViewData& data)
{ {
return HttpViewBase::genHttpResponse(viewName,data);
} }
const std::string HttpResponseImpl::web_content_type_to_string(uint8_t contenttype) const std::string HttpResponseImpl::web_content_type_to_string(uint8_t contenttype)
{ {

View File

@ -1,4 +1,10 @@
#include "HttpViewBase.h" //
// Copyright 2018, An Tao. All rights reserved.
//
// Use of this source code is governed by a MIT license
// that can be found in the License file.
#include <drogon/HttpViewBase.h>
#include <drogon/DrClassMap.h> #include <drogon/DrClassMap.h>
#include <trantor/utils/Logger.h> #include <trantor/utils/Logger.h>
#include <memory> #include <memory>