blob: f2ac6e40b0b11328660eedc38e630a39900b84d1 [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 Williamsbd79bce2024-08-16 15:22:20 -040055 std::string_view tag =
56 url.substr(urlSegmentIndex, 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
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400242 static_assert(
243 std::numeric_limits<decltype(code)>::max() < decodingData.size());
Jonathan Doman5beaf842020-08-14 11:23:33 -0700244 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 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400287 output += static_cast<char>(
288 ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700289 }
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{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400313inline boost::urls::url appendUrlPieces(
314 boost::urls::url& url, const std::initializer_list<std::string_view> args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700315{
Ed Tanous26ccae32023-02-16 10:28:44 -0800316 for (std::string_view arg : args)
Ed Tanouseae855c2021-10-26 11:26:02 -0700317 {
318 url.segments().push_back(arg);
319 }
320 return url;
321}
Willy Tuc6bcedc2022-09-27 05:36:59 +0000322
Ed Tanouseae855c2021-10-26 11:26:02 -0700323} // namespace details
324
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700325class OrMorePaths
326{};
327
Ed Tanouseae855c2021-10-26 11:26:02 -0700328template <typename... AV>
Willy Tuc6bcedc2022-09-27 05:36:59 +0000329inline void appendUrlPieces(boost::urls::url& url, const AV... args)
330{
331 details::appendUrlPieces(url, {args...});
332}
333
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100334namespace details
335{
336
337// std::reference_wrapper<std::string> - extracts segment to variable
338// std::string_view - checks if segment is equal to variable
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700339using UrlSegment = std::variant<std::reference_wrapper<std::string>,
340 std::string_view, OrMorePaths>;
341
342enum class UrlParseResult
343{
344 Continue,
345 Fail,
346 Done,
347};
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100348
349class UrlSegmentMatcherVisitor
350{
351 public:
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700352 UrlParseResult operator()(std::string& output)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100353 {
Ed Tanous079360a2022-06-29 10:05:19 -0700354 output = segment;
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700355 return UrlParseResult::Continue;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100356 }
357
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700358 UrlParseResult operator()(std::string_view expected)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100359 {
Ed Tanous079360a2022-06-29 10:05:19 -0700360 if (segment == expected)
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700361 {
362 return UrlParseResult::Continue;
363 }
364 return UrlParseResult::Fail;
365 }
366
367 UrlParseResult operator()(OrMorePaths /*unused*/)
368 {
369 return UrlParseResult::Done;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100370 }
371
Ed Tanous079360a2022-06-29 10:05:19 -0700372 explicit UrlSegmentMatcherVisitor(std::string_view segmentIn) :
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100373 segment(segmentIn)
374 {}
375
376 private:
Ed Tanous079360a2022-06-29 10:05:19 -0700377 std::string_view segment;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100378};
379
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700380inline bool readUrlSegments(const boost::urls::url_view_base& url,
Ed Tanous5be2b142024-03-27 15:27:04 -0700381 std::initializer_list<UrlSegment> segments)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100382{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700383 const boost::urls::segments_view& urlSegments = url.segments();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100384
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700385 if (!urlSegments.is_absolute())
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100386 {
387 return false;
388 }
389
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700390 boost::urls::segments_view::const_iterator it = urlSegments.begin();
391 boost::urls::segments_view::const_iterator end = urlSegments.end();
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100392
393 for (const auto& segment : segments)
394 {
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700395 if (it == end)
396 {
397 // If the request ends with an "any" path, this was successful
398 return std::holds_alternative<OrMorePaths>(segment);
399 }
400 UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
401 if (res == UrlParseResult::Done)
402 {
403 return true;
404 }
405 if (res == UrlParseResult::Fail)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100406 {
407 return false;
408 }
409 it++;
410 }
Carson Labrado4c30e222022-06-24 22:16:00 +0000411
412 // There will be an empty segment at the end if the URI ends with a "/"
413 // e.g. /redfish/v1/Chassis/
414 if ((it != end) && urlSegments.back().empty())
415 {
416 it++;
417 }
Ed Tanous7f8d8fa2022-08-19 07:00:38 -0700418 return it == end;
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100419}
420
421} // namespace details
422
423template <typename... Args>
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700424inline bool readUrlSegments(const boost::urls::url_view_base& url,
425 Args&&... args)
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100426{
Ed Tanous39662a32023-02-06 15:09:46 -0800427 return details::readUrlSegments(url, {std::forward<Args>(args)...});
Szymon Dompkeca1600c2022-03-03 14:42:52 +0100428}
429
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700430inline boost::urls::url
431 replaceUrlSegment(const boost::urls::url_view_base& urlView,
432 const uint replaceLoc, std::string_view newSegment)
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000433{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700434 const boost::urls::segments_view& urlSegments = urlView.segments();
Carson Labrado1c0bb5c2022-05-18 00:12:52 +0000435 boost::urls::url url("/");
436
437 if (!urlSegments.is_absolute())
438 {
439 return url;
440 }
441
442 boost::urls::segments_view::iterator it = urlSegments.begin();
443 boost::urls::segments_view::iterator end = urlSegments.end();
444
445 for (uint idx = 0; it != end; it++, idx++)
446 {
447 if (idx == replaceLoc)
448 {
449 url.segments().push_back(newSegment);
450 }
451 else
452 {
453 url.segments().push_back(*it);
454 }
455 }
456
457 return url;
458}
459
Ed Tanousa716aa72023-08-01 11:35:53 -0700460inline void setProtocolDefaults(boost::urls::url& url,
461 std::string_view protocol)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800462{
Ed Tanousa716aa72023-08-01 11:35:53 -0700463 if (url.has_scheme())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800464 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700465 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800466 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700467 if (protocol == "Redfish" || protocol.empty())
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800468 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700469 if (url.port_number() == 443)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800470 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700471 url.set_scheme("https");
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800472 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700473 if (url.port_number() == 80)
474 {
Ed Tanous25b54db2024-04-17 15:40:31 -0700475 if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
Ed Tanousa716aa72023-08-01 11:35:53 -0700476 {
477 url.set_scheme("http");
478 }
479 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800480 }
Ed Tanousa716aa72023-08-01 11:35:53 -0700481 else if (protocol == "SNMPv2c")
Chicago Duan3d307082020-11-26 14:12:12 +0800482 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700483 url.set_scheme("snmp");
Chicago Duan3d307082020-11-26 14:12:12 +0800484 }
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800485}
486
Ed Tanousa716aa72023-08-01 11:35:53 -0700487inline void setPortDefaults(boost::urls::url& url)
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800488{
489 uint16_t port = url.port_number();
490 if (port != 0)
491 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700492 return;
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800493 }
494
495 // If the user hasn't explicitly stated a port, pick one explicitly for them
496 // based on the protocol defaults
497 if (url.scheme() == "http")
498 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700499 url.set_port_number(80);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800500 }
501 if (url.scheme() == "https")
502 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700503 url.set_port_number(443);
Ed Tanouseb1c47d2022-02-09 11:47:27 -0800504 }
Chicago Duan3d307082020-11-26 14:12:12 +0800505 if (url.scheme() == "snmp")
506 {
Ed Tanousa716aa72023-08-01 11:35:53 -0700507 url.set_port_number(162);
Chicago Duan3d307082020-11-26 14:12:12 +0800508 }
Ed Tanous11baefe2022-02-09 12:14:12 -0800509}
510
Ed Tanous1abe55e2018-09-05 08:30:59 -0700511} // namespace utility
512} // namespace crow
Ed Tanous71f2db72022-05-25 12:28:09 -0700513
514namespace nlohmann
515{
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700516template <std::derived_from<boost::urls::url_view_base> URL>
517struct adl_serializer<URL>
Ed Tanous71f2db72022-05-25 12:28:09 -0700518{
519 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanous4a7fbef2024-04-06 16:03:49 -0700520 static void to_json(json& j, const URL& url)
Ed Tanous71f2db72022-05-25 12:28:09 -0700521 {
Ed Tanous079360a2022-06-29 10:05:19 -0700522 j = url.buffer();
Ed Tanous71f2db72022-05-25 12:28:09 -0700523 }
524};
525} // namespace nlohmann