2 Replies Latest reply on Jun 10, 2015 8:36 AM by Colm Divilly-Oracle

    Restful API :body variable

    SaraB

      Hi

       

      We have a number of RESTful APIs that we've written and are now in use. These all seem to work fine and the POST and PUT APIs all use the built-in variables that are created from the request body. For example, if the request body is

       

      {"display_name":"My Big Company Name"}

       

      then the API code refers to :display_name to get the value.

       

      To make the APIs more robust and to help support our clients we want to add some debug code to record what the users are sending in the request body. For this the obvious thing to use is :body which stores the request body as a BLOB. However, if you so much as look at :body it is set to null and so are all the built-in variables, regardless of the order you do things in.

       

      So say we had code that used the request body above:

       

      begin

         update my_table

         set      display_name = :display_name

         where  id = :ID;

      end;

       

      ID is specified in the API URL as {ID} and this all works fine. But if we change the code to be:

       

      begin

         update my_table

         set      display_name = :display_name

         where  id = :ID;

         insert into my_debug_table (request_body) values (:body);

      end;

       

      This doesn't work and :display_name is null. This can be seen in a simpler example, if you have a POST API and pass anything in the body then have your API code as:

       

      begin

        htp.p(dbms_lob.getlength(:body)||' - '||dbms_lob.getlength(:body));

      end;

       

      You will see the output as n - 0 where n is the length of your request body and 0 is what it's set to after you've touched it.

       

      Obviously all this code is greatly simplified. Our API requests have large JSON objects, lots of variables, validations and processing which is why storing the request body would be so useful to us. What I can't figure out is why all the variables are set to null even if you reference :body at the end of the code.

       

      I have tried googling and searching the forum, but there is very little information available on these variables.

       

      So is there a way to use the variables and also the :body? And why does everything get set to null?

       

      Many thanks for your help

      Sara

       

      PS. Also posted in APEX forum Restful API :body variable as using APEX 4.2.5 and also tested in APEX 5.

        • 1. Re: Restful API :body variable
          SaraB

          Hi

           

          Just wondered if anyone had any thoughts on this or had even seen it before? I can't see that it's limited to just our environment as I've reproduced on apex.oracle.com. We'd really like to use the :body variable, but there just doesn't seem to be any way to do this.

           

          It also seems really bizarre that it's blank and all other variables are blank after you've referenced it.

           

          Any ideas are really appreciated!!

           

          Many thanks

          Sara

          • 2. Re: Restful API :body variable
            Colm Divilly-Oracle

            The request body is a stream, the client sends it once, and the server can only read it once. So you have a choice either you can use the named binds and let ORDS parse the JSON for you, or use :body and read and parse the body yourself. You cannot do both, because to do so requires buffering, and if the request is large buffering will not scale.

             

            It sounds like you have a need to process more complex documents that the simple key value pattern that ORDS can automatically parse, so it sounds like you just need to switch to using :body alone.

             

            Note also that you need to assign the :body instance to a local variable, and then operate on the local variable, so for example the following will not work robustly:

             

            begin

            do_something(:body);

            do_something_else(:body);

            end;

             

            whereas the following will:

             

            declare

            l_body blob;

            begin

            l_body := :body;

            do_something(l_body);

            do_something_else(l_body);

            end;