blob: 41b48e4b92bf90e555a1a263edb96ed7dd2843b5 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07002
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "bmcweb_config.h"
4
Ed Tanousc867a832022-03-10 14:17:00 -08005#include <boost/callable_traits.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07006#include <boost/url/parse.hpp>
Ed Tanouseae855c2021-10-26 11:26:02 -07007#include <boost/url/url.hpp>
Ed Tanous079360a2022-06-29 10:05:19 -07008#include <boost/url/url_view.hpp>
Ed Tanous4a7fbef2024-04-06 16:03:49 -07009#include <boost/url/url_view_base.hpp>
Ed Tanous71f2db72022-05-25 12:28:09 -070010#include <nlohmann/json.hpp>
Nan Zhou1d8782e2021-11-29 22:23:18 -080011
Ed Tanous9ea15c32022-01-04 14:18:22 -080012#include <array>
Ed Tanous74849be2021-02-05 09:47:47 -080013#include <chrono>
Ed Tanousc715ec22022-03-10 15:38:01 -080014#include <cstddef>
Ed Tanous7045c8d2017-04-03 10:04:37 -070015#include <cstdint>
Ed Tanous9ea15c32022-01-04 14:18:22 -080016#include <ctime>
Ed Tanous7045c8d2017-04-03 10:04:37 -070017#include <functional>
Ed Tanous9896eae2022-07-23 15:07:33 -070018#include <iomanip>
Ed Tanous9ea15c32022-01-04 14:18:22 -080019#include <limits>
Ed Tanous7045c8d2017-04-03 10:04:37 -070020#include <stdexcept>
21#include <string>
Ed Tanous9ea15c32022-01-04 14:18:22 -080022#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070023#include <tuple>
Ed Tanous9ea15c32022-01-04 14:18:22 -080024#include <type_traits>
25#include <utility>
Szymon Dompkeca1600c2022-03-03 14:42:52 +010026#include <variant>
Ed Tanous7045c8d2017-04-03 10:04:37 -070027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace crow
29{
Ed Tanous47488a92023-06-26 18:19:33 -070030namespace utility
Ed Tanous1abe55e2018-09-05 08:30:59 -070031{
Ed Tanous7045c8d2017-04-03 10:04:37 -070032
Ed Tanous9de65b32024-03-27 13:34:40 -070033constexpr uint64_t getParameterTag(std::string_view url)
Ed Tanous1abe55e2018-09-05 08:30:59 -070034{
Ed Tanous1c30e502022-03-08 18:02:24 -080035 uint64_t tagValue = 0;
36 size_t urlSegmentIndex = std::string_view::npos;
Ed Tanousb00dcc22021-02-23 12:52:50 -080037
Ed Tanous1c30e502022-03-08 18:02:24 -080038 for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++)
39 {
40 char character = url[urlIndex];
41 if (character == '<')
42 {
43 if (urlSegmentIndex != std::string_view::npos)
44 {
45 return 0;
46 }
47 urlSegmentIndex = urlIndex;
48 }
49 if (character == '>')
50 {
51 if (urlSegmentIndex == std::string_view::npos)
52 {
53 return 0;
54 }
Patrick Williams89492a12023-05-10 07:51:34 -050055 std::string_view tag = url.substr(urlSegmentIndex,
56 urlIndex + 1 - urlSegmentIndex);
Ed Tanous1c30e502022-03-08 18:02:24 -080057
Ed Tanous1c30e502022-03-08 18:02:24 -080058 if (tag == "<str>" || tag == "<string>")
59 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070060 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080061 }
62 if (tag == "<path>")
63 {
Ed Tanousd9e89df2024-03-27 14:08:59 -070064 tagValue++;
Ed Tanous1c30e502022-03-08 18:02:24 -080065 }
Ed Tanous1c30e502022-03-08 18:02:24 -080066 urlSegmentIndex = std::string_view::npos;
67 }
68 }
69 if (urlSegmentIndex != std::string_view::npos)
Ed Tanous988403c2020-08-24 11:29:49 -070070 {
71 return 0;
72 }
Ed Tanous1c30e502022-03-08 18:02:24 -080073 return tagValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070074}
Ed Tanous7045c8d2017-04-03 10:04:37 -070075
Ed Tanousee192c02023-12-13 10:49:58 -080076class Base64Encoder
Adriana Kobylakd830ff52021-01-27 14:15:27 -060077{
Ed Tanousee192c02023-12-13 10:49:58 -080078 char overflow1 = '\0';
79 char overflow2 = '\0';
80 uint8_t overflowCount = 0;
81
82 constexpr static std::array<char, 64> key = {
Adriana Kobylakd830ff52021-01-27 14:15:27 -060083 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
84 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
85 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
86 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
87 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
88
Ed Tanousee192c02023-12-13 10:49:58 -080089 // Takes 3 ascii chars, and encodes them as 4 base64 chars
90 static void encodeTriple(char first, char second, char third,
91 std::string& output)
Adriana Kobylakd830ff52021-01-27 14:15:27 -060092 {
Ed Tanous543f4402022-01-06 13:12:53 -080093 size_t keyIndex = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -060094
Ed Tanousee192c02023-12-13 10:49:58 -080095 keyIndex = static_cast<size_t>(first & 0xFC) >> 2;
96 output += key[keyIndex];
Adriana Kobylakd830ff52021-01-27 14:15:27 -060097
Ed Tanousee192c02023-12-13 10:49:58 -080098 keyIndex = static_cast<size_t>(first & 0x03) << 4;
99 keyIndex += static_cast<size_t>(second & 0xF0) >> 4;
100 output += key[keyIndex];
101
102 keyIndex = static_cast<size_t>(second & 0x0F) << 2;
103 keyIndex += static_cast<size_t>(third & 0xC0) >> 6;
104 output += key[keyIndex];
105
106 keyIndex = static_cast<size_t>(third & 0x3F);
107 output += key[keyIndex];
108 }
109
110 public:
111 // Accepts a partial string to encode, and writes the encoded characters to
112 // the output stream. requires subsequently calling finalize to complete
113 // stream.
114 void encode(std::string_view data, std::string& output)
115 {
116 // Encode the last round of overflow chars first
117 if (overflowCount == 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600118 {
Ed Tanousee192c02023-12-13 10:49:58 -0800119 if (!data.empty())
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600120 {
Ed Tanousee192c02023-12-13 10:49:58 -0800121 encodeTriple(overflow1, overflow2, data[0], output);
122 overflowCount = 0;
123 data.remove_prefix(1);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600124 }
Ed Tanousee192c02023-12-13 10:49:58 -0800125 }
126 else if (overflowCount == 1)
127 {
128 if (data.size() >= 2)
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600129 {
Ed Tanousee192c02023-12-13 10:49:58 -0800130 encodeTriple(overflow1, data[0], data[1], output);
131 overflowCount = 0;
132 data.remove_prefix(2);
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600133 }
134 }
Ed Tanousee192c02023-12-13 10:49:58 -0800135
136 while (data.size() >= 3)
137 {
138 encodeTriple(data[0], data[1], data[2], output);
139 data.remove_prefix(3);
140 }
141
142 if (!data.empty() && overflowCount == 0)
143 {
144 overflow1 = data[0];
145 overflowCount++;
146 data.remove_prefix(1);
147 }
148
149 if (!data.empty() && overflowCount == 1)
150 {
151 overflow2 = data[0];
152 overflowCount++;
153 data.remove_prefix(1);
154 }
155 }
156
157 // Completes a base64 output, by writing any MOD(3) characters to the
158 // output, as well as any required trailing =
159 void finalize(std::string& output)
160 {
161 if (overflowCount == 0)
162 {
163 return;
164 }
165 size_t keyIndex = static_cast<size_t>(overflow1 & 0xFC) >> 2;
166 output += key[keyIndex];
167
168 keyIndex = static_cast<size_t>(overflow1 & 0x03) << 4;
169 if (overflowCount == 2)
170 {
171 keyIndex += static_cast<size_t>(overflow2 & 0xF0) >> 4;
172 output += key[keyIndex];
173 keyIndex = static_cast<size_t>(overflow2 & 0x0F) << 2;
174 output += key[keyIndex];
175 }
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600176 else
177 {
Ed Tanousee192c02023-12-13 10:49:58 -0800178 output += key[keyIndex];
179 output += '=';
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600180 }
Ed Tanousee192c02023-12-13 10:49:58 -0800181 output += '=';
182 overflowCount = 0;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600183 }
184
Ed Tanousee192c02023-12-13 10:49:58 -0800185 // Returns the required output buffer in characters for an input of size
186 // inputSize
187 static size_t constexpr encodedSize(size_t inputSize)
188 {
189 // Base64 encodes 3 character blocks as 4 character blocks
190 // With a possibility of 2 trailing = characters
191 return (inputSize + 2) / 3 * 4;
192 }
193};
194
195inline std::string base64encode(std::string_view data)
196{
197 // Encodes a 3 character stream into a 4 character stream
198 std::string out;
199 Base64Encoder base64;
200 out.reserve(Base64Encoder::encodedSize(data.size()));
201 base64.encode(data, out);
202 base64.finalize(out);
203 return out;
Adriana Kobylakd830ff52021-01-27 14:15:27 -0600204}
205
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100206// TODO this is temporary and should be deleted once base64 is refactored out of
207// crow
Ed Tanous26ccae32023-02-16 10:28:44 -0800208inline bool base64Decode(std::string_view input, std::string& output)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700209{
Ed Tanous271584a2019-07-09 16:24:22 -0700210 static const char nop = static_cast<char>(-1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211 // See note on encoding_data[] in above function
Jonathan Doman5beaf842020-08-14 11:23:33 -0700212 static const std::array<char, 256> decodingData = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
214 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
215 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
216 nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59,
217 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4,
218 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
219 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26,
220 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
221 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop,
222 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
223 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
224 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
225 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
226 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
227 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
228 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
229 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
230 nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
231 nop, nop, nop, nop};
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100232
Ed Tanous1abe55e2018-09-05 08:30:59 -0700233 size_t inputLength = input.size();
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100234
Ed Tanous1abe55e2018-09-05 08:30:59 -0700235 // allocate space for output string
236 output.clear();
237 output.reserve(((inputLength + 2) / 3) * 4);
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100238
Jonathan Doman5beaf842020-08-14 11:23:33 -0700239 auto getCodeValue = [](char c) {
240 auto code = static_cast<unsigned char>(c);
241 // Ensure we cannot index outside the bounds of the decoding array
242 static_assert(std::numeric_limits<decltype(code)>::max() <
243 decodingData.size());
244 return decodingData[code];
245 };
246
Ed Tanous1abe55e2018-09-05 08:30:59 -0700247 // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
Gunnar Millscaa3ce32020-07-08 14:46:53 -0500248 // dropping first two bits
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249 // and regenerate into 3 8-bits sequences
James Feist5a806642020-07-31 16:40:33 +0000250
Ed Tanous1abe55e2018-09-05 08:30:59 -0700251 for (size_t i = 0; i < inputLength; i++)
252 {
Ed Tanous543f4402022-01-06 13:12:53 -0800253 char base64code0 = 0;
254 char base64code1 = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700255 char base64code2 = 0; // initialized to 0 to suppress warnings
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100256
Jonathan Doman5beaf842020-08-14 11:23:33 -0700257 base64code0 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700258 if (base64code0 == nop)
259 { // non base64 character
260 return false;
261 }
262 if (!(++i < inputLength))
263 { // we need at least two input bytes for first
264 // byte output
265 return false;
266 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700267 base64code1 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700268 if (base64code1 == nop)
269 { // non base64 character
270 return false;
271 }
272 output +=
273 static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100274
Ed Tanous1abe55e2018-09-05 08:30:59 -0700275 if (++i < inputLength)
276 {
277 char c = input[i];
278 if (c == '=')
279 { // padding , end of input
280 return (base64code1 & 0x0f) == 0;
281 }
Jonathan Doman5beaf842020-08-14 11:23:33 -0700282 base64code2 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700283 if (base64code2 == nop)
284 { // non base64 character
285 return false;
286 }
287 output += static_cast<char>(((base64code1 << 4) & 0xf0) |
288 ((base64code2 >> 2) & 0x0f));
289 }
290
291 if (++i < inputLength)
292 {
293 char c = input[i];
294 if (c == '=')
295 { // padding , end of input
296 return (base64code2 & 0x03) == 0;
297 }
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700298 char base64code3 = getCodeValue(input[i]);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700299 if (base64code3 == nop)
300 { // non base64 character
301 return false;
302 }
303 output +=
304 static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
305 }
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100306 }
307
Ed Tanous1abe55e2018-09-05 08:30:59 -0700308 return true;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +0100309}
310
Ed Tanouseae855c2021-10-26 11:26:02 -0700311namespace details
312{
313inline boost::urls::url
Willy Tuc6bcedc2022-09-27 05:36:59 +0000314 appendUrlPieces(boost::urls::url& url,
315 const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700316{
Ed Tanous26ccae32023-02-16 10:28:44 -0800317 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700318 {
319 url.segments().push_back(arg);
320 }
321 return url;
322}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000323
Ed Tanouseae855c2021-10-26 11:26:02 -0700324} // namespace details
325
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700326class OrMorePaths
327{};
328
Ed Tanouseae855c2021-10-26 11:26:02 -0700329template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000330inline void appendUrlPieces(boost::urls::url& url, const AV... args)
331{
332 details::appendUrlPieces(url, {args...});
333}
334
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100335namespace details
336{
337
338// std::reference_wrapper<std::string> - extracts segment to variable
339// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700340using UrlSegment = std::variant<std::reference_wrapper<std::string>,
341 std::string_view, OrMorePaths>;
342
343enum class UrlParseResult
344{
345 Continue,
346 Fail,
347 Done,
348};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100349
350class UrlSegmentMatcherVisitor
351{
352 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700353 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100354 {
Ed Tanous079360a2022-06-29 10:05:19 -0700355 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700356 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100357 }
358
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700359 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100360 {
Ed Tanous079360a2022-06-29 10:05:19 -0700361 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700362 {
363 return UrlParseResult::Continue;
364 }
365 return UrlParseResult::Fail;
366 }
367
368 UrlParseResult operator()(OrMorePaths /*unused*/)
369 {
370 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100371 }
372
Ed Tanous079360a2022-06-29 10:05:19 -0700373 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100374 segment(segmentIn)
375 {}
376
377 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700378 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100379};
380
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700381inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700382 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100383{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700384 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100385
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700386 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100387 {
388 return false;
389 }
390
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700391 boost::urls::segments_view::const_iterator it = urlSegments.begin();
392 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100393
394 for (const auto& segment : segments)
395 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700396 if (it == end)
397 {
398 // If the request ends with an "any" path, this was successful
399 return std::holds_alternative<OrMorePaths>(segment);
400 }
401 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
402 if (res == UrlParseResult::Done)
403 {
404 return true;
405 }
406 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100407 {
408 return false;
409 }
410 it++;
411 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000412
413 // There will be an empty segment at the end if the URI ends with a "/"
414 // e.g. /redfish/v1/Chassis/
415 if ((it != end) && urlSegments.back().empty())
416 {
417 it++;
418 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700419 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100420}
421
422} // namespace details
423
424template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700425inline bool readUrlSegments(const boost::urls::url_view_base& url,
426 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100427{
Ed Tanous39662a32023-02-06 15:09:46 -0800428 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100429}
430
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700431inline boost::urls::url
432 replaceUrlSegment(const boost::urls::url_view_base& urlView,
433 const uint replaceLoc, std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000434{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700435 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000436 boost::urls::url url("/");
437
438 if (!urlSegments.is_absolute())
439 {
440 return url;
441 }
442
443 boost::urls::segments_view::iterator it = urlSegments.begin();
444 boost::urls::segments_view::iterator end = urlSegments.end();
445
446 for (uint idx = 0; it != end; it++, idx++)
447 {
448 if (idx == replaceLoc)
449 {
450 url.segments().push_back(newSegment);
451 }
452 else
453 {
454 url.segments().push_back(*it);
455 }
456 }
457
458 return url;
459}
460
Ed Tanousa716aa72023-08-01 11:35:53 -0700461inline void setProtocolDefaults(boost::urls::url& url,
462 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800463{
Ed Tanousa716aa72023-08-01 11:35:53 -0700464 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800465 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700466 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800467 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700468 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800469 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700470 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800471 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700472 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800473 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700474 if (url.port_number() == 80)
475 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700476 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700477 {
478 url.set_scheme("http");
479 }
480 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800481 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700482 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800483 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700484 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800485 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800486}
487
Ed Tanousa716aa72023-08-01 11:35:53 -0700488inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800489{
490 uint16_t port = url.port_number();
491 if (port != 0)
492 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700493 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800494 }
495
496 // If the user hasn't explicitly stated a port, pick one explicitly for them
497 // based on the protocol defaults
498 if (url.scheme() == "http")
499 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700500 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800501 }
502 if (url.scheme() == "https")
503 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700504 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800505 }
Chicago Duan3d307082020-11-26 14:12:12 +0800506 if (url.scheme() == "snmp")
507 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700508 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800509 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800510}
511
Ed Tanous1abe55e2018-09-05 08:30:59 -0700512} // namespace utility
513} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700514
515namespace nlohmann
516{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700517template <std::derived_from<boost::urls::url_view_base> URL>
518struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700519{
520 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700521 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700522 {
Ed Tanous079360a2022-06-29 10:05:19 -0700523 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700524 }
525};
526} // namespace nlohmann