PageRenderTime 36ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/mordor/http/servlet.cpp

http://github.com/mozy/mordor
C++ | 137 lines | 119 code | 13 blank | 5 comment | 33 complexity | 363f8945c90fc110f2bf700c55aa3911 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2010 - Mozy, Inc.
  2. #include "servlet.h"
  3. #include "mordor/assert.h"
  4. #include "server.h"
  5. namespace Mordor {
  6. namespace HTTP {
  7. Servlet::ptr
  8. ServletDispatcher::getServletPtr(ServletDispatcher::ServletOrCreator &creator)
  9. {
  10. Servlet::ptr servletPtr = boost::get<Servlet::ptr>(creator);
  11. if (servletPtr)
  12. return servletPtr;
  13. else
  14. return Servlet::ptr(boost::get<boost::function<Servlet *()> >(creator)());
  15. }
  16. Servlet::ptr
  17. ServletDispatcher::getServlet(const URI &uri)
  18. {
  19. MORDOR_ASSERT(!uri.authority.userinfoDefined());
  20. Servlet::ptr result;
  21. if (m_servlets.empty())
  22. return result;
  23. URI copy(uri);
  24. copy.normalize();
  25. ServletHostMap::iterator it = m_servlets.find(copy.authority);
  26. if (it != m_servlets.end()) {
  27. result = getServlet(it->second, copy.path);
  28. if (result)
  29. return result;
  30. }
  31. if (copy.authority.hostDefined()) {
  32. // fall back to no authority defined scenario
  33. it = m_servlets.find(URI::Authority());
  34. if (it != m_servlets.end())
  35. result = getServlet(it->second, copy.path);
  36. }
  37. return result;
  38. }
  39. void
  40. ServletDispatcher::request(ServerRequest::ptr request)
  41. {
  42. URI uri = request->request().requestLine.uri;
  43. if (!request->request().request.host.empty())
  44. uri.authority = request->request().request.host;
  45. Servlet::ptr servlet = getServlet(uri);
  46. if (servlet)
  47. servlet->request(request);
  48. else
  49. respondError(request, NOT_FOUND);
  50. }
  51. Servlet::ptr
  52. ServletDispatcher::getServletWildcard(ServletWildcardPathMap &vhost, const URI::Path &path)
  53. {
  54. // reverse order because '*' < [a-zA-Z]
  55. for (ServletWildcardPathMap::reverse_iterator it = vhost.rbegin();
  56. it != vhost.rend(); ++it) {
  57. if (wildcardPathMatch(it->first, path))
  58. return getServletPtr(it->second);
  59. }
  60. return Servlet::ptr();
  61. }
  62. Servlet::ptr
  63. ServletDispatcher::getServlet(ServletPathMapPair &vhosts, const URI::Path &path)
  64. {
  65. URI::Path copy(path);
  66. while (!copy.segments.empty()) {
  67. // search from non-wildcard path
  68. ServletPathMap::iterator it = vhosts.first.find(copy);
  69. if (it != vhosts.first.end())
  70. return getServletPtr(it->second);
  71. if (m_enableWildcard) {
  72. Servlet::ptr result = getServletWildcard(vhosts.second, copy);
  73. if (result)
  74. return result;
  75. }
  76. // can't find any match, shorten the path
  77. if (!copy.segments.back().empty()) {
  78. copy.segments.back().clear();
  79. } else {
  80. copy.segments.pop_back();
  81. }
  82. }
  83. return Servlet::ptr();
  84. }
  85. void
  86. ServletDispatcher::registerServlet(const URI &uri,
  87. const ServletOrCreator &servlet)
  88. {
  89. MORDOR_ASSERT(!uri.authority.userinfoDefined());
  90. MORDOR_ASSERT(!uri.queryDefined());
  91. MORDOR_ASSERT(!uri.fragmentDefined());
  92. URI copy(uri);
  93. copy.normalize();
  94. ServletPathMap * vhost = NULL;
  95. if (m_enableWildcard && isWildcardPath(copy.path))
  96. vhost = &(m_servlets[copy.authority].second);
  97. else
  98. vhost = &(m_servlets[copy.authority].first);
  99. MORDOR_ASSERT(vhost->find(copy.path) == vhost->end());
  100. (*vhost)[copy.path] = servlet;
  101. }
  102. bool
  103. ServletDispatcher::wildcardPathMatch(const URI::Path &wildPath, const URI::Path &path)
  104. {
  105. if (path.segments.size() != wildPath.segments.size())
  106. return false;
  107. for (size_t i = 0; i < path.segments.size(); ++i) {
  108. if (wildPath.segments[i] == "*")
  109. continue;
  110. if (wildPath.segments[i] != path.segments[i])
  111. return false;
  112. }
  113. return true;
  114. }
  115. bool
  116. ServletDispatcher::isWildcardPath(const URI::Path &path)
  117. {
  118. for (std::vector<std::string>::const_iterator it=path.segments.begin();
  119. it!=path.segments.end(); ++it) {
  120. if (*it == "*") return true;
  121. }
  122. return false;
  123. }
  124. }}