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

Re: Using SOAP::Transport::IO::Server to process request

Expand Messages
  • iancrogers
    I ve sorted this out, somewhat. SOAP::Transport::IO::Server - new( ) - in ( CLIENT ) - out( CLIENT ) - dispatch_to( MuseClient ) - handle ; writes
    Message 1 of 5 , Jan 29, 2002
    • 0 Attachment
      I've sorted this out, somewhat.

      SOAP::Transport::IO::Server
      -> new( )
      -> in ( CLIENT )
      -> out( CLIENT )
      -> dispatch_to( 'MuseClient' )
      -> handle
      ;

      writes output to a file 'CLIENT'.

      The following gives the desired result by first writing the request
      to a file:

      open ( SO, "> INPUT.xml" );
      $msg_body = "";
      LINE: while ( recv( CLIENT, $buf, 1, 0 ) ) {
      print SO $buf;
      $msg_body .= $buf;
      last LINE if ( $msg_body =~ /<\/SOAP-ENV:Envelope>/ );
      }
      close SO;

      print CLIENT "HTTP/1.1 200 OK\n";
      print CLIENT "Content-Type: text/xml\n\n";

      SOAP::Transport::IO::Server
      -> new( )
      -> in ( 'INPUT.xml' )
      -> out( *CLIENT )
      -> dispatch_to( 'MuseClient' )
      -> handle
      ;

      This, however, blocks forever:

      SOAP::Transport::IO::Server
      -> new( )
      -> in ( *CLIENT )
      -> out( *CLIENT )
      -> dispatch_to( 'MuseClient' )
      -> handle
      ;

      Client is making the SOAP request as in the previous post:

      print SOAP::Lite
      -> uri($soap_uri)
      -> proxy($soap_proxy)
      -> test_routine( $email, $password, $XML )
      -> result . "\n";

      I assume this is a buffering issue. The client doesn't send a
      newline at the end of the request, and the read waits forever for
      this last record separator. This is why while( <CLIENT> ) wasn't
      working for me, I think, and I had to resort to reading one
      character at a time.

      Obviously, I don't want to have to write the SOAP request to a file
      before I process it. Can someone suggest an alternative?

      Thanks in advance,
      ian
    • Paul Kulchenko
      Hi, Ian! ... It depends on what do you want to do ;). ... This won t work. You can t easily read from and write to the same filehandle. From IPC::Open2: This
      Message 2 of 5 , Jan 29, 2002
      • 0 Attachment
        Hi, Ian!

        > Obviously, I don't want to have to write the SOAP request to a file
        > before I process it. Can someone suggest an alternative?
        It depends on what do you want to do ;).

        > -> in ( *CLIENT )
        > -> out( *CLIENT )
        This won't work. You can't easily read from and write to the same
        filehandle. From IPC::Open2:

        This whole affair is quite dangerous, as you may block forever. It
        assumes it's going to talk to something like B<bc>, both writing
        to it and reading from it. This is presumably safe because you
        "know" that commands like B<bc> will read a line at a time and
        output a line at a time. Programs like B<sort> that read their
        entire input stream first, however, are quite apt to cause deadlock.

        If you have file or stream you can use SOAP::Transport::IO to handle
        that. If you have HTTP, you can use SOAP::Transport::HTTP::* module
        to handle that. If you use combination of those and want to handle
        transport level yourself, you can use SOAP::Server to handle payload:

        $response_xml = SOAP::Server
        ->dispatch_to(...)
        ->handle($request_xml);

        In this case you don't need to create a file and then process it with
        ::IO transport. Hope it helps. Please provide little bit more details
        if you still have problems.

        Best wishes, Paul.

        --- iancrogers <ian@...> wrote:
        > I've sorted this out, somewhat.
        >
        > SOAP::Transport::IO::Server
        > -> new( )
        > -> in ( CLIENT )
        > -> out( CLIENT )
        > -> dispatch_to( 'MuseClient' )
        > -> handle
        > ;
        >
        > writes output to a file 'CLIENT'.
        >
        > The following gives the desired result by first writing the request
        >
        > to a file:
        >
        > open ( SO, "> INPUT.xml" );
        > $msg_body = "";
        > LINE: while ( recv( CLIENT, $buf, 1, 0 ) ) {
        > print SO $buf;
        > $msg_body .= $buf;
        > last LINE if ( $msg_body =~ /</SOAP-ENV:Envelope>/ );
        > }
        > close SO;
        >
        > print CLIENT "HTTP/1.1 200 OK
        ";
        > print CLIENT "Content-Type: text/xml

        ";
        >
        > SOAP::Transport::IO::Server
        > -> new( )
        > -> in ( 'INPUT.xml' )
        > -> out( *CLIENT )
        > -> dispatch_to( 'MuseClient' )
        > -> handle
        > ;
        >
        > This, however, blocks forever:
        >
        > SOAP::Transport::IO::Server
        > -> new( )
        > -> in ( *CLIENT )
        > -> out( *CLIENT )
        > -> dispatch_to( 'MuseClient' )
        > -> handle
        > ;
        >
        > Client is making the SOAP request as in the previous post:
        >
        > print SOAP::Lite
        > -> uri($soap_uri)
        > -> proxy($soap_proxy)
        > -> test_routine( $email, $password, $XML )
        > -> result . "
        ";
        >
        > I assume this is a buffering issue. The client doesn't send a
        > newline at the end of the request, and the read waits forever for
        > this last record separator. This is why while( <CLIENT> ) wasn't
        > working for me, I think, and I had to resort to reading one
        > character at a time.
        >
        > Obviously, I don't want to have to write the SOAP request to a file
        >
        > before I process it. Can someone suggest an alternative?
        >
        > Thanks in advance,
        > ian
        >
        >
        > ------------------------ Yahoo! Groups Sponsor
        >
        > To unsubscribe from this group, send an email to:
        > soaplite-unsubscribe@yahoogroups.com
        >
        >
        >
        > Your use of Yahoo! Groups is subject to
        > http://docs.yahoo.com/info/terms/
        >
        >


        __________________________________________________
        Do You Yahoo!?
        Great stuff seeking new owners in Yahoo! Auctions!
        http://auctions.yahoo.com
      • ian c rogers
        ... SOAP::Server got me much further, but I m still having sporadic results. Let me explain in a bit more detail what I m trying to do, as I feel I might be
        Message 3 of 5 , Feb 1, 2002
        • 0 Attachment
          > If you have file or stream you can use SOAP::Transport::IO to handle
          > that. If you have HTTP, you can use SOAP::Transport::HTTP::* module
          > to handle that. If you use combination of those and want to handle
          > transport level yourself, you can use SOAP::Server to handle payload:

          SOAP::Server got me much further, but I'm still having sporadic results.

          Let me explain in a bit more detail what I'm trying to do, as I feel I might
          be approaching this the wrong way. I have a simple program that has a
          simple (forking) HTTP server within it. The HTTP server may be called upon
          to serve a few specific files, or it may receive a SOAP request. I handle
          either by reading in the HTTP header like so:

          # Read HTTP header info
          LINE: while ( $buf = <CLIENT> ) {
          chomp( $buf );
          last LINE if ( length( $buf ) == 1 );
          $some_data .= "$buf\n";
          }

          and then serve the file if I see /^GET (\/.+txt) HTTP/ or handle the SOAP
          if I see /^POST \/SOAPONAROPE HTTP/. Here's how I'm handling the SOAP now:

          $request_xml = "";
          LINE: while ( recv( CLIENT, $buf, 1, 0 ) ) {
          $request_xml .= $buf;
          last LINE if ( $request_xml =~ /<\/SOAP-ENV:Envelope>/ ||
          $request_xml eq "" );
          }
          $response_xml = SOAP::Server
          ->dispatch_to( 'TestPackage' )
          ->handle($request_xml);

          print CLIENT "HTTP/1.1 200 OK\n";
          print CLIENT "Content-Type: text/xml\n\n";
          print CLIENT "$response_xml\n";

          is simply:

          package TestPackage;

          sub test_routine {
          my ( $self, $email, $password, $XML ) = @_;

          return "AW YEAH!\n";
          }

          And the soap_client.pl is:

          $soap_uri = "http://localhost/TestPackage";
          $soap_proxy = "http://localhost/SOAPONAROPE";
          print "calling test_routine via $soap_proxy: ";
          print SOAP::Lite # fix tags
          -> uri($soap_uri)
          -> proxy($soap_proxy)
          -> test_routine( $email, $password, $XML )
          -> result . "\n";
          exit;

          Sample output:

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: 500 read timeout
          at ./soap_client.pl line 30
          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          $ ./soap_client.pl
          calling test_routine via http://localhost/SOAPONAROPE: AW YEAH!

          On the timeout run, the header info is read, but the server blocks forever
          on the recv() at LINE. I've added some code to take a look at the socket to
          see if there's any data to be read there, and as you might guess, sometimes
          there isn't (which avoids the timeout but not the larger problem). Why not?

          Clearly I'm no whiz at handling the transport myself and I'd prefer not to.
          Is there another way in my case? If not, suggestions? Any idea why my
          soap_client.pl would be sending header only then blocking sometimes? What
          other factors might be to blame?

          Thanks again for your help. Sorry for the delay in follow-up, I had minor
          surgery Weds am. :)

          ian
        • Duncan Cameron
          ... Presumably this works, but what is the above line actually testing? ... ... I suggest using HTTP::Daemon to construct your server. That should
          Message 4 of 5 , Feb 2, 2002
          • 0 Attachment
            On 2002-02-01 ian c rogers <ian@...> wrote:

            >Let me explain in a bit more detail what I'm trying to do, as I feel I might
            >be approaching this the wrong way. I have a simple program that has a
            >simple (forking) HTTP server within it. The HTTP server may be called upon
            >to serve a few specific files, or it may receive a SOAP request. I handle
            >either by reading in the HTTP header like so:
            >
            > # Read HTTP header info
            > LINE: while ( $buf = <CLIENT> ) {
            > chomp( $buf );
            > last LINE if ( length( $buf ) == 1 );

            Presumably this works, but what is the above line actually testing?

            > $some_data .= "$buf\n";
            > }
            >
            <snipped>

            >On the timeout run, the header info is read, but the server blocks forever
            >on the recv() at LINE. I've added some code to take a look at the socket to
            >see if there's any data to be read there, and as you might guess, sometimes
            >there isn't (which avoids the timeout but not the larger problem). Why not?
            >
            >Clearly I'm no whiz at handling the transport myself and I'd prefer not to.
            >Is there another way in my case? If not, suggestions? Any idea why my
            >soap_client.pl would be sending header only then blocking sometimes? What
            >other factors might be to blame?

            I suggest using HTTP::Daemon to construct your server. That should
            avoid many of the possible problems which you might be hitting.

            Also, I'm no expert in sockets but is it a good idea to mix stdio type
            input (using <CLIENT>) and recv() input on the same socket?
            There should be a Content-length header which tells you _exactly_ how
            many bytes to read so you don't have to read one byte at a time.

            Regards

            Duncan Cameron
          Your message has been successfully submitted and would be delivered to recipients shortly.