Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/beast2
8 : //
9 :
10 : #include <boost/beast2/server/serve_redirect.hpp>
11 : #include <boost/http_proto/file_source.hpp>
12 : #include <boost/http_proto/response.hpp>
13 : #include <boost/http_proto/string_body.hpp>
14 : #include <boost/url/url.hpp>
15 : #include <boost/url/authority_view.hpp>
16 : #include <boost/url/grammar/ci_string.hpp>
17 : #include <ctime>
18 : #include <iomanip>
19 : #include <sstream>
20 : #include <string>
21 :
22 : #include <iostream>
23 :
24 : namespace boost {
25 : namespace beast2 {
26 :
27 : //------------------------------------------------
28 :
29 : /// Returns the current system time formatted as an HTTP-date per RFC 9110 §5.6.7.
30 : /// Example: "Sat, 11 Oct 2025 02:12:34 GMT"
31 : static
32 : std::string
33 0 : make_http_date()
34 : {
35 : using namespace std;
36 :
37 : // Get current time in UTC
38 0 : std::time_t t = std::time(nullptr);
39 0 : std::tm tm_utc{};
40 : #if defined(_WIN32)
41 : gmtime_s(&tm_utc, &t);
42 : #else
43 0 : gmtime_r(&t, &tm_utc);
44 : #endif
45 :
46 0 : char const* wkday[] = {
47 : "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
48 : };
49 0 : char const* month[] = {
50 : "Jan", "Feb", "Mar", "Apr", "May", "Jun",
51 : "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
52 : };
53 :
54 : // Format strictly according to RFC 9110 (fixed-width, English locale)
55 : char buf[40];
56 0 : std::snprintf(
57 : buf, sizeof(buf),
58 : "%s, %02d %s %04d %02d:%02d:%02d GMT",
59 0 : wkday[tm_utc.tm_wday],
60 : tm_utc.tm_mday,
61 0 : month[tm_utc.tm_mon],
62 0 : tm_utc.tm_year + 1900,
63 : tm_utc.tm_hour,
64 : tm_utc.tm_min,
65 : tm_utc.tm_sec);
66 :
67 0 : return std::string(buf);
68 : }
69 :
70 : static
71 : void
72 0 : prepare_error(
73 : http_proto::response& res,
74 : std::string& body,
75 : http_proto::status code,
76 : http_proto::request_base const& req)
77 : {
78 0 : res.set_start_line(code, req.version());
79 0 : res.append(http_proto::field::server, "boost");
80 0 : res.append(http_proto::field::date, make_http_date());
81 0 : res.append(http_proto::field::cache_control, "no-store");
82 0 : res.append(http_proto::field::content_type, "text/html");
83 0 : res.append(http_proto::field::content_language, "en");
84 :
85 : // format the numeric code followed by the reason string
86 : auto title = std::to_string(
87 : static_cast<std::underlying_type<
88 0 : http_proto::status>::type>(code));
89 0 : title.push_back(' ');
90 0 : title.append( res.reason() );
91 :
92 0 : std::ostringstream ss;
93 : ss <<
94 : "<HTML>"
95 : "<HEAD>"
96 : "<TITLE>" << title << "</TITLE>"
97 : "</HEAD>\n"
98 : "<BODY>"
99 : "<H1>" << title << "</H1>"
100 : "</BODY>"
101 0 : "</HTML>"
102 : ;
103 0 : body = ss.str();
104 0 : }
105 :
106 : auto
107 0 : serve_redirect::
108 : operator()(
109 : Request& req,
110 : Response& res) const ->
111 : system::error_code
112 : {
113 0 : std::string body;
114 0 : prepare_error(res.m, body,
115 : http_proto::status::moved_permanently, req.m);
116 0 : urls::url u1(req.m.target());
117 0 : u1.set_scheme_id(urls::scheme::https);
118 0 : u1.set_host_address("localhost"); // VFALCO WTF IS THIS!
119 0 : res.m.append(http_proto::field::location, u1.buffer());
120 0 : res.sr.start(res.m,
121 0 : http_proto::string_body( std::move(body)));
122 0 : return {};
123 0 : }
124 :
125 : } // beast2
126 : } // boost
127 :
|