Change UpdateService POST URI

As d01e32c3786f2fbbb70c9724a87cf979b4a06232 found, the Redfish
specification doesn't allow a direct POST handler on UpdateService.
Ideally clients would be following the specification, and relying on
the HttpPushUri as the spec requires, so we could simply make this
change.  Unfortunately, a quick polling of the community shows that a
significant number of instances, including the Redfish cheat sheet, and
the robot tests, have hardcoded the non-spec behavior.  This commit is
present to give a trap door to allow easier porting of this behavior to
the specification.

The old uri is left, and now returns a WARNING http field, indicating
that the uri is deprecated, in case clients have ignored the Redfish
specification.

Tested:
Ran firmware update instructions from
https://gerrit.openbmc-project.xyz/c/openbmc/docs/+/53664

Test gave the same result as previously.

/redfish/v1/UpdateService returns an HttpPushUri that matches the above.

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I7427f461d151c9460160b0b9b366dca5aefc49d5
diff --git a/meson.build b/meson.build
index 0ab48ff..d51d9b8 100644
--- a/meson.build
+++ b/meson.build
@@ -80,6 +80,7 @@
   'redfish-host-logger'                         : '-DBMCWEB_ENABLE_REDFISH_HOST_LOGGER',
   'redfish-new-powersubsystem-thermalsubsystem' : '-DBMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM',
   'redfish-provisioning-feature'                : '-DBMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE',
+  'redfish-post-to-old-updateservice'           : '-DBMCWEB_ENABLE_REDFISH_UPDATESERVICE_OLD_POST_URL',
   'redfish'                                     : '-DBMCWEB_ENABLE_REDFISH',
   'rest'                                        : '-DBMCWEB_ENABLE_DBUS_REST',
   'session-auth'                                : '-DBMCWEB_ENABLE_SESSION_AUTHENTICATION',
diff --git a/meson_options.txt b/meson_options.txt
index d943222..f2b4f37 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -214,6 +214,17 @@
 )
 
 option(
+    'redfish-post-to-old-updateservice',
+    type: 'feature',
+    value: 'enabled',
+    description: '''Allows POST to /redfish/v1/UpdateService, counter to
+                    the redfish specification.  Option provided to allow
+                    potential users to move away from using this endpoint.
+                    Option will be removed Q4 2022.'''
+)
+
+
+option(
     'https_port',
     type: 'integer',
     min: 1,
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 716904c..53ee1ad 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -580,8 +580,10 @@
             asyncResp->res.jsonValue["Description"] =
                 "Service for Software Update";
             asyncResp->res.jsonValue["Name"] = "Update Service";
+
             asyncResp->res.jsonValue["HttpPushUri"] =
-                "/redfish/v1/UpdateService";
+                "/redfish/v1/UpdateService/update";
+
             // UpdateService cannot be disabled
             asyncResp->res.jsonValue["ServiceEnabled"] = true;
             asyncResp->res.jsonValue["FirmwareInventory"]["@odata.id"] =
@@ -718,8 +720,31 @@
             }
         });
 
+// The "old" behavior of the update service URI causes redfish-service validator
+// failures when the Allow header is supported, given that in the spec,
+// UpdateService does not allow POST.  in openbmc, we unfortunately reused that
+// resource as our HttpPushUri as well.  A number of services, including the
+// openbmc tests, and documentation have hardcoded that erroneous API, instead
+// of relying on HttpPushUri as the spec requires.  This option will exist
+// temporarily to allow the old behavior until Q4 2022, at which time it will be
+// removed.
+#ifdef BMCWEB_ENABLE_REDFISH_UPDATESERVICE_OLD_POST_URL
     BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/")
         .privileges(redfish::privileges::postUpdateService)
+        .methods(
+            boost::beast::http::verb::
+                post)([&app](
+                          const crow::Request& req,
+                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+            asyncResp->res.addHeader(
+                boost::beast::http::field::warning,
+                "299 - \"POST to /redfish/v1/UpdateService is deprecated. Use "
+                "the value contained within HttpPushUri.\"");
+            handleUpdateServicePost(app, req, asyncResp);
+        });
+#endif
+    BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/update/")
+        .privileges(redfish::privileges::postUpdateService)
         .methods(boost::beast::http::verb::post)(
             std::bind_front(handleUpdateServicePost, std::ref(app)));
 }