EHS Embedded HTTP Server  1.5.1.0
ehs_test.cpp

Multiple instances serving different URI paths.This example shows, how multiple EHS instances can handle different URI paths. Furthermore, handling of cookies is demonstrated as well.

/* $Id: ehs_test.cpp 70 2011-12-12 17:11:44Z felfert $
*
* EHS is a library for embedding HTTP(S) support into a C++ application
*
* Copyright (C) 2004 Zachary J. Hansen
*
* Code cleanup, new features and bugfixes: Copyright (C) 2010 Fritz Elfert
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation;
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This can be found in the 'COPYING' file.
*
*/
#include <ehs.h>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include "common.h"
using namespace std;
class tester : public EHS
{
protected:
virtual ResponseCode HandleRequest(HttpRequest *, HttpResponse *);
public:
tester(string file, int delay = 0):
EHS(), m_nDelay(delay), m_oInfile(file.c_str())
{
cout << "loading file '" << file << "'" << endl;
if (m_oInfile.fail()) {
throw runtime_error("Could not open file");
}
}
private:
// delay
int m_nDelay;
// our source file
ifstream m_oInfile;
};
static int nRequests = 0;
static pthread_mutex_t oRequestMutex = PTHREAD_MUTEX_INITIALIZER;
ResponseCode tester::HandleRequest(HttpRequest *request, HttpResponse *response)
{
pthread_mutex_lock(&oRequestMutex);
int nMyRequest = ++nRequests;
pthread_mutex_unlock(&oRequestMutex);
if (0 == (nMyRequest % 1000)) {
cerr << "[" << nMyRequest << "]" << endl;
}
char buf[5000];
sleep (m_nDelay);
m_oInfile.getline(buf, 4999);
if (m_oInfile.eof()) {
// At end of file start from beginning
m_oInfile.seekg(0);
}
string sCopy(buf);
string sBody(buf);
sBody.append("<br>previous line: ").append(request->Cookies("ehs_test_cookie"));
response->SetBody(sBody.c_str(), sBody.length());
// throw in a cookie here, just to show how it's done
CookieParameters oCP;
string sCookieName("ehs_test_cookie_");
oCP["name"] = sCookieName.append(m_sRegisteredAs);
oCP["value"] = sCopy;
response->SetCookie(oCP);
// more attributes can go here
return HTTPRESPONSECODE_200_OK;
}
int main(int argc, char **argv)
{
cout << getEHSconfig() << endl;
if (argc < 4) {
string cmd = basename(argv[0]);
cerr << "Usage: " << cmd << " [mode] [port] [file] <delay> <threadcount> <norouterequest>)" << endl;
cerr << "\tModes: 1 - Single Threaded (last parameter ignored)" << endl;
cerr << "\tModes: 2 - Multithreaded, fixed number of threads" << endl;
cerr << "\tModes: 3 - Multithreaded, one thread per request (last parameter ignored)" << endl;
cerr << "\tnorouterequest: if anything is specified, requests will not be routed" << endl;
return 0;
}
int nDelay = 0;
int nThreadCount = 1;
int nMode = atoi(argv[1]);
if (argc >= 5) {
nDelay = atoi(argv[4]);
}
if (argc >= 6) {
nThreadCount = atoi(argv[5]);
}
EHSServerParameters oSP;
oSP["port"] = argv[2];
if (argc >= 7) {
oSP["norouterequest"] = 1;
}
switch (nMode) {
case 1:
cout << "Running in single threaded mode" << endl;
oSP["mode"] = "singlethreaded";
break;
case 2:
cout << "Running with a thread pool of " << nThreadCount << " threads" << endl;
oSP["mode"] = "threadpool";
oSP["threadcount"] = nThreadCount;
break;
case 3:
cout << "Running with one thread per request" << endl;
oSP["mode"] = "onethreadperrequest";
break;
default:
cerr << "Invalid mode specified: must be 1, 2, or 3" << endl;
return 0;
}
cout << "binding to " << argv[2] << endl;
cout << "Delay set to " << nDelay << " seconds" << endl;
tester srv(argv[3], nDelay);
try {
srv.StartServer(oSP);
tester a(argv[3]);
// Handles URIs like http://localhost/a
srv.RegisterEHS(&a, "a");
tester b(argv[3]);
// Handles URIs like http://localhost/b
srv.RegisterEHS(&b, "b");
tester aa(argv[3]);
// Handles URIs like http://localhost/a/a
a.RegisterEHS(&aa, "a");
tester ab(argv[3]);
// Handles URIs like http://localhost/a/b
a.RegisterEHS(&ab, "b");
// if in single threaded mode,
// we must handle data explicitly.
kbdio kbd;
cout << "Press q to terminate ..." << endl;
while (!(srv.ShouldTerminate() || kbd.qpressed())) {
if (1 == nMode) {
srv.HandleData(1000); // waits for 1 second
} else {
usleep(300000);
}
}
srv.StopServer();
} catch (exception &e) {
cerr << "ERROR: " << e.what() << endl;
}
return 0;
}
EHS provides HTTP server functionality to a child class.
Definition: ehs.h:147
This class represents a clients HTTP request.
Definition: httprequest.h:51
CookieMap & Cookies()
Retrieves cookies.
Definition: httprequest.h:173
This class represents what is sent back to the client.
Definition: httpresponse.h:54
void SetBody(const char *ipsBody, size_t inBodyLength)
Sets the body of this instance.
void SetCookie(CookieParameters &iroCookieParameters)
Sets cookies for this response.