title: Implementing multiple API in casablanca
body: <p>I'm looking at this code which implements a simple JSON server using casablanca. I have not found a better example so far. The author seems to use a different HTTP method for each API which could become a problem when the server is supposed to many APIs. How should this problem be solved ? Would it mean that I would need multiple http_listeners ?</p>
  
  <pre><code>#include &lt;cpprest/http_listener.h&gt;
  #include &lt;cpprest/json.h&gt;
  
  using namespace web;
  using namespace web::http;
  using namespace web::http::experimental::listener;
  
  #include &lt;iostream&gt;
  #include &lt;map&gt;
  #include &lt;set&gt;
  #include &lt;string&gt;
  using namespace std;
  
  #define TRACE(msg)            wcout &lt;&lt; msg
  #define TRACE_ACTION(a, k, v) wcout &lt;&lt; a &lt;&lt; L" (" &lt;&lt; k &lt;&lt; L", " &lt;&lt; v &lt;&lt; L")\n"
  
  map&lt;utility::string_t, utility::string_t&gt; dictionary;
  typedef std::vector&lt;std::pair&lt;utility::string_t, json::value&gt;&gt; field_map;
  /* handlers implementation */
  
  void handle_get(http_request request)
  {
      TRACE(L"\nhandle GET\n");
  
      field_map answer;
  
      for (auto const &amp; p : dictionary)
      {
          answer.push_back(make_pair(p.first, json::value(p.second)));
      }
  
      request.reply(status_codes::OK, json::value::object(answer));
  }
  
  void handle_request(http_request request,
      function&lt;void(json::value &amp;, field_map &amp;)&gt; action)
  {
      field_map answer;
  
      request
          .extract_json()
          .then([&amp;answer, &amp;action](pplx::task&lt;json::value&gt; task) {
          try
          {
              auto &amp; jvalue = task.get();
  
              if (!jvalue.is_null())
              {
                  action(jvalue, answer);
              }
          }
          catch (http_exception const &amp; e)
          {
              wcout &lt;&lt; e.what() &lt;&lt; endl;
          }
      })
          .wait();
  
      request.reply(status_codes::OK, json::value::object(answer));
  }
  
  void handle_post(http_request request)
  {
      TRACE("\nhandle POST\n");
  
      handle_request(
          request,
          [](json::value &amp; jvalue, field_map &amp; answer)
      {
          for (auto const &amp; e : jvalue.as_array())
          {
              if (e.is_string())
              {
                  auto key = e.as_string();
  
                  auto pos = dictionary.find(key);
                  if (pos == dictionary.end())
                  {
                      answer.push_back(make_pair(key, json::value(L"&lt;nil&gt;")));
                  }
                  else
                  {
                      answer.push_back(make_pair(pos-&gt;first, json::value(pos-&gt;second)));
                  }
              }
          }
      }
      );
  }
  
  void handle_put(http_request request)
  {
      TRACE("\nhandle PUT\n");
  
      handle_request(
          request,
          [](json::value &amp; jvalue, field_map &amp; answer)
      {
          for (auto const &amp; e : jvalue.as_object())
          {
              if (e.second.is_string())
              {
                  auto key = e.first;
                  auto value = e.second.as_string();
  
                  if (dictionary.find(key) == dictionary.end())
                  {
                      TRACE_ACTION(L"added", key, value);
                      answer.push_back(make_pair(key, json::value(L"&lt;put&gt;")));
                  }
                  else
                  {
                      TRACE_ACTION(L"updated", key, value);
                      answer.push_back(make_pair(key, json::value(L"&lt;updated&gt;")));
                  }
  
                  dictionary[key] = value;
              }
          }
      }
      );
  }
  
  void handle_del(http_request request)
  {
      TRACE("\nhandle DEL\n");
  
      handle_request(
          request,
          [](json::value &amp; jvalue, field_map &amp; answer)
      {
          set&lt;utility::string_t&gt; keys;
          for (auto const &amp; e : jvalue.as_array())
          {
              if (e.is_string())
              {
                  auto key = e.as_string();
  
                  auto pos = dictionary.find(key);
                  if (pos == dictionary.end())
                  {
                      answer.push_back(make_pair(key, json::value(L"&lt;failed&gt;")));
                  }
                  else
                  {
                      TRACE_ACTION(L"deleted", pos-&gt;first, pos-&gt;second);
                      answer.push_back(make_pair(key, json::value(L"&lt;deleted&gt;")));
                      keys.insert(key);
                  }
              }
          }
  
          for (auto const &amp; key : keys)
              dictionary.erase(key);
      }
      );
  }
  
  int main()
  {
      http_listener listener(L"http://localhost/restdemo");
  
      listener.support(methods::GET, handle_get);
      listener.support(methods::POST, handle_post);
      listener.support(methods::PUT, handle_put);
      listener.support(methods::DEL, handle_del);
  
      try
      {
          listener
              .open()
              .then([&amp;listener]() {TRACE(L"\nstarting to listen\n"); })
              .wait();
  
          while (true);
      }
      catch (exception const &amp; e)
      {
          wcout &lt;&lt; e.what() &lt;&lt; endl;
      }
  
      return 0;
  }
  </code></pre>