[cpp-sp] branch main updated: Flesh out draft of SessionInitiator handler.

Scott Cantor cantor.2 at osu.edu
Tue Feb 4 20:37:33 UTC 2025


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=fe6a0c6f1488acf8656e93f046ff5fae1823cee2

The following commit(s) were added to refs/heads/main by this push:
     new fe6a0c6f Flesh out draft of SessionInitiator handler.
fe6a0c6f is described below

commit fe6a0c6f1488acf8656e93f046ff5fae1823cee2
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 4 15:37:22 2025 -0500

    Flesh out draft of SessionInitiator handler.
---
 Projects/vc22/shibsp.vcxproj                       |   1 -
 Projects/vc22/shibsp.vcxproj.filters               |   3 -
 shibsp/Agent.cpp                                   |   2 +-
 shibsp/exceptions.cpp                              |   6 +
 shibsp/exceptions.h                                |  11 +-
 shibsp/handler/AbstractHandler.h                   |  25 ++-
 shibsp/handler/SessionInitiator.h                  | 103 ----------
 shibsp/handler/impl/AbstractHandler.cpp            |  87 ++++++--
 .../handler/impl/DefaultHandlerConfiguration.cpp   |   2 +-
 shibsp/handler/impl/SessionInitiator.cpp           | 219 +++++++++++++--------
 shibsp/handler/impl/StatusHandler.cpp              |  22 +--
 shibsp/remoting/impl/AbstractRemotingService.cpp   |  10 +-
 12 files changed, 266 insertions(+), 225 deletions(-)

diff --git a/Projects/vc22/shibsp.vcxproj b/Projects/vc22/shibsp.vcxproj
index c768f594..5eeb86ef 100644
--- a/Projects/vc22/shibsp.vcxproj
+++ b/Projects/vc22/shibsp.vcxproj
@@ -45,7 +45,6 @@
     <ClInclude Include="..\..\shibsp\handler\LogoutInitiator.h" />
     <ClInclude Include="..\..\shibsp\handler\RemotedHandler.h" />
     <ClInclude Include="..\..\shibsp\handler\SecuredHandler.h" />
-    <ClInclude Include="..\..\shibsp\handler\SessionInitiator.h" />
     <ClInclude Include="..\..\shibsp\impl\StorageServiceSessionCache.h" />
     <ClInclude Include="..\..\shibsp\impl\XMLApplication.h" />
     <ClInclude Include="..\..\shibsp\impl\XMLServiceProvider.h" />
diff --git a/Projects/vc22/shibsp.vcxproj.filters b/Projects/vc22/shibsp.vcxproj.filters
index 03953740..b8d46d4b 100644
--- a/Projects/vc22/shibsp.vcxproj.filters
+++ b/Projects/vc22/shibsp.vcxproj.filters
@@ -135,9 +135,6 @@
     <ClInclude Include="..\..\shibsp\handler\SecuredHandler.h">
       <Filter>Header Files\Handler</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\shibsp\handler\SessionInitiator.h">
-      <Filter>Header Files\Handler</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\shibsp\io\GenericRequest.h">
       <Filter>Header Files\IO</Filter>
     </ClInclude>
diff --git a/shibsp/Agent.cpp b/shibsp/Agent.cpp
index 5c82e1a6..9436c0ab 100644
--- a/shibsp/Agent.cpp
+++ b/shibsp/Agent.cpp
@@ -25,8 +25,8 @@
 #include "AccessControl.h"
 #include "SPRequest.h"
 #include "attribute/Attribute.h"
+#include "handler/Handler.h"
 #include "handler/HandlerConfiguration.h"
-#include "handler/SessionInitiator.h"
 #include "logging/Category.h"
 #include "session/SessionCache.h"
 #include "util/Date.h"
diff --git a/shibsp/exceptions.cpp b/shibsp/exceptions.cpp
index e886e35f..b3cbd448 100644
--- a/shibsp/exceptions.cpp
+++ b/shibsp/exceptions.cpp
@@ -56,6 +56,12 @@ void agent_exception::setStatusCode(int code) noexcept
     m_status = code;
 }
 
