Page 1 of 1
Persistent connection
Posted: Wed Oct 19, 2022 9:50 pm
by Alan5432
I'm trying to do multiple http_req('POST'... operations through TLS and it appears to be closing the connection after each post response is processed. Is there something that can be done to continue to re-use the established connection until the timeout is reached?
Code: Select all
recvresp(): entered
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Date: Wed, 19 Oct 2022 20:04:53 GMT
Content-Length: 2442
Strict-Transport-Security: max-age=15552000; includeSubDomains
SetError() #13: HTTP/1.1 200 OK
recvresp(): end with 200
recvdoc parms: identity 2442
header_load_cookies() entered
recvdoc(): entered
SetError() #0:
recvdoc(): Receiving 2442 bytes.
...
http_close(): entered
HTTPAPI Ver 1.45 released 2021-09-20
NTLM Ver 1.4.0 released 2014-12-22
OS/400 Ver V7R4M0
http_persist_open(): entered
Re: Persistent connection
Posted: Wed Oct 19, 2022 10:14 pm
by Scott Klement
You would need to change your code to call the following routines:
- http_persist_open(): This establishes the initial connection to the server that will persist. This returns a connection handle to the opened connection.
- http_persist_req(): This may be called many times (with a different URL each time, provided that it points to the same host/port) with the connection handle from step 1. Calling this with the connection handle ensures that it uses the already open connection. If for some reason you get a network error on that connection, you will have to close the connection and call http_persist_open again.
- http_persist_close(): This is called when you are ready to disconnect from the server.
Re: Persistent connection
Posted: Fri Nov 04, 2022 8:59 pm
by Alan5432
I'm struggling with http_persist_req(). I'm using string variables for my send and receive and the send is working fine. In http_req the RcvProc is set to the %PADDR of RcvToBuf, but I don't think I have access to that internal procedure.
I saw several examples that used the IFS for the receive with - http_persist_get( pComm: URL: fd: %paddr('write')).
What do I use for the peSaveProc (procptr) parameter in http_persist_req if I'm using a string variable?
Re: Persistent connection
Posted: Mon Nov 07, 2022 3:33 am
by Scott Klement
You would need to provide your own subprocedure that puts the data into a string variable.
Here's a simple example:
Code: Select all
**free
Ctl-Opt DFTACTGRP(*NO) ACTGRP(*NEW) BNDDIR('HTTPAPI');
/define WEBFORMS
/copy qrpglesrc,httpapi_h
Dcl-C CRLF CONST(x'0D25');
Dcl-S rc Int(10);
Dcl-S fromAddr Varchar(100);
Dcl-S Subject Varchar(100);
Dcl-S Message Varchar(1000);
Dcl-S formData Varchar(32767);
dcl-s result varchar(500000) ccsid(*utf8);
dcl-s url varchar(500);
dcl-s comm pointer;
http_debug(*on: '/tmp/persist_example_log.txt');
//
// CHANGE THIS TO YOUR E-MAIL ADDRESS:
//
FromAddr = 'example4@scottklement.com';
//
// CHANGE THIS TO THE SUBJECT YOU'D LIKE SENT TO ME:
//
Subject = 'EXAMPLE4 from HTTPAPI.';
//
// CHANGE THIS TO THE MESSAGE YOU'D LIKE SENT TO ME:
//
Message = 'Hi Scott!' + CRLF +
' Just a note to tell you that I''m testing out the +
EXAMPLE4 program in HTTPAPI. If you receive this, it +
must work!' + CRLF;
//
// Encode the data as it would appear on a web form
//
formData = 'from=' + http_urlEncode(FromAddr)
+ '&subject=' + http_urlEncode(Subject)
+ '&Comment=' + http_urlEncode(message);
url = 'http://www.scottklement.com/cgi-bin/email_comment.cgi';
comm = http_persist_open(url);
if comm = *null;
http_crash();
endif;
result = '';
rc = http_persist_req( 'POST'
: comm
: url
: 0
: *null
: %addr(formData:*data)
: %len(formData)
: 0
: %paddr(Save2String)
: HTTP_TIMEOUT
: *omit
: 'application/x-www-form-urlencoded' );
if rc=302;
rc = http_persist_req( 'GET'
: comm
: http_redir_loc()
: 0
: *null
: *null
: 0
: 0
: %paddr(Save2String) );
endif;
// the "result" variable now contains the result of calling the server.
// perform additional requests (must be to the same server) by calling http_persist_req
// more times here.
http_persist_close(comm);
//
// If there's an error, use the DSPLY opcode to show it on the
// screen. If not, use the DSPF command from OS/400 to display
// the data that was returned onto the screen.
//
if rc <> 1;
http_crash();
endif;
*inlr = *on;
dcl-proc save2string;
dcl-pi *n int(10);
fd int(10) value;
data char(65535) options(*varsize) ccsid(*utf8);
len int(10) value;
end-pi;
if len > 0;
result += %subst(data:1:len);
endif;
return len;
end-proc;
fwiw, http_persist_req is considered a "lower level" routine, intended more for flexibility than for easy of use. If you're making many requests of the same server in a short amount of time, the fact that it leaves the connection open can make a huge performance difference. Most people don't need that, so this is really just out there for a few people (and for internal use of HTTPAPI) that need to do something special.