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

off-by-one on array input

Expand Messages
  • v_pareto
    When my SOAP::Lite client feeds an array to a SOAP::Transport::HTTP server, I get an off-by-one error. That is to say, the following code on the client @a =
    Message 1 of 4 , Feb 25, 2002
    • 0 Attachment
      When my SOAP::Lite client feeds an array to a SOAP::Transport::HTTP
      server, I get an off-by-one error. That is to say, the following code
      on the client

      @a = (0,1,2);
      $x = $soap->foo(@a)->result;
      print($x,"\n");

      given to the following subroutine on the server

      sub foo {

      my @a = @_;
      return($a[1]);

      }

      prints 0, not 1. Of course, I can shift my way around this problem,
      but I would still consider this a bug. Arrays in perl start at 0.
      What's going on here?
    • Duncan Cameron
      ... What s going on is that you ve not looked at any of the examples. The first parameter o th method is the class/object reference. See the SOAP::Lite pod
      Message 2 of 4 , Feb 25, 2002
      • 0 Attachment
        On 2002-02-26 v_pareto wrote:
        >When my SOAP::Lite client feeds an array to a SOAP::Transport::HTTP
        >server, I get an off-by-one error. That is to say, the following code
        >on the client
        >
        >@a = (0,1,2);
        >$x = $soap->foo(@a)->result;
        >print($x,"\n");
        >
        >given to the following subroutine on the server
        >
        >sub foo {
        >
        > my @a = @_;
        > return($a[1]);
        >
        >}
        >
        >prints 0, not 1. Of course, I can shift my way around this problem,
        >but I would still consider this a bug. Arrays in perl start at 0.
        >What's going on here?
        >
        "What's going on" is that you've not looked at any of the examples.
        The first parameter o th method is the class/object reference.
        See the SOAP::Lite pod under IN/OUT

        BTW, I don't think tht you are actually sending an array, rather a
        series of individual elements which the server decides to treat as
        an array. It's not the same as sending a SOAP array, which you
        asked about on this list a week ago.

        Regards,
        Duncan Cameron
      • Sam Tregar
        ... SOAP calls are class method calls. The first parameter is the name of the class where foo is defined. Add: my $pkg = shift; above the line where you load
        Message 3 of 4 , Feb 26, 2002
        • 0 Attachment
          On Tue, 26 Feb 2002, v_pareto wrote:

          > sub foo {
          >
          > my @a = @_;
          > return($a[1]);
          >
          > }
          >
          > prints 0, not 1. Of course, I can shift my way around this problem,
          > but I would still consider this a bug. Arrays in perl start at 0.
          > What's going on here?

          SOAP calls are class method calls. The first parameter is the name of the
          class where foo is defined. Add:

          my $pkg = shift;

          above the line where you load @a and you should get the behavior you're
          looking for. If OO in Perl is new to you, may I suggest you read Damian
          Conway's excelent book "Object-Oriented Perl"?

          -sam
        • Duncan Cameron
          ... Not sure what you are looking at. This code: my @array1 = ( z , x , c , v ); my $r = $s- test1(@array1); generates XML like this:
          Message 4 of 4 , Feb 26, 2002
          • 0 Attachment
            On 2002-02-26 David Wright wrote:
            >> BTW, I don't think tht you are actually sending an array, rather a
            >> series of individual elements which the server decides to treat as
            >> an array. It's not the same as sending a SOAP array, which you
            >> asked about on this list a week ago.
            >
            >What I asked about a week ago was how to send an arrary from the server;
            >this question involved sending an array from the client. The undesirable
            >behaviour is that SOAP::Lite handles these situations asymmetrically.
            >
            >If you look with a packet sniffer, you will see that what goes out over
            >the wire when you
            > $soap->foo(@a)->result;
            >from the client is indeed a SOAP array. In fact, is has the exact same
            >XML structure as what goes out from the server when you
            > return [@a];

            Not sure what you are looking at. This code:

            my @array1 = ('z','x', 'c', 'v');
            my $r = $s->test1(@array1);

            generates XML like this:

            <namesp1:test1 xmlns:namesp1="urn:Demo">
            <c-gensym3 xsi:type="xsd:string">z</c-gensym3>
            <c-gensym5 xsi:type="xsd:string">x</c-gensym5>
            <c-gensym7 xsi:type="xsd:string">c</c-gensym7>
            <c-gensym9 xsi:type="xsd:string">v</c-gensym9>
            </namesp1:test1>

            This is not a SOAP array. Whereas return[@a] generates xml like:

            <namesp1:test1Response xmlns:namesp1="urn:Demo">
            <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[3]" xsi:type="SOAP-ENC:Array">
            <item xsi:type="xsd:string">a</item>
            <item xsi:type="xsd:string">b</item>
            <item xsi:type="xsd:string">c</item>
            </SOAP-ENC:Array>
            </namesp1:test1Response>

            >This is one reason this behaviour is undesirable. In one direction
            >(server passes array to client),
            > $a[0] (on client) = $a[0] (on server)
            >but in the other direction (client passes array to server)
            > $a[0] (on client) = $a[1] (on server)
            The 'off by one' is due to the class/object reference, and applies
            regardless of whether you're sending an array, a hash or a scalar.

            >The other reason this behaviour is undesirable is that it prevents you
            >from taking a perfectly good perl package you have written and turning
            >it into a SOAP service by just slapping on a SOAP::Transport:HTTP
            >wrapper. Array handling will be broken until you insert a shift
            >operation at the beginning of every subroutine that takes an array.
            The way to approach this is to wrap the existing function in a layer
            which discards the class and calls the function:

            package Package1;

            sub doit {
            my @array = @_;
            # do something;
            return 134;
            }

            package WrapPackage1;
            sub doit {
            my $class = shift;
            Package1::doit(@_);
            }

            >
            >Perl is not an OO language. We should stop breaking it by trying to make
            >it one.

            That's another topic!

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