ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Help me with This page requires a user-id & password using HTTPAPI

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

  • Help me with This page requires a user-id & password using HTTPAPI

    Hi everyone,

    Please, I'm using HTTPAPI v1.4 and I need to solve this error: This page requires a user-id & password

    The API-REST only requires authentication using the header parameters that are username and password.
    • Request Postman (Works 100% all time)
    Code:
    GET /Api/CardFormats? HTTP/1.1
    Host: 192.168.1.XX:444
    Content-Type: application/xml
    Accept: application/xml
    Username: user
    Password: password
    cache-control: no-cache
    • My Code:
    Code:
      http_debug(*on);
      http_setAuth(HTTP_AUTH_NONE: '': '');                    
    http_xproc( HTTP_POINT_ADDL_HEADER: *null );              
    http_xproc( HTTP_POINT_ADDL_HEADER: %paddr(add_headers) );
    
    Response = *blanks;                                      
    ResCode  = *blanks;                                      
    ResMessage = *blanks;                                    
    
       monitor;                                              
          Response = http_string( %trim(Method): %trim(URL):  
                     %trim(BodyCont): %trim(ContentType) );  
          http_error(*omit: httpstatus);                      
          ResCode = %char(0);                                
          ResMessage = %char(httpstatus);                    
       on-error;                                              
          ResCode = %char(9);                                
          ResMessage = http_error();                          
       endmon;                                               
         *inlr = *on;
     
      *******************************************************************
      P add_headers     B                                  
    D                 PI                                
    D headers                    32767A   varying        
    D CRLF            C                   x'0d25'        
     /FREE                                              
         headers = 'Content-Type: application/xml' + CRLF
                 + 'Accept: application/xml' + CRLF      
                 + 'Username: ' + %trim(user) + CRLF    
                 + 'Password: ' + %trim(pass) + CRLF;    
     /END-FREE
    • httpapidebug.txt
      • In some cases the response is:
    Code:
    Protocol Used: TLS Version 1.2  
    http_persist_req(GET) entered.  
    http_long_ParseURL(): entered  
    http_long_ParseURL(): entered  
    do_oper(GET): entered          
    There are 0 cookies in the cache
    GET /Api/CardFormats HTTP/1.1  
    Host: 192.168.1.XX:444          
    User-Agent: http-api/1.39      
    Content-Type: application/xml  
    Accept: application/xml        
    USERNAME: user             
    PASSWORD: password            
       
      recvresp(): entered                        
    HTTP/1.1 200 OK                            
    Cache-Control: no-cache                    
    Pragma: no-cache                            
    Content-Type: application/xml; charset=utf-8
    Expires: -1                                
    Server: Microsoft-IIS/8.5                  
    Strict-Transport-Security: max-age=31536000
    JWT: xxx
    Content-Security-Policy: script-src 'self';
    X-AspNet-Version: 4.0.30319                
    X-Powered-By: [URL="http://ASP.NET"]ASP.NET[/URL]                      
    Date: Thu, 05 Sep 2019 15:44:53 GMT        
    Content-Length: 504                        
      SetError() Ñ13: HTTP/1.1 200 OK
    recvresp(): end with 200      
    recvdoc parms: identity 504   
      recvdoc parms: identity 504    
    header_load_cookies() entered  
    recvdoc(): entered            
    SetError() Ñ0:                
    recvdoc(): Receiving 504 bytes.
    <XMLRESPONSE>...
    http_close(): entered
      • If I try to consume several times, it succeeds without problem. But from one moment to another it stops working and begins to respond:

    Code:
    Protocol Used: TLS Version 1.0  
    http_persist_req(GET) entered.  
    http_long_ParseURL(): entered  
    http_long_ParseURL(): entered  
    do_oper(GET): entered          
    There are 0 cookies in the cache
    GET /Api/CardFormats HTTP/1.1  
      Host: 192.168.1.XX:444                                                      
    User-Agent: http-api/1.39                                                  
    Content-Type: application/xml                                              
    Accept: application/xml                                                    
    USERNAME: user                                                         
    PASSWORD: password                                                        
    
    recvresp(): entered                                                        
    HTTP/1.1 401 192.168.1.7                                                    
    Cache-Control: no-cache                                                    
    Pragma: no-cache                                                            
    Content-Length: 238                                                        
    Content-Type: text/plain; charset=utf-8                                    
    Expires: -1                                                                
    Server: Microsoft-IIS/8.5                                                  
    Strict-Transport-Security: max-age=31536000                                
    Content-Security-Policy: script-src 'self'; style-src 'self' 'unsafe-inline'
      X-AspNet-Version: 4.0.30319                                                
    X-Powered-By: [URL="http://ASP.NET"]ASP.NET[/URL]                                                      
    Date: Thu, 05 Sep 2019 15:18:32 GMT                                        
    
    SetError() Ñ13: HTTP/1.1 401 192.168.1.7                                  
    recvresp(): end with 401                                                  
    recvdoc parms: identity 238                                                
    SetError() Ñ36: This page requires a user-id & password                    
    AuthPlugin_mustReceiceAuthErrorPage(): entered                            
    http_close(): entered
    This happens frequently and is intermittent.

    Thank you in advance for your help,





  • #2
    Just a quick thought, does the service you are using have any sort of "quota" limits in force.?
    I have run into a site which allowed only so many calls per some period of time. It gave me the same response as your are indicating. "This page requires a user-id & password"
    I was only able to discern the actual problem by talking to the web administrator directly. And subsequently avoided the issue by self imposed timing rules, ie. so many calls per period of time.
    Very frustrating but I was not in a position to request or require otherwise. Good luck.

    Comment


    • #3
      Hi Roverbyte and thanks for answering,

      I thought about the same thing when it happened to me the first time. However, I tried to consume the web service at the same time from my IBM i and from PostMan under Linux. And even, I also consumed it several times from PostMan. But in Postman always answer correctly. And in the IBM i sometimes it responds well and sometimes it responds erroneously.

      I'm really very confused and I don't know if there are global variables that are freezing inside the API. Do you know if there is any way to clean the whole environment?

      I was also investigating that the http_string method opens a persistent session, but I did not find any method to close the session or to verify this.

      Comment


      • #4
        Maybe reporting your issue to the web service to see if they can give you a method to clean/close or some feedback as to the difference in behavior between environments?

        Comment


        • #5
          Have you asked the service provider what they are seeing on their end? Seems to me that they should be able to look at their end and see what is happening.

          Also - I don't know Postman - but I know with SoapUI I can set up a load test and have it loop through a series of attempts - have you tried something like that with postman? It could just be coincidence that it always seems to work from there.

          Comment


          • #6
            have u tried by putting the user and password in the http_setauth-function directly ?

            Code:
            d rc              s             10I 0
            d peAuthType      s              1A
            d peUsername      s             80A
            d pePasswd        s           1024A
            
            peAuthType = HTTP_AUTH_NONE;
            rc = http_setauth(peAuthType:peUsername:pePasswd);
            if rc = 0;
              //connection ok
            else;
              //connection failed
            endif;

            Comment


            • #7
              Please don't attempt to code the HTTP protocol yourself.

              You appear to be manually trying to set your own HTTP headers rather than using HTTPAPI's functionality that does that for you. If you understand what you're doing, its possible to make that work properly. But, do you really want to learn the internals of the HTTP protocol to make sure you're doing it right?

              The way you're doing Content-Type will result in a duplicate header.

              The way you're doing Username/Password won't work at all with a typical HTTP server as it does not do the necessary encoding.

              In HTTPAPI, you are provided with subprocedures to call and parameters to pass to do all of these things. Please at least start by trying to use these. See if they work for you, and if not, then find out why not rather than inventing your own code.

              Use http_SetAuth() to set the userid/password. However, please try HTTP_AUTH_BASIC (not "NONE" like the previous post... HTTP_AUTH_NONE actually means to NOT send a userid/password!)

              Use the parameter for content-type when you call http_string instead of manually adding a content-type header.

              Comment


              • #8
                Hi roverbyte, JonBoy, pet0etie and Scott Klement,

                Maybe reporting your issue to the web service to see if they can give you a method to clean/close or some feedback as to the difference in behavior between environments?
                No, it is an API developed and implemented with many other clients. We are not talking about a custom development.

                Have you asked the service provider what they are seeing on their end? Seems to me that they should be able to look at their end and see what is happening.

                Also - I don't know Postman - but I know with SoapUI I can set up a load test and have it loop through a series of attempts - have you tried something like that with postman? It could just be coincidence that it always seems to work from there.
                Although I am not the owner of the API, I have it installed on my server. Therefore, I will install a sniffer to review the http request. I already checked the IIS logs and they don't give me much information. Thank you.

                Please don't attempt to code the HTTP protocol yourself.

                You appear to be manually trying to set your own HTTP headers rather than using HTTPAPI's functionality that does that for you. If you understand what you're doing, its possible to make that work properly. But, do you really want to learn the internals of the HTTP protocol to make sure you're doing it right?

                The way you're doing Content-Type will result in a duplicate header.

                The way you're doing Username/Password won't work at all with a typical HTTP server as it does not do the necessary encoding.

                In HTTPAPI, you are provided with subprocedures to call and parameters to pass to do all of these things. Please at least start by trying to use these. See if they work for you, and if not, then find out why not rather than inventing your own code.

                Use http_SetAuth() to set the userid/password. However, please try HTTP_AUTH_BASIC (not "NONE" like the previous post... HTTP_AUTH_NONE actually means to NOT send a userid/password!)

                Use the parameter for content-type when you call http_string instead of manually adding a content-type header.
                Good morning Scott,
                the first thing is to thank you for giving me an answer. The truth is that it is an honor for me.

                The truth is that my code is quite obfuscated and redundant due to the desperate actions in which I have tried to solve the problem. For example:

                Code:
                  
                 Response = http_string( %trim(Method): %trim(URL):  %trim(BodyCont):[B] %trim(ContentType)[/B] );
                //and
                headers = 'Content-Type: application/xml' + CRLF
                // Or the misuse of cleaning the authentication method with:
                http_xproc( HTTP_POINT_ADDL_HEADER: *null );
                I ask that you please excuse me for attempting the HTTP protocol with my code. And the truth is that I only need a request with URL, Method and Header (Without authentication). But in the Header, I need: Content-Type, Accept, Username and Password. Nothing else. And there is something that does not allow me that all requests are all successful. I do not know what it is. The same program can respond randomly according to what I see in the IIS Log the following:

                Code:
                2019-09-06 13:44:05 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X http-api/1.39 - 401 0 0 1221
                2019-09-06 13:47:49 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X PostmanRuntime/7.6.0 - 200 0 0 10
                2019-09-06 13:52:21 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X http-api/1.39 - 200 0 0 195
                I will review the request on the server with a sniffer and tell you how it goes. Thank you for your valuable time,

                Comment


                • #9
                  Reading this over again, I noticed that the PostMan example is doing a GET request. But, your HTTPAPI example is sending its payload as a request body (the "BodyCont" variable.) That doesn't make sense as a GET request doesn't send a request body.

                  Can you please provide full details about what is working in PostMan so we can tell you how to do the same thing in HTTPAPI?

                  Comment


                  • #10
                    Good morning Scott,
                    the first thing is to thank you for giving me an answer. The truth is that it is an honor for me.

                    The truth is that my code is quite obfuscated and redundant due to the desperate actions in which I have tried to solve the problem. For example:

                    Code:
                      
                     Response = http_string( %trim(Method): %trim(URL):  %trim(BodyCont):[B] %trim(ContentType)[/B] );
                    //and
                    headers = 'Content-Type: application/xml' + CRLF
                    // Or the misuse of cleaning the authentication method with:
                    http_xproc( HTTP_POINT_ADDL_HEADER: *null );
                    I ask that you please excuse me for attempting the HTTP protocol with my code. And the truth is that I only need a request with URL, Method and Header (Without authentication). But in the Header, I need: Content-Type, Accept, Username and Password. Nothing else. And there is something that does not allow me that all requests are all successful. I do not know what it is. The same program can respond randomly according to what I see in the IIS Log the following:

                    Code:
                    2019-09-06 13:44:05 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X http-api/1.39 - 401 0 0 1221
                    2019-09-06 13:47:49 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X PostmanRuntime/7.6.0 - 200 0 0 10
                    2019-09-06 13:52:21 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.X http-api/1.39 - 200 0 0 195
                    I will review the request on the server with a sniffer and tell you how it goes. Thank you for your valuable time,

                    Comment


                    • #11
                      Originally posted by Scott Klement View Post
                      Reading this over again, I noticed that the PostMan example is doing a GET request. But, your HTTPAPI example is sending its payload as a request body (the "BodyCont" variable.) That doesn't make sense as a GET request doesn't send a request body.

                      Can you please provide full details about what is working in PostMan so we can tell you how to do the same thing in HTTPAPI?
                      This is my request PostMan:

                      Click image for larger version

