Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
smassung committed Feb 21, 2016
0 parents commit 54b7180
Show file tree
Hide file tree
Showing 7 changed files with 420 additions and 0 deletions.
52 changes: 52 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
# BasedOnStyle: LLVM
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: true
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 60
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 4
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Allman
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
SpaceBeforeParens: ControlStatements
...
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
102 changes: 102 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
cmake_minimum_required(VERSION 3.0.0)
project(meta-simple-http-server)

set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

include(CTest)
include(CheckCXXCompilerFlag)
include_directories(include /usr/include /usr/local/include)

option(USE_LIBCXX "Use libc++ for the C++ standard library" OFF)

if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")

# if we don't already set the standard for the compiler, detect the
# best one available and use it
if(NOT "${CMAKE_CXX_FLAGS}" MATCHES "std=c\\+\\+(11|1y|14)")
check_cxx_compiler_flag(-std=c++14 HAS_CXX14)
if(HAS_CXX14)
message("-- Compiler supports C++14 (using it)")
set(STDOPT "-std=c++14")
endif()

if(NOT STDOPT)
check_cxx_compiler_flag(-std=c++1y HAS_CXX1Y)
if(HAS_CXX1Y)
message("-- Compiler supports C++1y (using it)")
set(STDOPT "-std=c++1y")
endif()
endif()

if(NOT STDOPT)
check_cxx_compiler_flag(-std=c++11 HAS_CXX11)
if(HAS_CXX11)
message("-- Compiler supports C++11 (using it)")
set(STDOPT "-std=c++11")
endif()
endif()

if(NOT STDOPT)
message(FATAL_ERROR
"server requires a compiler with at least C++11 support")
endif()

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STDOPT}")
endif()

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(CMAKE_GENERATOR STREQUAL "Ninja")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color")
endif()
endif()

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(CMAKE_GENERATOR STREQUAL "Ninja")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
endif()
if(USE_LIBCXX)
message("-- Locating libc++...")
find_library(LIBCXX_LIBRARY NAMES c++ cxx)
if(LIBCXX_LIBRARY)
message("-- Located libc++, using it.")
set(LIBCXX_OPTIONS "-stdlib=libc++")
message("-- Locating libc++'s abi...")
find_library(LIBCXXABI_LIBRARY NAMES c++abi)
find_library(LIBCXXRT_LIBRARY NAMES cxxrt)
if(LIBCXXABI_LIBRARY)
message("-- Found libc++abi, using it.")
set(CXXABI_LIBRARY ${LIBCXXABI_LIBRARY})
elseif(LIBCXXRT_LIBRARY)
message("-- Found libcxxrt, using it.")
set(CXXABI_LIBRARY ${LIBCXXRT_LIBRARY})
else()
message("-- No abi library found. "
"Attempting to continue without one...")
endif()
endif()
else()
message("-- Could not find libc++, will not use it.")
endif()
endif()

find_library(LIBDL_LIBRARY NAMES dl ldl)
if(LIBDL_LIBRARY)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${LIBDL_LIBRARY}")
endif()

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXX_OPTIONS}")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${CXXABI_LIBRARY}")
endif()

find_library(LIBEVENT NAMES event)
message("-- Found LIBEVENT: ${LIBEVENT}")

find_package(Threads REQUIRED)

add_library(simple-http-server src/simple_http_server.cpp)
target_link_libraries(simple-http-server ${LIBEVENT} ${CMAKE_THREAD_LIBS_INIT})

add_executable(api-server src/api_server.cpp)
target_link_libraries(api-server simple-http-server ${LIBEVENT}
${CMAKE_THREAD_LIBS_INIT})
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This class can be used to create simple demo APIs for various parts of
[MeTA](https://meta-toolkit.org).

It can also be used as a starting place for creating your own Web-based uses of
MeTA.

The implementation is based on [this blog
post](http://kukuruku.co/hub/cpp/lightweight-http-server-in-less-than-40-lines-on-libevent-and-c-11).

To test,

```bash
mkdir build
cd build/
cmake ../
make
./api-server
```

In another terminal,

```bash
curl --data "World" 0.0.0.0:8088
```
61 changes: 61 additions & 0 deletions include/simple_http_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @file simple_http_server.h
* @author Sean Massung
* @see
* http://kukuruku.co/hub/cpp/lightweight-http-server-in-less-than-40-lines-on-libevent-and-c-11
*/

#ifndef META_SIMPLE_HTTP_SERVER_H_
#define META_SIMPLE_HTTP_SERVER_H_

#include <event2/buffer.h>
#include <evhttp.h>

/**
* A very simple multithreaded HTTP server that can accept a string request and
* return a string response. Usually, the request and response will be JSON
* objects.
*/
class simple_http_server
{
public:
/**
* @param on_request A function that is called for each request (which uses
* the context parameter to perform some operation)
* @param context A pointer to an object that performs an operation for each
* request
* @param address The address the server is running on
* @param port The port the server is running on
* @param num_threads Number of threads to listen for requests
*/
simple_http_server(void (*on_request)(evhttp_request*, void*),
void* context, const std::string& address = "0.0.0.0",
int64_t port = 8088, int64_t num_threads = 4);

/**
* Starts the server and waits for a keypress to stop.
*/
void start() const;

/**
* @param req The request "object" from libevent
* @return a std::string version of the request data from the client
*/
static std::string receive_request_string(evhttp_request* req);

/**
* @param req The request "object" from libevent
* @param response The string data (probably JSON) to send to the client
*/
static void send_response_string(evhttp_request* req,
const std::string& response);

private:
void (*on_request_)(evhttp_request*, void*);
void* context_;
std::string address_;
int64_t port_;
int64_t num_threads_;
};

#endif
46 changes: 46 additions & 0 deletions src/api_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @file api_server.cpp
* @author Sean Massung
*/

#include <memory>
#include <event2/buffer.h>
#include <evhttp.h>

#include "simple_http_server.h"

class greeter
{
public:
greeter(const std::string& greeting) : greeting_{greeting}
{
// nothing
}

std::string greet(const std::string& request) const
{
return greeting_ + " " + request + "\n";
}

private:
std::string greeting_;
};

int main()
{
std::unique_ptr<greeter> grt = std::make_unique<greeter>("Hello");

void (*on_request)(evhttp_request*, void*)
= [](evhttp_request* req, void* void_ptr)
{
auto request_str = simple_http_server::receive_request_string(req);

greeter* grt_ptr = (greeter*)void_ptr;
auto result = grt_ptr->greet(request_str);

simple_http_server::send_response_string(req, result);
};

simple_http_server srv{on_request, grt.get()};
srv.start();
}
Loading

0 comments on commit 54b7180

Please sign in to comment.