+const char* agent_exception::getProperty(const char* name) const noexcept
+{
+    const auto& prop = m_props.find(name);
+    return prop != m_props.end() ? prop->second.c_str() : nullptr;
+}
+
 const unordered_map<string,string>& agent_exception::getProperties() const noexcept
 {
     return m_props;
diff --git a/shibsp/exceptions.h b/shibsp/exceptions.h
index 4257006f..fc80f47a 100644
--- a/shibsp/exceptions.h
+++ b/shibsp/exceptions.h
@@ -93,12 +93,21 @@ namespace shibsp {
         void setStatusCode(int code) noexcept;
 
         /**
-         * Gets the properties attacked to this exception.
+         * Gets the properties attached to this exception.
          * 
          * @return property map
          */
         const std::unordered_map<std::string,std::string>& getProperties() const noexcept;
 
+        /**
+         * Gets a specific property attached to this exception.
+         * 
+         * @param name property name
+         * 
+         * @return property value or null
+         */
+        const char* getProperty(const char* name) const noexcept;
+
         /**
          * Attach a set of named properties to the exception.
          * 
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index 73c193f1..5b473072 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -26,6 +26,7 @@
 #include <shibsp/util/BoostPropertySet.h>
 
 #include <string>
+#include <vector>
 #include <boost/property_tree/ptree_fwd.hpp>
 
 namespace shibsp {
@@ -47,13 +48,35 @@ namespace shibsp {
     {
     protected:
         /**
-         * Constructor
+         * Constructor.
          * 
          * @param pt    root of handler configuration
          * @param log   logging category to use
          */
         AbstractHandler(const boost::property_tree::ptree& pt, Category& log);
 
+        /**
+         * Wrap a request for remoting to hub.
+         * 
+         * @param request the request to remote
+         * @param headers names of request headers to remote
+         * 
+         * @return wrapped structure to add to remoted data
+         */
+        virtual DDF wrapRequest(
+            const SPRequest& request, const std::vector<std::string>& headers, bool sendBody=true
+            ) const;
+
+        /**
+         * Unwrap a response from the hub and play back to user agent.
+         * 
+         * @param request request to playback response into
+         * @param wrappedResponse wrapped response data
+         * 
+         * @return result of response playback to return from handler
+         */
+        virtual std::pair<bool,long> unwrapResponse(SPRequest& request, DDF& wrappedResponse) const;
+
         /**
          * Prevents unused relay state from building up by cleaning old state from the client.
          *
diff --git a/shibsp/handler/SessionInitiator.h b/shibsp/handler/SessionInitiator.h
deleted file mode 100644
index 1c4ea124..00000000
--- a/shibsp/handler/SessionInitiator.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file shibsp/handler/SessionInitiator.h
- * 
- * Pluggable runtime functionality that handles initiating sessions.
- */
-
-#ifndef __shibsp_sesinitiator_h__
-#define __shibsp_sesinitiator_h__
-
-#include <shibsp/handler/AbstractHandler.h>
-
-#include <set>
-#include <string>
-
-#if defined (_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4251 )
-#endif
-
-namespace shibsp {
-
-    /**
-     * Pluggable runtime functionality that handles initiating sessions.
-     *
-     * <p>By default, SessionInitiators look for an entityID on the incoming request
-     * and pass control to the specialized run method.
-     */
-    class SHIBSP_API SessionInitiator : public virtual AbstractHandler
-    {
-        friend void SHIBSP_API registerSessionInitiators();
-    protected:
-
-        /** Set of optional settings supported by handler. */
-        std::set<std::string> m_supportedOptions;
-
-        /**
-         * Constructor.
-         * 
-         * @param pt    root of handler configuration
-         * @param log   logging category
-         */
-        SessionInitiator(const boost::property_tree::ptree& pt, Category& log);
-
-        /**
-         * Examines the request and applicable settings to determine whether
-         * the handler is able to support the request.
-         * <p>If the handler is within a chain, the method will return false,
-         * otherwise an exception will be raised.
-         *
-         * @param request   SP request context
-         * @param isHandler true iff executing in the context of a direct handler invocation
-         * @return  true iff the request appears to be compatible
-         */
-        bool checkCompatibility(SPRequest& request, bool isHandler) const;
-
-    public:
-        virtual ~SessionInitiator();
-
-        /**
-         * Indicates the set of optional settings supported by the handler.
-         *
-         * @return  a set of the optional settings supported
-         */
-        virtual const std::set<std::string>& getSupportedOptions() const;
-
-        /**
-         * Executes an incoming request.
-         * 
-         * <p>SessionInitiators can be run either directly by incoming web requests
-         * or indirectly/implicitly during other SP processing.
-         * 
-         * @param request   SP request context
-         * @param entityID  the name of an IdP to request a session from, if known
-         * @param isHandler true iff executing in the context of a direct handler invocation
-         * @return  a pair containing a "request completed" indicator and a server-specific response code
-         */
-        virtual std::pair<bool,long> run(SPRequest& request, std::string& entityID, bool isHandler=true) const=0;
-
-        std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-    };
-    
-};
-
-#if defined (_MSC_VER)
-#pragma warning( pop )
-#endif
-
-
-#endif /* __shibsp_sesinitiator_h__ */
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 1a935aea..75b79ee2 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -48,19 +48,18 @@ using namespace std;
 #endif
 
 namespace shibsp {
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2ConsumerFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AttributeCheckerFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory MetadataGeneratorFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2ConsumerFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AttributeCheckerFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory MetadataGeneratorFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory StatusHandlerFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionHandlerFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionHandlerFactory;
 
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AdminLogoutInitiatorFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutInitiatorFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory LocalLogoutInitiatorFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AdminLogoutInitiatorFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutInitiatorFactory;
+    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory LocalLogoutInitiatorFactory;
 
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2SessionInitiatorFactory;
-    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAMLDSSessionInitiatorFactory;
+    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionInitiatorFactory;
 
     void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {
         static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
@@ -97,8 +96,7 @@ void SHIBSP_API shibsp::registerHandlers()
     //conf.HandlerManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
     //conf.HandlerManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
 
-    //conf.HandlerManager.registerFactory(SAML2_SESSION_INITIATOR, SAML2SessionInitiatorFactory);
-    //conf.HandlerManager.registerFactory(SAMLDS_SESSION_INITIATOR, SAMLDSSessionInitiatorFactory);
+    conf.HandlerManager.registerFactory(SESSION_INITIATOR_HANDLER, SessionInitiatorFactory);
 } 
 
 Handler::Handler()
@@ -123,6 +121,71 @@ const char* Handler::getEventType() const
     return nullptr;
 }
 
+DDF AbstractHandler::wrapRequest(const SPRequest& request, const vector<string>& headers, bool sendBody) const
+{
+    DDF in = DDF("http").structure();
+    in.addmember("scheme").string(request.getScheme());
+    in.addmember("hostname").unsafe_string(request.getHostname());
+    in.addmember("port").integer(request.getPort());
+    in.addmember("content_type").string(request.getContentType().c_str());
+    if (sendBody) {
+        in.addmember("body").unsafe_string(request.getRequestBody());
+    }
+    in.addmember("content_length").longinteger(request.getContentLength());
+    in.addmember("remote_user").string(request.getRemoteUser().c_str());
+    in.addmember("remote_addr").string(request.getRemoteAddr().c_str());
+    in.addmember("method").string(request.getMethod());
+    in.addmember("uri").unsafe_string(request.getRequestURI());
+    in.addmember("url").unsafe_string(request.getRequestURL());
+    in.addmember("query").string(request.getQueryString());
+
+    if (!headers.empty()) {
+        string hdr;
+        DDF hin = in.addmember("headers").structure();
+        for (const string& h : headers) {
+            hdr = request.getHeader(h.c_str());
+            if (!hdr.empty())
+                hin.addmember(h.c_str()).unsafe_string(hdr.c_str());
+        }
+    }
+
+    return in;
+}
+
+pair<bool,long> AbstractHandler::unwrapResponse(SPRequest& request, DDF& wrappedResponse) const
+{
+    DDF h = wrappedResponse["headers"];
+    DDF hdr = h.first();
+    while (hdr.isstring()) {
+        if (!strcasecmp(hdr.name(), "Content-Type")) {
+            request.setContentType(hdr.string());
+        }
+        else {
+            request.setResponseHeader(hdr.name(), hdr.string());
+        }
+        hdr = h.next();
+    }
+
+    h = wrappedResponse["redirect"];
+    if (h.isstring()) {
+        return make_pair(true, request.sendRedirect(h.string()));
+    }
+
+    h = wrappedResponse["response"];
+    if (h.isstruct()) {
+        const char* data = h["data"].string();
+        if (data) {
+            // TODO: we should be able to create a custom streambuf to wrap the existing
+            // buffer without copying it.
+            istringstream s(data);
+            return make_pair(true, request.sendResponse(s, h["status"].integer()));
+        }
+    }
+
+    return make_pair(false, 0L);
+}
+
+
 void AbstractHandler::cleanRelayState(SPRequest& request) const
 {
     const char* mech = request.getRequestSettings().first->getString("relayState");
diff --git a/shibsp/handler/impl/DefaultHandlerConfiguration.cpp b/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
index 9f809435..c0a7b524 100644
--- a/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
+++ b/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
@@ -64,7 +64,7 @@ HandlerConfiguration::HandlerConfiguration() {}
 HandlerConfiguration::~HandlerConfiguration() {}
 
 DefaultHandlerConfiguration::DefaultHandlerConfiguration(const char* pathname)
-    : m_sessionInitiator(nullptr), m_tokenConsumerConfig("token_consumers")
+    : m_sessionInitiator(nullptr), m_tokenConsumerConfig("response_url")
 {
     ini_parser::read_ini(pathname, m_pt);
 
diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp
index 39232fbf..cbd4f72f 100644
--- a/shibsp/handler/impl/SessionInitiator.cpp
+++ b/shibsp/handler/impl/SessionInitiator.cpp
@@ -15,127 +15,176 @@
 /**
  * handler/impl/SessionInitiator.cpp
  * 
- * Pluggable runtime functionality that handles initiating sessions.
+ * Handler for initiating sessions.
  */
 
 #include "internal.h"
 #include "exceptions.h"
+#include "Agent.h"
 #include "SPRequest.h"
-#include "handler/SessionInitiator.h"
+#include "handler/AbstractHandler.h"
+#include "handler/HandlerConfiguration.h"
 #include "logging/Category.h"
+#include "remoting/RemotingService.h"
 #include "util/Misc.h"
 
 using namespace shibsp;
 using namespace boost::property_tree;
 using namespace std;
 
-SessionInitiator::SessionInitiator(const ptree& pt, Category& log) : AbstractHandler(pt, log)
-{
-}
+namespace {
+    class SHIBSP_DLLLOCAL SessionInitiator : public virtual AbstractHandler {
+    public:
+        SessionInitiator(const ptree& pt, const char* path);
+        virtual ~SessionInitiator() {}
 
-SessionInitiator::~SessionInitiator()
-{
-}
+        pair<bool,long> run(SPRequest& request, bool isHandler) const;
 
-const set<string>& SessionInitiator::getSupportedOptions() const
-{
-    return m_supportedOptions;
-}
+    private:
+        string m_path;
+        vector<string> m_remotedHeaders;
+        vector<string> m_requestMapperSettings;
+        vector<string> m_querySettings;
+    };
+};
 
-bool SessionInitiator::checkCompatibility(SPRequest& request, bool isHandler) const
+namespace shibsp {
+    Handler* SHIBSP_DLLLOCAL SessionInitiatorFactory(const pair<ptree&,const char*>& p, bool) {
+        return new SessionInitiator(p.first, p.second);
+    }
+};
+
+SessionInitiator::SessionInitiator(const ptree& pt, const char* path)
+    : AbstractHandler(pt, Category::getInstance(SHIBSP_LOGCAT ".Handler.SessionInitiator")),
+        m_path(path), m_remotedHeaders({ "Cookie" })
 {
-    bool isPassive = false;
-    if (isHandler) {
-        const char* flag = request.getParameter("isPassive");
-        if (flag) {
-            string_to_bool_translator tr;
-            boost::optional<bool> b = tr.get_value(flag);
-            isPassive = b.has_value() ? b.get() : false;
-        }
-        else {
-            isPassive = getBool("isPassive", false);
-        }
+    const char* settings = getString("requestMapperSettings");
+    if (settings) {
+        split_to_container(m_requestMapperSettings, settings);
     }
     else {
-        // It doesn't really make sense to use isPassive with automated sessions, but...
-        if (request.getRequestSettings().first->hasProperty("isPassive")) {
-            isPassive = request.getRequestSettings().first->getBool("isPassive", false);
-        } else {
-            isPassive = getBool("isPassive", false);
-        }
+        // Legacy SAML defaults.
+        m_requestMapperSettings = {
+            "entityID",
+            "authority",
+            "forceAuthn",
+            "isPassive",
+            "authnContextClassRef",
+            "authnContextComparison",
+            "NameIDFormat",
+            "SPNameQualifier",
+            "attributeIndex"
+        };
     }
 
-    // Check for support of isPassive if it's used.
-    if (isPassive && getSupportedOptions().count("isPassive") == 0) {
-        throw ConfigurationException("Unsupported option (isPassive) supplied to SessionInitiator.");
+    settings = getString("querySettings");
+    if (settings) {
+        split_to_container(m_querySettings, settings);
+    }
+    else {
+        // Same defaults for now.
+        m_querySettings = m_requestMapperSettings;
     }
-
-    return true;
 }
 
 pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
 {
-    /*
-    cleanRelayState(request);
-
-    const char* entityID = nullptr;
-    pair<bool,const char*> param = getString("entityIDParam");
-    if (isHandler) {
-        entityID = request.getParameter(param.first ? param.second : "entityID");
-        if (!param.first && (!entityID || !*entityID))
-            entityID=request.getParameter("providerId");
-    }
-    if (!entityID || !*entityID) {
-        param.second = request.getRequestSettings().first->getString("entityID");
-        if (param.second)
-            entityID = param.second;
-    }
-    if (!entityID || !*entityID)
-        entityID = getString("entityID").second;
+    try {
+        string state, target, handler;
 
-    string copy(entityID ? entityID : "");
+        if (isHandler) {
+            // Check for a state parameter in the query string.
+            const char* param = request.getParameter("state");
+            if (param) {
+                // We'll pass state as is and target will be omitted.
+                state = param;
+                // handler can be derived from "this" URL since this is a re-entrant call to this handler,
+                // i.e., we know this is the right URL to use because "it already was" originally.
+                handler = request.getHandlerURL(request.getRequestURL()) + m_path;
+            }
+            else {
+                // target will come from query string, map, or handler or fall back to this request.
+                target = getString("target", request, request.getRequestURL());
+                // handler is derived from the target resource.
+                handler = request.getHandlerURL(target.c_str()) + m_path;
+            }
+        }
+        else {
+            // Check for a hardwired target value in the map or handler.
+            target = getString("target", request, request.getRequestURL(),
+                HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP);
+            // state is empty since this is a direct resource request.
+            // handler is derived from the target resource
+            handler = request.getHandlerURL(target.c_str()) + m_path;
+        }
 
-    try {
-        return run(request, copy, isHandler);
+        const PropertySet* settings = request.getRequestSettings().first;
+
+        DDF input("session-initiator");
+        DDFJanitor inputJanitor(input);
+
+        input.structure();
+        input.addmember("application").string(settings->getString("applicationId", "default"));
+        input.addmember("handler").unsafe_string(handler.c_str());
+        if (state.empty()) {
+            input.addmember("target").unsafe_string(target.c_str());
+        }
+        else {
+            input.addmember("state").string(state.c_str());
+        }
+
+        const DDF& consumers = request.getAgent().getHandlerConfiguration(
+            settings->getString("handlerConfigID")).getTokenConsumerInfo();
+        DDF dup = consumers.copy();
+        input.add(dup);
+
+        DDF wrapped = wrapRequest(request, m_remotedHeaders,
+            !isHandler && getBool("preservePostData", request, false,
+                HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP));
+        input.add(wrapped);
+
+        for (const string& propname : m_requestMapperSettings) {
+            const char* prop = getString(propname.c_str(), request, nullptr,
+                HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP);
+            if (prop) {
+                input.addmember(propname.c_str()).string(prop);
+            }
+        }
+
+        // If there's an overlap with the previous set, this will overwrite.
+
+        for (const string& propname : m_querySettings) {
+            const char* prop = getString(propname.c_str(), request, nullptr,
+                HANDLER_PROPERTY_REQUEST);
+            if (prop) {
+                input.addmember(propname.c_str()).string(prop);
+            }
+        }
+
+        DDF output = request.getAgent().getRemotingService()->send(input);
+        DDFJanitor outputJanitor(output);
+
+        return unwrapResponse(request, output);
     }
     catch (exception& ex) {
         // If it's a handler operation, and isPassive is used or returnOnError is set, we trap the error.
         if (isHandler) {
-            bool returnOnError = false;
-            const char* flag = request.getParameter("isPassive");
-            if (flag && (*flag == 't' || *flag == '1')) {
-                returnOnError = true;
-            }
-            else {
-                pair<bool,bool> flagprop = getBool("isPassive");
-                if (flagprop.first && flagprop.second) {
-                    returnOnError = true;
-                }
-                else {
-                    flag = request.getParameter("returnOnError");
-                    if (flag) {
-                        returnOnError = (*flag=='1' || *flag=='t');
-                    }
-                    else {
-                        flagprop = getBool("returnOnError");
-                        returnOnError = (flagprop.first && flagprop.second);
-                    }
-                }
+            bool returnOnError = getBool("isPassive", request, false);
+            if (!returnOnError) {
+                returnOnError = getBool("returnOnError", request, false);
             }
 
             if (returnOnError) {
-                // Log it and attempt to recover relay state so we can get back.
-                m_log.error(ex.what());
-                m_log.info("trapping SessionInitiator error condition and returning to target location");
-                flag = request.getParameter("target");
-                string target(flag ? flag : "");
-                recoverRelayState(request, target, false);
-                request.limitRedirect(target.c_str());
-                return make_pair(true, request.sendRedirect(target.c_str()));
+                m_log.warn(ex.what());
+                const agent_exception* agent_ex = dynamic_cast<const agent_exception*>(&ex);
+                const char* target = agent_ex ? agent_ex->getProperty("target") : nullptr;
+                if (target) {
+                    m_log.info("trapping SessionInitiator failure and returning to target location");
+                    request.limitRedirect(target);
+                    return make_pair(true, request.sendRedirect(target));
+                }
             }
         }
         throw;
     }
-    */
-    return pair(true,0);
 }
diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp
index 1cbb13f3..2300911a 100644
--- a/shibsp/handler/impl/StatusHandler.cpp
+++ b/shibsp/handler/impl/StatusHandler.cpp
@@ -42,12 +42,7 @@ using namespace std;
 #ifndef HAVE_STRCASECMP
 # define strncasecmp _strnicmp
 #endif
-namespace shibsp {
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
+namespace {
 
     class SHIBSP_API StatusHandler : public SecuredHandler
     {
@@ -61,15 +56,6 @@ namespace shibsp {
         ostream& systemInfo(ostream& os) const;
     };
 
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    Handler* SHIBSP_DLLLOCAL StatusHandlerFactory(const pair<ptree&,const char*>& p, bool)
-    {
-        return new StatusHandler(p.first);
-    }
-
     class DummyRequest : public virtual HTTPRequest
     {
     public:
@@ -197,6 +183,12 @@ namespace shibsp {
     };
 };
 
+namespace shibsp {
+    Handler* SHIBSP_DLLLOCAL StatusHandlerFactory(const pair<ptree&, const char*>& p, bool) {
+        return new StatusHandler(p.first);
+    }
+};
+
 StatusHandler::StatusHandler(const ptree& pt)
     : SecuredHandler(pt, Category::getInstance(SHIBSP_LOGCAT ".Handler.Status"))
 {
diff --git a/shibsp/remoting/impl/AbstractRemotingService.cpp b/shibsp/remoting/impl/AbstractRemotingService.cpp
index 59546610..8c7da84a 100644
--- a/shibsp/remoting/impl/AbstractRemotingService.cpp
+++ b/shibsp/remoting/impl/AbstractRemotingService.cpp
@@ -46,8 +46,14 @@ DDF AbstractRemotingService::send(const DDF& in) const
 
     const char* event = output.getmember("event").string();
     if (event && strcmp(event, "success")) {
-        DDFJanitor cleanup(output);
-        throw OperationException(event);
+        OperationException ex("A remote operation was unsuccessful.");
+        ex.addProperty("event", event);
+        const char* target = output.getmember("target").string();
+        if (target) {
+            ex.addProperty("target", target);
+        }
+        output.destroy();
+        throw ex;
     }
     return output;
 }

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list