Name:	Captura de pantalla de 2019-09-06 13-59-29.png
Views:	688
Size:	50.4 KB
ID:	151175

                      Comment


                      • #12
                        So you are not sending any data at all? Just the headers?

                        Can you explain why you are ssending a content-type if you are not sending any data? You are telling the server "here is the type of content I am sending", but you aren't sending any data?

                        Comment


                        • #13
                          Originally posted by Scott Klement View Post
                          So you are not sending any data at all? Just the headers?

                          Can you explain why you are ssending a content-type if you are not sending any data? You are telling the server "here is the type of content I am sending", but you aren't sending any data?
                          You're right. The truth is that the first method to consume that I found documented from HTTPAPI was http_string. I am not an RPG programmer and I usually work with Cobol. So, my goal is to build a PGM that can easily invoke from a CL or from Cobol.

                          Therefore, I thought I could leave the Content-Type without any collateral effects for all GET, POST, PUT, etc. requests. Because I really need to consume an API-REST with many microservices and different methods. In PostMan I have no problems if I pass the Content-Type for all methods.

                          Do you think that if I pass * OMIT in Content-Type when the request is GET my problem is solved?

                          Comment


                          • #14
                            I can't promise that any of this will solve the problem, as I don't understand the problem that you're experiencing.

                            I am only doing my best to look at the code you've posted and try to tell you what does and/or doesn't make sense.

                            Comment


                            • #15
                              Hi Scott,

                              My new code:
                              Code:
                                 http_xproc( HTTP_POINT_ADDL_HEADER: %paddr(add_headers) );
                              
                                 monitor;                                               
                                    Response = http_string( %trim(Method): %trim(URL):  
                                               *OMIT: *OMIT );                          
                                    http_error(*omit: httpstatus);                      
                                    ResCode = %char(0);                                 
                                    ResMessage = %char(httpstatus);                     
                                 on-error;                                              
                                    ResCode = %char(9);                                 
                                    ResMessage = http_error();                          
                                 endmon;                                               
                                 *inlr = *on;
                              *************************************************
                              P add_headers     B                             
                              D                 PI                            
                              D headers                     1024A   varying   
                              D CRLF            C                   x'0d25'   
                               /FREE                                          
                                   headers = 'Accept: application/xml' + CRLF
                                           + 'Username: ' + %trim(user) + CRLF
                                           + 'Password: ' + %trim(pass) + CRLF
                                           + 'cache-control: no-cache' + CRLF;
                               /END-FREE                                      
                              P                 E

                              My IIS Target Log (1 = Program RPG) / (2 = PostMan or SoapUI)
                              Code:
                              date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(Referer) sc-status sc-substatus sc-win32-status time-taken Username Password Content-Type Accept
                              [B](1)[/B] 2019-09-06 21:30:53 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.XX - [B]401[/B] 0 0 1025 username password application/xml
                              [B](2)[/B] 2019-09-06 21:31:20 192.168.1.XX GET /Api/CardFormats - PORT - 192.168.1.XX - [B]200[/B] 0 0 2168 username password application/xml
                              Thanks,

                              Comment

                              Working...
                              X