Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPWebRequestController.h"
24 : #include "SPWebHostController.h"
25 : #include "SPWebRequest.h"
26 : #include "SPWebInputFilter.h"
27 : #include "SPWebHost.h"
28 : #include "SPWebRoot.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::web {
31 :
32 0 : RequestController::~RequestController() { }
33 :
34 3125 : RequestController::RequestController(pool_t *pool, RequestInfo &&info)
35 3125 : : _pool(pool), _info(move(info)) {
36 :
37 3125 : }
38 :
39 3125 : bool RequestController::init() {
40 3125 : auto str = _info.url.query;
41 3125 : if (str.is('(')) {
42 600 : _info.queryData = data::serenity::read<Interface>(str);
43 : }
44 3125 : if (!str.empty()) {
45 500 : if (str.is('?') || str.is('&')) {
46 0 : ++ str;
47 : }
48 500 : auto d = UrlView::parseArgs<Interface>(str, 100_KiB);
49 500 : if (_info.queryData.empty()) {
50 500 : _info.queryData = std::move(d);
51 : } else {
52 0 : for (auto &it : d.asDict()) {
53 0 : if (!_info.queryData.hasValue(it.first)) {
54 0 : _info.queryData.setValue(std::move(it.second), it.first);
55 : }
56 : }
57 : }
58 500 : }
59 :
60 3125 : _info.queryPath = makeSpanView(UrlView::parsePath<Interface>(_info.url.path)).pdup(_pool);
61 :
62 3125 : auto h = getRequestHeader("accept");
63 3125 : if (!h.empty()) {
64 3100 : string::split(h, ",", [&, this] (StringView v) {
65 3100 : float q = 1.0f;
66 3100 : auto val = v.readUntil<StringView::Chars<';'>>();
67 3100 : if (v.starts_with(";q=")) {
68 0 : v += 3;
69 0 : q = v.readFloat().get(1.0f);
70 : }
71 3100 : val.trimChars<StringView::WhiteSpace>();
72 3100 : _acceptList.emplace_back(pair(val, q));
73 3100 : });
74 :
75 3100 : std::stable_sort(_acceptList.begin(), _acceptList.end(), [] (const Pair<StringView, float> &l, const Pair<StringView, float> &r) {
76 0 : return l.second < r.second;
77 : });
78 : }
79 :
80 3125 : return true;
81 : }
82 :
83 3100 : void RequestController::finalize() { }
84 :
85 2600 : float RequestController::isAcceptable(StringView name) const {
86 5200 : for (auto &it : _acceptList) {
87 2600 : if (it.first == name) {
88 0 : return it.second;
89 : }
90 : }
91 2600 : return 0.0f;
92 : }
93 :
94 3125 : void RequestController::bind(HostController *host) {
95 3125 : _host = host;
96 3125 : _info.documentRoot = _host->getHostInfo().documentRoot;
97 3125 : }
98 :
99 525 : bool RequestController::isSecureAuthAllowed() const {
100 525 : return Host(_host).isSecureAuthAllowed(Request(const_cast<RequestController *>(this)));
101 : }
102 :
103 5900 : db::Adapter RequestController::acquireDatabase() {
104 5900 : if (!_database) {
105 2850 : _database = Host(_host).acquireDbForRequest(this);
106 : }
107 5900 : return db::Adapter(_database, _host->getRoot());
108 : }
109 :
110 650 : InputFilter *RequestController::makeInputFilter(InputFilterAccept accept) {
111 1300 : return perform([&, this] {
112 650 : return new (_pool) InputFilter(Request(this), accept);
113 1300 : }, _pool, config::TAG_REQUEST, this);
114 : }
115 :
116 650 : void RequestController::setInputFilter(InputFilter *f) {
117 650 : _filter = f;
118 650 : }
119 :
120 450 : Value RequestController::getDefaultResult() {
121 450 : Value ret;
122 450 : ret.setBool(false, "OK");
123 450 : ret.setInteger(_info.requestTime.toMicros(), "date");
124 450 : ret.setInteger(toInt(_info.status), "status");
125 450 : ret.setString(_info.statusLine, "message");
126 :
127 : #if DEBUG
128 450 : if (!_debug.empty()) {
129 25 : ret.setArray(std::move(_debug), "debug");
130 : }
131 : #endif
132 450 : if (!_errors.empty()) {
133 25 : ret.setArray(std::move(_errors), "errors");
134 : }
135 :
136 450 : return ret;
137 0 : }
138 :
139 50 : void RequestController::pushErrorMessage(Value &&val) {
140 50 : _errors.emplace_back(std::move(val));
141 50 : }
142 :
143 25 : void RequestController::pushDebugMessage(Value &&val) {
144 25 : _debug.emplace_back(std::move(val));
145 25 : }
146 :
147 : }
|