6 Replies Latest reply on May 5, 2016 12:15 AM by rhardey

    How do you redirect responses to GET requests using X-APEX-FORWARD?

    rhardey

      In ORDS 3.0 (without APEX) I've successfully created POST and PUT handlers that use X-APEX-FORWARD to redirect to the newly created or updated resource's URL.  I've tried the same with a GET handler, source type of 'plsql/block' but have not been able to get it to work.  Specifically I'm trying to implement a query at a base URL that will derive a URL, then set the X-APEX-FORWARD response header value to that derived URL and  trigger a redirect.

       

      E.g. I want to issue a GET request with the following URL - https://<server>:<port>/ords/x/y/qry/?inv_number=123456

       

      The URL returned should point to the account number this invoice applies to (as an example).

       

      For demonstration purposes I have defined templates, handlers and parameters as follows:

       

      begin

         ords.define_template(p_module_name => 'y'

                             ,p_pattern     => 'qry/'

                             ,p_comments    => '');

       

         ords.define_handler(p_module_name    => 'y'

                            ,p_pattern        => 'qry/'

                            ,p_method         => 'GET'

                            ,p_source_type    => 'plsql/block'

                            ,p_source         =>

      'begin

         if :inv_number is not null then

            for rec in (select utl_url.escape(''../accs/i.account_number||''/'') account_url

                          from invoices i

                         where i.invoice_number = :inv_number)

            loop

               :location := rec.open_invoices_url;

               :status := 302;

            end loop;

         else

            htp.p(''...'');

            :status := 200;

         end if;

      end;

      '

                            ,p_items_per_page => 25);

       

         ords.define_parameter(p_module_name         => 'y'

                              ,p_pattern            => 'qry/'

                              ,p_method              => 'GET'

                              ,p_name                => 'X-APEX-FORWARD'

                              ,p_bind_variable_name  => 'location'

                              ,p_source_type         => 'HEADER'

                              ,p_param_type          => 'STRING'

                              ,p_access_method       => 'OUT'

         );

       

         ords.define_parameter(p_module_name         => 'y'

                              ,p_pattern             => 'qry/'

                              ,p_method              => 'GET'

                              ,p_name                => 'X-APEX-STATUS-CODE'

                              ,p_bind_variable_name  => 'status'

                              ,p_source_type         => 'HEADER'

                              ,p_param_type          => 'INT'

                              ,p_access_method       => 'OUT'

         );

       

         commit;

      end;

       

      I'm not sure what is materially different here from what I am doing in my POST and PUT requests, but this invocation will not return anything.  If I put an htp.p() expression within the loop to display the selected value, this shows when called by a client, so the problem is not with the data.

       

      Any help on this greatly appreciated.

       

      Regards,

      Ryan.

        • 1. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
          Kiran Pawar

          Hi rhardey,

          rhardey wrote:

           

          In ORDS 3.0 (without APEX) I've successfully created POST and PUT handlers that use X-APEX-FORWARD to redirect to the newly created or updated resource's URL.  I've tried the same with a GET handler, source type of 'plsql/block' but have not been able to get it to work.  Specifically I'm trying to implement a query at a base URL that will derive a URL, then set the X-APEX-FORWARD response header value to that derived URL and  trigger a redirect.

           

          E.g. I want to issue a GET request with the following URL - https://<server>:<port>/ords/x/y/qry/?inv_number=123456

               The hint is to use the {location} parameter which is mapped to the X-APEX-FORWARD Header. This will make a GET call for the new resource (you must specify the new resource path and have a GET for it).

               Refer: ORDS Return JSON object in POST call result

           

          Regards,

          Kiran

          • 2. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
            rhardey

            Hi Kiran,

             

            Thanks for your reply.  That is in fact what I am trying to do in the code above but I am not getting the results I expect.  If I modify the above script slightly to make it a POST request I get the behaviour I want, but I can't get it to work as a GET request.

             

            Do I need to configure something in addition to the above for GET requests?

             

            Regards,

            Ryan.

            • 3. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
              IoanaIo

              Hi,

              for GET calls the handler should look like that:

              ords.define_handler(p_module_name    => 'y'

                                    ,p_pattern        => 'qry/'

                                    ,p_method         => 'GET'

                                    ,p_source_type    => ords.source_type_collection_item,

                                    ,p_source         => 'select 1 from dual'

                                    ,p_items_per_page => 1);


              !! no need to define parameters and pay attention to the p_source_type parameter - it changes;


              if you call it .../y/qry/ it will return a json object containing 1:

               

              {

                "items": [

                  {

                    "1": 1

                  }

                ]

              ............



              if the select returns multiple rows, use: p_source_type    => ords.source_type_collection_feed,

                                                        ........

                                                        p_items_per_page => 25


              Hope it helps!!!

              • 4. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
                rhardey

                Hullo 3220653,

                 

                Thanks for your response, but I don't think you've understood my question.

                 

                In a nutshell I would like for a user to execute a query against one URL which derives a URL to another resource, then have the response be what would be returned if the derived URL had been what was requested in the first place.

                 

                I am trying to model it on how X-APEX-FORWARD is handled for POST requests (which I can do, I don't need examples of that).

                 

                E.g:

                 

                Original request:

                GET /ords/xxx/?parm1=y

                Host: my.server.com

                 

                Behind the scenes the GET handler derives the following URL: http://my.server.com/ords/xxx/some/resource/123456

                 

                The response would be something like

                 

                Response headers include:

                Content-Location: http://my.server.com/ords/xxx/some/resource/123456

                 

                Response body:

                {

                     "id":"123456",

                     "attr1":"xyz",

                     "attr2":"123",

                     ...

                }

                 

                Any help appreciated.

                 

                Regards,

                Ryan.

                • 5. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
                  Kris Rice-Oracle

                  The basic question is from a GET with a QUERY type, you can't do this.  You'll have to have a PL/SQL source type and the same code from your POST example will work.

                   

                  -kris

                  • 6. Re: How do you redirect responses to GET requests using X-APEX-FORWARD?
                    rhardey

                    Hi Kris,

                     

                    Thanks for your response.  I think things have been obscured a little bit since I first asked this question, but the GET handler I have defined does have a PL/SQL source, NOT a query source.  At the risk of boring you I've put together a complete script for reproducing what I have currently in my stand-alone installation of ORDS.  There are three templates, one (pattern 'redir/:an/'), is what I'm using to redirect to, the other two try to use X-APEX-FORWARD to redirect to URLs based on this template.  One has a POST handler (pattern 'post_request/') and successfully redirects, the other has a GET handler (with PL/SQL source) and does not successfully redirect.  There is no substantive difference between these handlers other than one uses the GET method and the other the POST method. 

                     

                    Using curl I get the following:

                     

                    C:\>curl -d "{\"parm1\":\"there\"}" -H "Content-Type: application/json" http://localhost:8080/ords/ords_forum_test/test/post_request/

                    {"url_segment":"there","links":[{"rel":"collection","href":"http://localhost:8080/ords/ords_forum_test/test/redir/"},{"rel":"self","href":"http://localhost:8080

                    /ords/ords_forum_test/test/redir/there/"}]}

                     

                    C:\>curl -G http://localhost:8080/ords/ords_forum_test/test/get_request/?parm1=not%20there

                    parm1 = not there

                     

                    This second call shows by the output that the handler has been called, it's just that setting the :location bind variable does not seem to be triggering a redirect.

                     

                    Thanks for any help you can provide.

                     

                    Regards,

                    Ryan.

                     

                     

                    And here are the steps in my script:

                     

                    SQL> create user ords_forum_test identified by ords_forum_test;

                     

                    User created.

                     

                    SQL> grant create session to ords_forum_test;

                     

                    Grant succeeded.

                     

                    SQL> connect ords_forum_test/ords_forum_test

                    Connected.

                     

                    SQL> ords.enable_schema;

                     

                    PL/SQL procedure successfully completed.

                     

                    SQL> commit;

                     

                    Commit complete.

                     

                    begin

                     

                     

                       --

                       -- 'test' module creation.

                       --

                     

                     

                       ords.define_module(p_module_name    => 'test'

                                         ,p_base_path      => 'test/'

                                         ,p_comments       => '');

                     

                     

                       ords.define_template(p_module_name => 'test'

                                           ,p_pattern     => 'get_request/'

                                           ,p_comments    => '');

                     

                     

                       ords.define_handler(p_module_name    => 'test'

                                          ,p_pattern        => 'get_request/'

                                          ,p_method         => 'GET'

                                          ,p_source_type    => 'plsql/block'

                                          ,p_source         =>

                    'begin

                       if :parm1 is not null then

                          :location := ''../redir/''||:parm1||''/'';

                          htp.p(''parm1 = ''||:parm1);

                          :status := 302;

                       else

                          htp.p(''...'');

                          :status := 200;

                       end if;

                    end;'

                                          ,p_items_per_page => 25);

                     

                     

                       ords.define_parameter(p_module_name         => 'test'

                                            ,p_pattern            => 'get_request/'

                                            ,p_method              => 'GET'

                                            ,p_name                => 'X-APEX-FORWARD'

                                            ,p_bind_variable_name  => 'location'

                                            ,p_source_type         => 'HEADER'

                                            ,p_param_type          => 'STRING'

                                            ,p_access_method       => 'OUT');

                     

                     

                       ords.define_parameter(p_module_name         => 'test'

                                            ,p_pattern             => 'get_request/'

                                            ,p_method              => 'GET'

                                            ,p_name                => 'X-APEX-STATUS-CODE'

                                            ,p_bind_variable_name  => 'status'

                                            ,p_source_type         => 'HEADER'

                                            ,p_param_type          => 'INT'

                                            ,p_access_method       => 'OUT');

                     

                     

                       ords.define_template(p_module_name => 'test'

                                           ,p_pattern     => 'post_request/'

                                           ,p_comments    => '');

                     

                     

                       ords.define_handler(p_module_name    => 'test'

                                          ,p_pattern        => 'post_request/'

                                          ,p_method         => 'POST'

                                          ,p_source_type    => 'plsql/block'

                                          ,p_source         =>

                    'begin

                       if :parm1 is not null then

                          :location := ''../redir/''||:parm1||''/'';

                          htp.p(''parm1 = ''||:parm1);

                          :status := 302;

                       else

                          htp.p(''...'');

                          :status := 200;

                       end if;

                    end;'

                                          ,p_items_per_page => 25);

                     

                     

                       ords.define_parameter(p_module_name         => 'test'

                                            ,p_pattern            => 'post_request/'

                                            ,p_method              => 'POST'

                                            ,p_name                => 'X-APEX-FORWARD'

                                            ,p_bind_variable_name  => 'location'

                                            ,p_source_type         => 'HEADER'

                                            ,p_param_type          => 'STRING'

                                            ,p_access_method       => 'OUT');

                     

                     

                       ords.define_parameter(p_module_name         => 'test'

                                            ,p_pattern             => 'post_request/'

                                            ,p_method              => 'POST'

                                            ,p_name                => 'X-APEX-STATUS-CODE'

                                            ,p_bind_variable_name  => 'status'

                                            ,p_source_type         => 'HEADER'

                                            ,p_param_type          => 'INT'

                                            ,p_access_method       => 'OUT');

                     

                     

                       --

                       -- 'redir/:an/' template creation.

                       --

                     

                     

                       ords.define_template(p_module_name => 'test'

                                           ,p_pattern     => 'redir/:an/'

                                           ,p_comments    => '');

                     

                     

                     

                     

                       --

                       -- 'redir/:an/' 'GET' handler creation.

                       --

                     

                     

                       ords.define_handler(p_module_name    => 'test'

                                          ,p_pattern        => 'redir/:an/'

                                          ,p_method         => 'GET'

                                          ,p_source_type    => 'json/item'

                                          ,p_source         =>

                    'select ''.'' "$self"

                          ,:an url_segment

                      from dual'

                                          ,p_items_per_page => 25);

                     

                     

                       commit;

                     

                     

                    end;

                    /

                     

                    PL/SQL procedure successfully completed.

                     

                    SQL> exit;

                     

                    C:\>curl -G http://localhost:8080/ords/ords_forum_test/test/redir/here/

                    {"url_segment":"here","links":[{"rel":"collection","href":"http://localhost:8080/ords/ords_forum_test/test/redir/"},{"rel":"self","href":"http://localhost:8080/

                    ords/ords_forum_test/test/redir/here/"}]}

                     

                    C:\>curl -d "{\"parm1\":\"there\"}" -H "Content-Type: application/json" http://localhost:8080/ords/ords_forum_test/test/post_request/

                    {"url_segment":"there","links":[{"rel":"collection","href":"http://localhost:8080/ords/ords_forum_test/test/redir/"},{"rel":"self","href":"http://localhost:8080

                    /ords/ords_forum_test/test/redir/there/"}]}

                     

                    C:\>curl -G http://localhost:8080/ords/ords_forum_test/test/get_request/?parm1=not%20there

                    parm1 = not there