So the steps of an standalone witty w/ custom resource server:
- create a server
- register a custom resource on a desired path
- start the server, hence its resources
- wait for server shutdown signal
- stop the server
Here is the snippet of the main.cpp, ignore all log-related plumbing:
#include <Wt/WServer> #include <iostream> #include "MyResource.h" #include "log.h" using namespace std; using namespace Wt; int main(int argc, char **argv) { WLogger logger; configLogger(logger); try { WServer server(argv[0], ""); try { server.setServerConfiguration(argc, argv); MyResource dr; server.addResource(&dr, "/resource"); info(logger, "Starting resource server."); if (server.start()) { WServer::waitForShutdown(); server.stop(); } else { fatal(logger, "Fatal error starting resource server."); return 1; } return 0; } catch (std::exception& e) { fatal(logger, "Fatal error starting resource server.", e.what()); return 1; } } catch (WServer::Exception& e) { fatal(logger, "Fatal error creating WServer.", e.what()); return 1; } catch (exception& e) { fatal(logger, "Fatal error occurred.", e.what()); return 1; } }
You may notice the creation and registration of MyResource, this is place where you provide the service implementation, specifically on the handleRequest() method, take a look at MyResource.h:
#ifndef MYRESOURCE_H_ #define MYRESOURCE_H_ #include <Wt/WResource> using namespace Wt; using namespace Wt::Http; class MyResource: public WResource { public: MyResource(); virtual ~MyResource(); protected: virtual void handleRequest(const Request &request, Response &response); }; #endif /* MYPRESOURCE_H_ */
The implemantation is very trivial, it's just an echo of the request content also including some extra data like content type, content length and request method: GET, POST, etc. Enjoy MyResource.cpp:
#include <iostream> #include <Wt/Http/Response> #include "MyResource.h" using namespace std; using namespace Wt::Http; MyResource::MyResource() { } MyResource::~MyResource() { } void MyResource::handleRequest(const Request& request, Response& response) { string method = request.method(); string contentType = request.contentType(); int contentLength = request.contentLength(); char* buffer = new char[contentLength + 1]; request.in().read(buffer, contentLength); buffer[contentLength] = 0; response.setMimeType("application/xml"); ostream& out = response.out(); out << "<?xml version='1.0' encoding='utf-8' ?>" << endl; out << "<reply>" << endl; out << "<method>" << method << "</method>" << endl; out << "<contentType>" << contentType << "</contentType>" << endl; out << "<contentLenght>" << contentLength << "</contentLenght>" << endl; out << "<body>" << buffer << "</body>" << endl; out << "</reply>"; delete[] buffer; }
The reamining stuff is just plumbing as I said before, here you got log.h:
#ifndef LOG_H_ #define LOG_H_ #include <Wt/WLogger> using namespace std; using namespace Wt; void info(WLogger& logger, const string& message); void fatal(WLogger& logger, const string& message, const char* what); void fatal(WLogger& logger, const string& message); void configLogger(WLogger& logger); #endif /* LOG_H_ */
And log.cpp:
#include "log.h" #include <iostream> void info(WLogger& logger, const string& message) { WLogEntry entry = logger.entry("info"); entry << WLogger::timestamp << WLogger::sep << WLogger::sep << '[' << "info" << ']' << WLogger::sep << message; } void fatal(WLogger& logger, const string& message, const char* what) { WLogEntry entry = logger.entry("fatal"); entry << WLogger::timestamp << WLogger::sep << WLogger::sep << '[' << "fatal" << ']' << WLogger::sep << message << what; } void fatal(WLogger& logger, const string& message) { fatal(logger, message, ""); } void configLogger(WLogger& logger) { logger.addField("datetime", false); logger.addField("type", false); logger.addField("message", true); logger.setFile("/var/log/resource.log"); }
Now compile an run the server, here in this case using standalone server mode instead of fast cgi mode, but also works w/ fast cgi variant:
$ g++ log.cpp MyResource.cpp main.cpp -lwthttp -oresource
Run the server:
$ ./resource --http-address 0.0.0.0 --http-port 80 --docroot=. INFO: Opened log file (/var/log/resource.log). [2013-May-07 19:52:11.046985] 9658 - [info] "config: reading Wt config file: /etc/wt/wt_config.xml (location = './resource')" [2013-May-07 19:52:11.047757] 9658 - [info] "WServer/wthttp: initializing built-in wthttpd" [2013-May-07 19:52:11.048027] 9658 - [info] "wthttp: started server: http://0.0.0.0:80"
Finally test the service using a simple call:
$ curl -X POST -H "Content-Type: application/xml" -d"<payload>PAYLOAD GOES HERE!</payload>" http://localhost/resource
<?xml version='1.0' encoding='utf-8' ?> <reply> <method>POST</method> <contentType>application/xml</contentType> <contentLenght>37</contentLenght> <body><payload>PAYLOAD GOES HERE!</payload></body> </reply>Very simple as you can see!
Very nice. Thanks!
ReplyDelete-Jim
Very clear article. I like Wt, too.
ReplyDeleteStage Rental Chicago
ReplyDeleteSpeaker Rental Chicago
LED Wall Rental Chicago
Best barber in surrey
ReplyDeleteI’m really pleased to have found your website! The content is insightful and engaging, and I truly value the knowledge you’ve shared. Many thanks!
ReplyDeleteSAP Analytics Cloud Training In Chennai
SAP SuccessFactors Training In Chennai
SAP SD Training In Chennai
SAP MDG Training In Chennai
SAP TM Training In Chennai