ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Using HTTPAPI http_persist_req For PUT

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using HTTPAPI http_persist_req For PUT

    Preface. I sometimes get the impression that when I ask questions in a certain way that they come across in an intended fashion. Please let it be known that I am not an expert and I am not in any way insinuating anything negative about anything I am about to discuss.

    I have a need to issue a PUT verb to a web service using HTTPS. I'm having difficulty searching through the email archives for HTTPAPI support (how do you search through those archives anyway) and haven't found a solid PUT example yet. I did find an http_persist_req api that could be used but it seems there are a series of api's that I must use to properly implement http_persist_req. I can see the procedure definition in the HTTPAPI_H source file, and I'm not sure of the proper values to use for each parameter (some of them are overly obvious...peMethod = PUT, peURL = services URL).

    Has anyone performed a PUT with HTTPS using http_persist_req?


  • #2
    With regards to the archives, are you referring to this page? http://www.scottklement.com/archives/ftpapi/
    What difficulty are you having searching?

    With regards to http_persist_req() -- this is one of the persistent routines, which means it is designed to allow you to make many requests without having to disconnect/reconnect from the server. When used properly, this can greatly improve performance, but, it does require more expertise to use.

    Instead of using http_persist_req(), please consider using http_req(), http_string() or http_stmf(). These routines are meant to be very easy to use.

    Code:
    url = 'https://the-server/etc/etc';
    ResponseString = http_string('PUT': url: jsonData: 'application/json');
    This does a PUT, sends the data in the jsonData variable, and gets back it's response into 'ResponseString'. If you ever needed a POST request just replace 'PUT' with 'POST'. If you ever needed a GET, you'd just replace the 'PUT' with 'GET' and remove the last two parameters (since you don't send anything aside from the URL when you use GET).

    If you're not finding these newer routines, it's likely that you have an older version of HTTPAPI. In that case, take the time to upgrade, it's worth it.

    Comment


    • TheZenbudda
      TheZenbudda commented
      Editing a comment
      Thanks Scott. I will give those a try. Indeed, the HTTPAPI version I downloaded must be an older version because those API's do not exist. Also, I'm not familiar with the format of the email archive site. As Emmanuel mentioned below, I probably should use my Googling skills to limit my searches to your email archive. ;-)

  • #3
    In case there's an issue with a web site's search function (not to suggest there's an issue with scottklement.com!), you can always use Google to search a particular web site using the SITE: directive after the search term.

    Cheers,

    Emmanuel

    Comment


    • #4
      Scott / Emmanuel,

      Thanks for your responses.

      I can successfully execute the rest request from a Windows client called Postman. Postman has the capability to show me the http rest request header.

      I am trying to use http_stmf() for my first example. I am getting the following error:

      Code:
      The call to HTTP_STMF ended in error (C G D F).                  
      C                                                                
      Application error.  CPF9897 unmonitored by HTTPAPI04 at statement
        0000003728, instruction X'0000'.
      The statement is the execution of the http_stmf command:

      Code:
      allp http_stmf( 'PUT'                
                    : urlPath              
                    : respStmf              
                    : sendStmf              
                    : 'application/json' );
      The error doesn't seem to indicate much more than that. I turned on debug http_debug( *ON : debugFileName ) to look at the header. Everything looks great (even see the certificate being included in the debug file). However, the content-length option is set to 0. When I use postman to include a content-length of 0, it fails as well. When I remove content-length completely (from Postman), it works. How do I get http_stmf() to set the proper content-length or tell http_stmf() to not include content-length?

      I just debugged http_setoption() and found that opt = 'CONTENT-LENGTH' is not one of the options you can set. Hmm..i'll keep digging.


      It looks like SendLen is = 0 when http_persist_req is called in the http_stmf() chain of calls:

      Code:
      rc = http_persist_req( Type            
                           : comm            
                           : URL            
                           : sndFd          
                           : sndProc        
                           : SendPtr        
                           : SendLen        
                           : rcvFd          
                           : rcvProc        
                           : global.timeout  
                           : global.userAgent
                          : ct              
                          : soapAction      
                          : global.modTime );
      When closeFiles subroutine is executed, rc = 0, sndFd = 1, rcvFd = 2. I'm still trying to wrap my head around the procedure(s) that checks/reads the the send file. Something else of note, my user profile is running the job/program. I have full authority to the IFS files.


      Comment


      • #5
        It's possible that you've found a bug in http_stmf(). Do you have the same problem when you use http_string()?

        http_stmf() should be automatically calculating the content-length. The length has to be exactly the same as the length of the data you're sending, so there's no reason for it to ever by set by hand, it should be calculated from the file you're sending. It sounds like perhaps it's not -- that's why it sounds like a bug to me. I will look into that.

        In the meantime,though, http_string() should work. I use that all the time, so I know it works.

        Comment


        • #6
          Originally posted by Scott Klement View Post
          It's possible that you've found a bug in http_stmf(). Do you have the same problem when you use http_string()?

          http_stmf() should be automatically calculating the content-length. The length has to be exactly the same as the length of the data you're sending, so there's no reason for it to ever by set by hand, it should be calculated from the file you're sending. It sounds like perhaps it's not -- that's why it sounds like a bug to me. I will look into that.

          In the meantime,though, http_string() should work. I use that all the time, so I know it works.
          Thanks for your response. I was hoping to use the stmf option because your yajl api's look like they require a file and I was hoping to keep a copy of everything in an ifs for research/auditing purposes. I assume all I need to do is write the request and the response to an IFS file on my own?

          Comment


          • #7
            This was indeed a bug. I've put an updated copy of HTTPAPI on my web site that fixes the problem. Just re-download it from here:


            That will fix the problem with http_stmf().

            As for writing the data to/from the IFS on your own... you can do that, but YAJL can also do it for you if you're using that. You can do yajl_saveBuf() to get JSON you generated into an IFS file After doing that, you can use yajl_copyBuf() to copy the data into a variable or pointer in your RPG program. Now you have the data in both places... you can save the IFS copy, and send the string copy. Then, when receiving data rather than generating it, you can use yajl_buf_load_tree() to load data from a variable into YAJL, or you can use yajl_load_tree_Stmf() to load from the IFS. In this case, if you want both, you would indeed need to write it to the IFS yourself.

            Though, now that HTTPAPI has been fixed, it may be a moot point.

            Comment


            • #8
              Originally posted by Scott Klement View Post
              This was indeed a bug. I've put an updated copy of HTTPAPI on my web site that fixes the problem. Just re-download it from here:


              That will fix the problem with http_stmf().

              As for writing the data to/from the IFS on your own... you can do that, but YAJL can also do it for you if you're using that. You can do yajl_saveBuf() to get JSON you generated into an IFS file After doing that, you can use yajl_copyBuf() to copy the data into a variable or pointer in your RPG program. Now you have the data in both places... you can save the IFS copy, and send the string copy. Then, when receiving data rather than generating it, you can use yajl_buf_load_tree() to load data from a variable into YAJL, or you can use yajl_load_tree_Stmf() to load from the IFS. In this case, if you want both, you would indeed need to write it to the IFS yourself.

              Though, now that HTTPAPI has been fixed, it may be a moot point.
              Wow! That was brilliant! Thanks Scott! I will download the update shortly and check the http_stmf() api. I need to ask another question and if you think it requires its own thread, I'd be happy to start a new one. I have a need to check the HTTP response (not the web service response) for these requests. Ie. HTTP 200, HTTP 300, HTTP 400, HTTP 401, HTTP 403, HTTP 500. These messages will mean something specific when a json response is not built.

              Comment


              • #9
                If you want the response code when you use http_stmf(), you can get it by calling http_error(). There is a 2nd optional parameter that will contain the response code.

                Code:
                dcl-s respCode int(10);
                
                monitor;
                   http_stmf( ...parameters... );
                on-error;
                endmon;
                
                 http_error(*omit: respCode);
                Note that anything aside from response=200 will genrate an exception, so the above needs the MONITOR block to catch the error so you can check for 401,403,404,500, etc.

                Alternately, you can use http_req() which does not generate an exception.

                Code:
                   respCode = http_req( ... parameters ... );
                   if respCode < 1;
                      // HTTP transaction did not complete
                   endif;
                   if respCode = 1;
                        respCode = 200;
                   endif;
                
                   // respCode will now be 200 for success, or one of the valid HTTP response codes (such as 404 or 500)
                   // if an error occurred.

                Comment

                Working...
                X