Netwhere
 All Classes Pages
webservice.hpp
1 /*
2  * Copyright (c) 2017, Ben Smith
3  * All rights reserved.
4  *
5  */
6 
7 #ifndef __WEBSERVICE_H__
8 #define __WEBSERVICE_H__
9 
10 #include <microhttpd.h>
11 #include <stdexcept>
12 #include <string>
13 #include <iostream>
14 
15 template <typename Functor>
16 class WebService {
17  public:
18  WebService(Functor &functor)
19  : functor(functor) {}
20 
21  void start() {
22  daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
23  8080,
24  NULL,
25  NULL,
26  &on_request,
27  this,
28  MHD_OPTION_END);
29  if (daemon == NULL)
30  throw std::runtime_error("MHD_start_daemon");
31  }
32 
33  ~WebService() {
34  MHD_stop_daemon(daemon);
35  }
36 
37  private:
38  MHD_Daemon* daemon;
39  Functor functor;
40 
41  static int on_request(void * cls, struct MHD_Connection * connection, const char * url, const char * method, const char * version,
42  const char * upload_data, size_t * upload_data_size,
43  void ** ptr);
44 };
45 
46 template <typename Functor>
47 int WebService<Functor>::on_request(void * cls,
48  struct MHD_Connection * connection,
49  const char * url,
50  const char * method,
51  const char * version,
52  const char * upload_data,
53  size_t * upload_data_size,
54  void ** ptr) {
55  static int dummy;
56  int ret;
57 
58  if (std::string("GET") != method)
59  return MHD_NO; /* unexpected method */
60  if (&dummy != *ptr)
61  {
62  /* The first time only the headers are valid,
63  do not respond in the first round... */
64  *ptr = &dummy;
65  return MHD_YES;
66  }
67  if (0 != *upload_data_size)
68  return MHD_NO; /* upload data in a GET!? */
69 
70  WebService<Functor>* webservice = static_cast<WebService<Functor>*>(cls);
71 
72  struct MHD_Response * response;
73  *ptr = NULL; /* clear context pointer */
74 
75  try {
76  const std::string& data = webservice->functor(url);
77 
78  response = MHD_create_response_from_buffer (data.size(),
79  const_cast<char*>(data.c_str()),
80  MHD_RESPMEM_MUST_COPY);
81  MHD_add_response_header(response, "Content-Type", "application/json");
82  MHD_add_response_header(response, "Access-Control-Allow-Origin", "*");
83 
84  ret = MHD_queue_response(connection,
85  MHD_HTTP_OK,
86  response);
87  } catch (const std::exception& e) {
88  const std::string& data = e.what();
89  response = MHD_create_response_from_buffer (data.size(),
90  const_cast<char*>(data.c_str()),
91  MHD_RESPMEM_MUST_COPY);
92  MHD_add_response_header(response, "Content-Type", "text");
93 
94  ret = MHD_queue_response(connection,
95  MHD_HTTP_BAD_REQUEST,
96  response);
97  }
98 
99  MHD_destroy_response(response);
100  return ret;
101 }
102 
103 #endif
Definition: webservice.hpp:16