Loading ...
Sorry, an error occurred while loading the content.

My own dispatching sub - is it possible?

Expand Messages
  • Íèêèòà Äåäèê
    Greetings! My task is to write a SOAP server, that would dispatch requests to some modules using its own sophisticated naming scheme. Imagine that I have
    Message 1 of 2 , Mar 5, 2005
    View Source
    • 0 Attachment
      Greetings!

      My task is to write a SOAP server, that would dispatch requests to
      some modules using its own "sophisticated" naming scheme. Imagine
      that I have several modules somehow located in directory tree, and
      I've got a mapping of module names to their paths. Due to some
      requirements I cannot place modules in SOAP::Lite's default naming
      scheme (like My::Example), but I can dynamically map URI to module and
      call the needed methods myself. Is there any possibility to make SOAP
      ::Transport::HTTP::CGI (or whatever) call some specified sub as a
      handler for ANY request, giving method URI to it as a parameter and
      taking its result as a respone for SOAP call, while this sub parses
      URI and calls the needed modules itself, forming a return value? I'm
      not afraid of some additional coding :), but I don't want to patch
      original SOAP::Lite distribution, that's why I'm asking you for some
      gentle solution.

      Many thanks in advance!
    • Jay A. Kreibich
      ... I am faced with a similar problem. In addition to not being able to use a structured namespace, I need to support an environment where security is taken
      Message 2 of 2 , Mar 6, 2005
      View Source
      • 0 Attachment
        On Sat, Mar 05, 2005 at 11:03:47AM -0000, ?????? ????? scratched on the wall:

        > My task is to write a SOAP server, that would dispatch requests to
        > some modules using its own "sophisticated" naming scheme. Imagine
        > that I have several modules somehow located in directory tree, and
        > I've got a mapping of module names to their paths. Due to some
        > requirements I cannot place modules in SOAP::Lite's default naming
        > scheme (like My::Example), but I can dynamically map URI to module and
        > call the needed methods myself. Is there any possibility to make SOAP
        > ::Transport::HTTP::CGI (or whatever) call some specified sub as a
        > handler for ANY request, giving method URI to it as a parameter and
        > taking its result as a respone for SOAP call, while this sub parses
        > URI and calls the needed modules itself, forming a return value? I'm
        > not afraid of some additional coding :), but I don't want to patch
        > original SOAP::Lite distribution, that's why I'm asking you for some
        > gentle solution.

        I am faced with a similar problem. In addition to not being able to
        use a structured namespace, I need to support an environment where
        security is taken very seriously, but where modules to our SOAP
        server can be written by people without a lot of knowledge or
        understanding of SOAP (in other words, security is my problem, but
        I'm not writing most of the code).

        In addition, all calls are authenticated using SOAP Headers, and
        I wanted to handle that auth/auth centrally, rather than have each
        exported function start with the same four lines of code (assuming
        the developer remembers to put it there!). I also export both the
        auth/auth info and the full request SOM object to the function as
        "localized package globals" (only in Perl could there be such a
        thing!) so that the average developer can just use the normal
        function style, but those that require more specific information
        (like parameter type info or names) can access that if required.

        In order to do all this, I'm using the "dispatch_to" method to
        dispatch into a directory of modules. All of those modules have
        exactly one line:

        -<dir to dispatch_to>/wsModule/Pkg.pm---------------------------------
        package wsModule::Pkg; our( @ISA ) = ( 'Project::WebsvcsBase'); 1;
        ----------------------------------------------------------------------

        Substituting the project, project module, and package name as required
        (this project is a very big deployment).

        The WebsvcsBase class is pre-loaded by mod_perl, so there is no need for
        a "use" statement and the security hassles of that under a "dispatch_to".
        The WebsvcsBase package has an AUTOLOAD function that catches all unknown
        calls, which in this case is all of them. My
        Project::WebsvcsBase::AUTOLOAD function extracts the SOAP Headers
        and does the auth/auth on that, then converts the call to
        "wsModule::Pkg::Function" into something like
        "Project::Module::Pkg::Websvcs::Function". After checking to be sure
        the function doesn't start with "_" (used to indicate a package
        internal helper function that should not be exposed to SOAP), "-> can()"
        is called on the package to see if the package/function exists, and
        get a CODE ref if it does. Finally, the localized package globals are
        set and the call is dispatched to the altered package path as a class
        method.

        This is pretty complex and carries some baggage (like the need for
        the "wsModule/Pkg.pm" files), but it gives me total control over the
        altering and dispatch of all calls. If you make sure the package
        Project::WebsvcsBase ONLY has the AUTOLOAD function, and you make
        sure the $AUTOLOAD var is not undef (indicating an explicit call to
        AUTOLOAD( )), then you've got only one spot that everything must go
        through in a controlled way.

        If all you need is to take a request (with SOAP-Action and URI path)
        and convert it to a new module path, it would be much simpler to
        write an "on_dispatch( )" hook into SOAP::Server. The SOAP::Server
        module still dispatches the call with one of the existing systems
        (dispatch_with, dispatch_to), but you can define (and limit) the
        conversion from URI to Perl module path. In my case I might be able
        to the auth/auth verification there, but I couldn't store the
        localized symbols. If you do choose to do that, it might not be
        obvious, but errors can result in a "die SOAP::Fault -> new(...)"
        call; there is no need (nor ability) to return error codes or the
        like.


        Talking with other SOAP::Lite developers, this desire to have better
        control over the dispatch seems like a fairly common thing. I have
        considered writing a patch to the core sources to implement a
        "dispatch_thru" system, by which the user could designate a
        superclass such as Project::WebsvcsBase. The SOAP::Server module
        would then create a "@Package....::ISA = ( $dispatch_thru_superclass )"
        entry in the symbol table for each call that came through and
        dispatch the call to that class (perhaps even local() to keep things
        tidy and neat).

        Why didn't I do it? In short, if you think the SOAP::Lite examples
        are opaque and difficult to follow, try looking at the core sources.
        I'll grant Paul a lot of credit in the fact that it works, but the
        source seems to value "compact and clever" over "easy to read and
        understand." It is very difficult to follow and understand, and even
        more difficult to modify "in the spirit" of the original style (at
        least for me). I may still write such a patch, but for now it was
        considered easier to auto-generate the stub class files.

        -j

        --
        Jay A. Kreibich | CommTech, Emrg Net Tech Svcs
        jak@... | Campus IT & Edu Svcs
        <http://www.uiuc.edu/~jak> | University of Illinois at U/C
      Your message has been successfully submitted and would be delivered to recipients shortly.