1 #pragma once
2 
3 #include "error_messages.hpp"
4 #include "utility.hpp"
5 
6 #include <app.hpp>
7 #include <http_request.hpp>
8 #include <http_response.hpp>
9 #include <schemas.hpp>
10 
11 #include <string>
12 
13 namespace redfish
14 {
15 
16 inline void redfishGet(App& app, const crow::Request& req,
17                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
18 {
19     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
20     {
21         return;
22     }
23     asyncResp->res.jsonValue["v1"] = "/redfish/v1/";
24 }
25 
26 inline void redfish404(App& app, const crow::Request& req,
27                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
28                        const std::string& path)
29 {
30     asyncResp->res.addHeader(boost::beast::http::field::allow, "");
31 
32     // If we fall to this route, we didn't have a more specific route, so return
33     // 404
34     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
35     {
36         return;
37     }
38 
39     BMCWEB_LOG_ERROR << "404 on path " << path;
40 
41     boost::urls::string_value name = req.urlView.segments().back();
42     std::string_view nameStr(name.data(), name.size());
43     // Note, if we hit the wildcard route, we don't know the "type" the user was
44     // actually requesting, but giving them a return with an empty string is
45     // still better than nothing.
46     messages::resourceNotFound(asyncResp->res, "", nameStr);
47 }
48 
49 inline void
50     jsonSchemaIndexGet(App& app, const crow::Request& req,
51                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
52 {
53     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
54     {
55         return;
56     }
57     nlohmann::json& json = asyncResp->res.jsonValue;
58     json["@odata.id"] = "/redfish/v1/JsonSchemas";
59     json["@odata.context"] =
60         "/redfish/v1/$metadata#JsonSchemaFileCollection.JsonSchemaFileCollection";
61     json["@odata.type"] = "#JsonSchemaFileCollection.JsonSchemaFileCollection";
62     json["Name"] = "JsonSchemaFile Collection";
63     json["Description"] = "Collection of JsonSchemaFiles";
64     nlohmann::json::array_t members;
65     for (const std::string_view schema : schemas)
66     {
67         nlohmann::json::object_t member;
68         member["@odata.id"] = crow::utility::urlFromPieces(
69             "redfish", "v1", "JsonSchemas", schema);
70         members.push_back(std::move(member));
71     }
72     json["Members"] = std::move(members);
73     json["Members@odata.count"] = schemas.size();
74 }
75 
76 inline void jsonSchemaGet(App& app, const crow::Request& req,
77                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
78                           const std::string& schema)
79 {
80     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
81     {
82         return;
83     }
84 
85     if (std::find(schemas.begin(), schemas.end(), schema) == schemas.end())
86     {
87         messages::resourceNotFound(asyncResp->res,
88                                    "JsonSchemaFile.JsonSchemaFile", schema);
89         return;
90     }
91 
92     nlohmann::json& json = asyncResp->res.jsonValue;
93     json["@odata.context"] =
94         "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile";
95     json["@odata.id"] =
96         crow::utility::urlFromPieces("redfish", "v1", "JsonSchemas", schema);
97     json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile";
98     json["Name"] = schema + " Schema File";
99     json["Description"] = schema + " Schema File Location";
100     json["Id"] = schema;
101     std::string schemaName = "#";
102     schemaName += schema;
103     schemaName += ".";
104     schemaName += schema;
105     json["Schema"] = std::move(schemaName);
106     constexpr std::array<std::string_view, 1> languages{"en"};
107     json["Languages"] = languages;
108     json["Languages@odata.count"] = languages.size();
109 
110     nlohmann::json::array_t locationArray;
111     nlohmann::json::object_t locationEntry;
112     locationEntry["Language"] = "en";
113     locationEntry["PublicationUri"] =
114         "http://redfish.dmtf.org/schemas/v1/" + schema + ".json";
115     locationEntry["Uri"] = crow::utility::urlFromPieces(
116         "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json");
117 
118     locationArray.emplace_back(locationEntry);
119 
120     json["Location"] = std::move(locationArray);
121     json["Location@odata.count"] = 1;
122 }
123 
124 inline void requestRoutesRedfish(App& app)
125 {
126     BMCWEB_ROUTE(app, "/redfish/")
127         .methods(boost::beast::http::verb::get)(
128             std::bind_front(redfishGet, std::ref(app)));
129 
130     BMCWEB_ROUTE(app, "/redfish/<path>")
131     (std::bind_front(redfish404, std::ref(app)));
132 
133     BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/")
134         .methods(boost::beast::http::verb::get)(
135             std::bind_front(jsonSchemaGet, std::ref(app)));
136 
137     BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/")
138         .methods(boost::beast::http::verb::get)(
139             std::bind_front(jsonSchemaIndexGet, std::ref(app)));
140 }
141 
142 } // namespace redfish
143