summaryrefslogtreecommitdiffhomepage
path: root/response.cpp
blob: 78368f6031bf3dbacdb6a7954a425df78c10ff0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "response.h"
#include "file.h"

namespace {

// Append an HTTP rel-path to a local filesystem path.
// The returned path is normalized for the platform.
std::string
path_cat(
    beast::string_view base,
    beast::string_view path)
{
    if(base.empty())
        return std::string(path);
    std::string result(base);
#ifdef BOOST_MSVC
    char constexpr path_separator = '\\';
    if(result.back() == path_separator)
        result.resize(result.size() - 1);
    result.append(path.data(), path.size());
    for(auto& c : result)
        if(c == '/')
            c = path_separator;
#else
    char constexpr path_separator = '/';
    if(result.back() == path_separator)
        result.resize(result.size() - 1);
    result.append(path.data(), path.size());
#endif
    return result;
}

}

http_exception::http_exception(std::string message): m_message(message)
{
}

const char* http_exception::what() const noexcept
{
 return m_message.data();
}

bad_request_exception::bad_request_exception(std::string message): http_exception(message)
{
}

not_found_exception::not_found_exception(std::string message): http_exception(message)
{
}

server_error_exception::server_error_exception(std::string message): http_exception(message)
{
}

std::string extend_index_html(std::string path)
{
 if (path.size() && path.back() == '/')
  path.append("index.html");
 return path;
}

std::string generate_response(http::request<http::string_body>& req, const Config& config, const Socket& socket)
{
 // Make sure we can handle the method
 if( req.method() != http::verb::get &&
     req.method() != http::verb::head)
  throw bad_request_exception("Unknown HTTP-method");

 // Request path must be absolute and not contain "..".
 if( req.target().empty() ||
     req.target()[0] != '/' ||
     req.target().find("..") != beast::string_view::npos)
  throw bad_request_exception("Illegal request-target");

 // Build the path to the requested file
 std::string host{req["host"]}; // TODO: just use string_view
 std::string target{req.target()};
 std::string path = path_cat(config.DocRoot(socket, host, target), extend_index_html(std::string(req.target())));

 std::string result;
 try {
  result = File::getFile(path);
 } catch (const std::runtime_error& ex) {
  throw not_found_exception(std::string(req.target()));
 } catch (const std::exception& ex) {
  throw server_error_exception(ex.what());
 }

 return result;
}