The following examples are https://
, demonstrating secure REST XMLSERVICE.
The modern languages featured below run on IBM i (new LPP OPS), but also run remote from laptop, cloud, etc.
Example languages demonstrates actual XML send to/from XMLSERVICE (no toolkits).
With this information, and, Google XML parsing in language, you can build your own https://
REST toolkits, in any language.
https://
)
https://
)The Common 2015 lab features simple PASE CGI xmlservice calls. This is not the fastest method, but it demonstrates both command line and PASE CGI as one-and-the-same. Most of these languages provide built-in web servers, usually simple proxy/reverse-proxy to Apache. However, most languages can also be configured to run with Apache as CGI and FastCGI.
#!/QOpenSys/opt/freeware/bin/bash export PASSWORD=(see instructor) mydir=$(dirname $PATH_TRANSLATED) cd $mydir myscript=$(basename $PATH_TRANSLATED) if [[ $myscript == *".py"* ]] then result=$(/QOpenSys/opt/freeware/bin/python $myscript) elif [[ $myscript == *".php"* ]] then result=$(env) elif [[ $myscript == *".rb"* ]] then result=$(/QOpenSys/usr/bin/ruby $myscript) elif [[ $myscript == *".js"* ]] then result=$(/usr/bin/node $myscript) elif [[ $myscript == *".sh"* ]] then result=$(exec $myscript) elif [[ $myscript == *".java"* ]] then myscript=$(basename $PATH_TRANSLATED | awk '{ gsub(/.java/,""); print }') result=$(/QOpenSys/usr/bin/java $myscript) else result="<html><body>unsupported type ($myscript)</body></html>" fi if [[ $result == *"<html>"* ]] then printf "Content-Type: text/html\n\n" else printf "Content-Type: text/xml\n\n" fi echo $result #echo '<pre>' #env #echo '</pre>'
; Static PHP servers for default user Server type="application/x-httpd-php" CommandLine="/usr/local/zendsvr6/bin/php-cgi.bin" StartProcesses="1" SetEnv="LIBPATH=/usr/local/zendsvr6/lib" SetEnv="PHPRC=/home/xml/etc" SetEnv="PHP_FCGI_CHILDREN=10" SetEnv="PHP_FCGI_MAX_REQUESTS=0" ConnectionTimeout="30" RequestTimeout="60" SetEnv="CCSID=1208" SetEnv="LANG=C" SetEnv="INSTALLATION_UID=100313092601" SetEnv="LDR_CNTRL=MAXDATA=0x40000000" SetEnv="ZEND_TMPDIR=/usr/local/zendsvr6/tmp" SetEnv="TZ=<EST>5<EDT>,M3.2.0,M11.1.0" SetEnv="PASSWORD=NICE2XML" ; Where to place socket files IpcDir /www/xmlservice/logs
# Apache Default server configuration LoadModule ibm_ssl_module /QSYS.LIB/QHTTPSVR.LIB/QZSRVSSL.SRVPGM LoadModule proxy_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM LoadModule proxy_http_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM LoadModule proxy_connect_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM LoadModule proxy_ftp_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM LoadModule proxy_balancer_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM LoadModule zend_enabler_module /QSYS.LIB/QHTTPSVR.LIB/QZFAST.SRVPGM ProxyPreserveHost On # General setup directives HotBackup Off TimeOut 30000 KeepAlive Off AddLanguage en .en DefaultFsCCSID 37 CGIJobCCSID 37 # Listen *:58700 Listen *:47700 # keep logs 7 days LogMaint logs/access_log 7 0 LogMaint logs/error_log 7 0 LogMaint logs/error_zfcgi 7 0 DocumentRoot /www/xmlservice/htdocs NameVirtualHost *:47700 <VirtualHost *:47700> # SSLAppName QIBM_HTTP_SERVER_STD77 SSLAppName QIBM_HTTP_SERVER_XMLSERVICE SSLCacheEnable SSLEngine On SSLClientAuth None SetEnv HTTPS_PORT 47700 </VirtualHost> <Directory /> order allow,deny deny from all Options -Indexes -ExecCGI -includes AllowOverride All </Directory> # Allow requests for files in document root <Directory /www/xmlservice/htdocs> order allow,deny allow from all </Directory> <Directory /www/xmlservice/htdocs/zip> Options +Indexes order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /QSYS.LIB/XMLSERVICE.LIB/ <Directory /QSYS.LIB/XMLSERVICE.LIB/> order allow,deny allow from all SetHandler cgi-script Options +ExecCGI </Directory> # pase CGI # cd /QOpenSys # ln -sf /home/xml xml # cd /www/xmlservice/htdocs # ln -sf /home/xml xml ScriptAlias /pase-bin/ /QOpenSys/xmlservice/ AddType application/x-httpd-python .py Action application/x-httpd-python /pase-bin/bash-cgi # AddType application/x-httpd-php .php # Action application/x-httpd-php /pase-bin/bash-cgi AddType application/x-httpd-ruby .rb Action application/x-httpd-ruby /pase-bin/bash-cgi AddType application/x-httpd-node .js Action application/x-httpd-node /pase-bin/bash-cgi AddType application/x-httpd-java .java Action application/x-httpd-java /pase-bin/bash-cgi AddType application/x-httpd-sh .sh Action application/x-httpd-sh /pase-bin/bash-cgi <Directory /QOpenSys/xmlservice> Options +ExecCGI order allow,deny allow from all </Directory> # zend fastcgi AddType application/x-httpd-php .php AddHandler fastcgi-script .php
<html> <body> <h1>Secure call XMLSERVICE please</h1> <form id="myForm" name="myForm" action="https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm" method="post"> <input type="hidden" name="db2" value="*LOCAL"> <br>User: <input type="input" name="uid" value=""> (see instructor) <br>Password: <input type="password" name="pwd" value=""> <input type="hidden" name="ipc" value="*na"> <input type="hidden" name="ctl" value="*here"> <br>XML Input: <br><textarea readonly name="xmlin" rows="20" cols="100"><?xml version='1.0'?> <xmlservice> <cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd> <pgm name='ZZCALL'> <parm><data type='1A'>a</data></parm> <parm><data type='1A'>b</data></parm> <parm><data type='7p4'>11.1111</data></parm> <parm><data type='12p2'>222.22</data></parm> <parm> <ds> <data type='1A'>x</data> <data type='1A'>y</data> <data type='7p4'>66.6666</data> <data type='12p2'>77777.77</data> </ds> </parm> </pgm> <sql> <query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query> <fetch block='all'/> </sql> </xmlservice> </textarea> <input type="hidden" name="xmlout" value="512000"> <br><input type="submit" name=submit" value="submit" /> </form> </body> </html>
ssh xml@common1.frankeni.com > bash xmlservice.sh
#!/bin/bash curl -k \ --data-urlencode "db2=*LOCAL" \ --data-urlencode "uid=XML" \ --data-urlencode "pwd=$PASSWORD" \ --data-urlencode "ipc=*na" \ --data-urlencode "ctl=*here" \ --data-urlencode "xmlin=\ <?xml version='1.0'?> <xmlservice> <cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd> <sh>system dsplibl</sh> <pgm name='ZZCALL'> <parm><data type='1A'>a</data></parm> <parm><data type='1A'>b</data></parm> <parm><data type='7p4'>11.1111</data></parm> <parm><data type='12p2'>222.22</data></parm> <parm> <ds> <data type='1A'>x</data> <data type='1A'>y</data> <data type='7p4'>66.6666</data> <data type='12p2'>77777.77</data> </ds> </parm> </pgm> <sql> <query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query> <fetch block='all'/> </sql> </xmlservice>" \ --data-urlencode "xmlout=512000" \ https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm
ssh xml@common1.frankeni.com > php xmlservice.php
<?php // $url = "http://common1.frankeni.com:58700/cgi-bin/xmlcgi.pgm"; $url = "https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm"; $ixml = "<?xml version='1.0'?>\n"; $ixml .= "<xmlservice>"; $ixml .= "<cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd>"; $ixml .= "<sh>system dsplibl</sh>"; $ixml .= " <pgm name='ZZCALL'>"; $ixml .= " <parm><data type='1A'>a</data></parm>"; $ixml .= " <parm><data type='1A'>b</data></parm>"; $ixml .= " <parm><data type='7p4'>11.1111</data></parm>"; $ixml .= " <parm><data type='12p2'>222.22</data></parm>"; $ixml .= " <parm>"; $ixml .= " <ds>"; $ixml .= " <data type='1A'>x</data>"; $ixml .= " <data type='1A'>y</data>"; $ixml .= " <data type='7p4'>66.6666</data>"; $ixml .= " <data type='12p2'>77777.77</data>"; $ixml .= " </ds>"; $ixml .= " </parm>"; $ixml .= "</pgm>"; $ixml .= "<sql>"; $ixml .= "<query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query>"; $ixml .= "<fetch block='all'/>"; $ixml .= "</sql>"; $ixml .= "</xmlservice>"; $postdata = http_build_query( array( 'db2'=>'*LOCAL', 'uid'=>'XML', 'pwd'=>getenv('PASSWORD'), 'ipc'=>'*na', 'ctl'=>'*here', 'xmlin'=>$ixml, 'xmlout'=>512000 ) ); $opts=array('http'=> array( 'method'=>'POST', 'header'=>'Content-type: application/x-www-form-urlencoded', 'content'=>$postdata ), ); if (strpos($url,"ttps") > 0) { $opts['ssl'] = array( "verify_peer"=>false, "verify_peer_name"=>false); } $context = stream_context_create($opts); $xmlout = file_get_contents($url, false, $context); // output print "$xmlout\n"; // print phpinfo(); ?>
ssh xml@common1.frankeni.com > python xmlservice.py
# python import os import urllib import xml.dom.minidom xmlout = "" try: # url = 'http://common1.frankeni.com:58700/cgi-bin/xmlcgi.pgm' url = 'https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm' ixml = "<?xml version='1.0'?>\n" ixml += "<xmlservice>" ixml += "<cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd>" ixml += "<sh>system dsplibl</sh>" ixml += "<pgm name='ZZCALL'>" ixml += " <parm><data type='1A'>a</data></parm>" ixml += " <parm><data type='1A'>b</data></parm>" ixml += " <parm><data type='7p4'>11.1111</data></parm>" ixml += " <parm><data type='12p2'>222.22</data></parm>" ixml += " <parm>" ixml += " <ds>" ixml += " <data type='1A'>x</data>" ixml += " <data type='1A'>y</data>" ixml += " <data type='7p4'>66.6666</data>" ixml += " <data type='12p2'>77777.77</data>" ixml += " </ds>" ixml += " </parm>" ixml += "</pgm>" ixml += "<sql>" ixml += "<query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query>" ixml += "<fetch block='all'/>" ixml += "</sql>" ixml += "</xmlservice>" params = urllib.urlencode({ 'db2': '*LOCAL', 'uid': 'XML', 'pwd': os.environ['PASSWORD'], 'ipc': '*na', 'ctl': '*here', 'xmlin': ixml, 'xmlout': '512000' }) usock = urllib.urlopen(url, params) xmldoc = xml.dom.minidom.parse(usock) usock.close() xmlout = xmldoc.toxml() except Exception, info: xmlout = "Error '%s' " % (info[0]) # output print xmlout
ssh xml@common1.frankeni.com > node xmlservice.js
// node.js // output (callback) function cb(str) { console.log(str); } // var uri = url.parse("http://common1.frankeni.com:58700/cgi-bin/xmlcgi.pgm"); var url = require('url'); var uri = url.parse("https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm"); if (uri.protocol == 'https:') { var http = require("https"); } else { var http = require('http'); } var ixml = "<?xml version='1.0'?>\n" + "<xmlservice>" + "<cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd>" + "<sh>system dsplibl</sh>" + " <pgm name='ZZCALL'>" + " <parm><data type='1A'>a</data></parm>" + " <parm><data type='1A'>b</data></parm>" + " <parm><data type='7p4'>11.1111</data></parm>" + " <parm><data type='12p2'>222.22</data></parm>" + " <parm>" + " <ds>" + " <data type='1A'>x</data>" + " <data type='1A'>y</data>" + " <data type='7p4'>66.6666</data>" + " <data type='12p2'>77777.77</data>" + " </ds>" + " </parm>" + "</pgm>" + "<sql>" + "<query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query>" + "<fetch block='all'/>" + "</sql>" + "</xmlservice>"; var xml_enc = encodeURI("db2=" + '*LOCAL' + "&uid=" + 'XML' + "&pwd=" + process.env.PASSWORD + "&ipc=" + '*na' + "&ctl=" + '*here' + "&xmlin=" + ixml + "&xmlout=" + '512000'); var arr = uri.host.split(":"); var options = { host: arr[0], port: arr[1], path: uri.path + '/?' + xml_enc }; if (uri.protocol == 'https:') { options['rejectUnauthorized'] = false; options['requestCert'] = true; options['agent'] = false; } // console.log(options); var httpCallback = function(response) { var str = ''; //another chunk of data has been received, so append it to `str` response.on('data', function (chunk) { str += chunk; }); //the whole response has been received, so return response.on('end', function () { cb(str); }); } // make the call var req = http.request(options, httpCallback).end();
ssh xml@common1.frankeni.com > ruby xmlservice.rb
# ruby require 'net/https' require 'uri' # @url = 'http://common1.frankeni.com:58700/cgi-bin/xmlcgi.pgm' @url = 'https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm' @ixml = "<?xml version='1.0'?>\n" @ixml << "<xmlservice>" @ixml << "<cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd>" @ixml << "<sh>system dsplibl</sh>" @ixml << " <pgm name='ZZCALL'>" @ixml << " <parm><data type='1A'>a</data></parm>" @ixml << " <parm><data type='1A'>b</data></parm>" @ixml << " <parm><data type='7p4'>11.1111</data></parm>" @ixml << " <parm><data type='12p2'>222.22</data></parm>" @ixml << " <parm>" @ixml << " <ds>" @ixml << " <data type='1A'>x</data>" @ixml << " <data type='1A'>y</data>" @ixml << " <data type='7p4'>66.6666</data>" @ixml << " <data type='12p2'>77777.77</data>" @ixml << " </ds>" @ixml << " </parm>" @ixml << "</pgm>" @ixml << "<sql>" @ixml << "<query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query>" @ixml << "<fetch block='all'/>" @ixml << "</sql>" @ixml << "</xmlservice>" post_args = { :db2 => '*LOCAL', :uid => 'XML', :pwd => ENV['PASSWORD'], :ipc => '*na', :ctl => '*here', :xmlin => URI::encode(@ixml), :xmlout => '512000' } uri = URI(@url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.scheme == 'https' http.verify_mode = OpenSSL::SSL::VERIFY_NONE res = http.post(uri, URI.encode_www_form(post_args)) # output @xmlout = res.body puts @xmlout
ssh xml@common1.frankeni.com > javac xmlservice.java > java xmlservice
// javac xmlservice.java // java xmlservice import java.io.*; import java.net.*; import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.*; public class xmlservice { public static String go () throws UnsupportedEncodingException, UnsupportedEncodingException, IOException { // URL url = new URL("http://common1.frankeni.com:58700/cgi-bin/xmlcgi.pgm"); URL url = new URL("https://common1.frankeni.com:47700/cgi-bin/xmlcgi.pgm"); String ixml = "<?xml version='1.0'?>\n" + "<xmlservice>" + "<cmd>CHGLIBL LIBL(XMLSERVICE) CURLIB(XMLSERVICE)</cmd>" + "<sh>system dsplibl</sh>" + " <pgm name='ZZCALL'>" + " <parm><data type='1A'>a</data></parm>" + " <parm><data type='1A'>b</data></parm>" + " <parm><data type='7p4'>11.1111</data></parm>" + " <parm><data type='12p2'>222.22</data></parm>" + " <parm>" + " <ds>" + " <data type='1A'>x</data>" + " <data type='1A'>y</data>" + " <data type='7p4'>66.6666</data>" + " <data type='12p2'>77777.77</data>" + " </ds>" + " </parm>" + "</pgm>" + "<sql>" + "<query>select * from QIWS.QCUSTCDT where LSTNAM='Jones'</query>" + "<fetch block='all'/>" + "</sql>" + "</xmlservice>"; String query = new String( java.net.URLEncoder.encode( "db2=" + "*LOCAL" + "&uid=" + "XML" + "&pwd=" + java.lang.System.getenv("PASSWORD") + "&ipc=" + "*na" + "&ctl=" + "*here" + "&xmlin=" + ixml + "&xmlout=" + "512000" , "ISO-8859-1")); byte[] queryBytes = query.getBytes("UTF-8"); String length = String.valueOf((url + query).getBytes("UTF-8").length); // HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); try { SSLSocketFactory sslSocketFactory = createSslSocketFactory(); conn.setSSLSocketFactory(sslSocketFactory); // certificate common name needed to be lp0364d (match tcp name) // conn.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String _s1, SSLSession _s2) { return true;} }); } catch (Exception e) { System.out.println(e.getMessage()); } conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Length", length); conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); os.write(queryBytes); os.flush(); conn.connect(); BufferedReader strm = new BufferedReader(new InputStreamReader(conn.getInputStream())); String inputLine; String doc = ""; while ((inputLine = strm.readLine()) != null) { doc = doc + inputLine; } return new String(doc); } private static SSLSocketFactory createSslSocketFactory() throws Exception { TrustManager[] byPassTrustManagers = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] chain, String authType) {} public void checkServerTrusted(X509Certificate[] chain, String authType) {} } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, byPassTrustManagers, new SecureRandom()); return sslContext.getSocketFactory(); } public static void main (String args[]) { // output String xmlout = ""; try { xmlout += go(); } catch (Exception e) { xmlout += e.getMessage(); } System.out.println(xmlout); } }