XML Service Samples Rest

Goto Main Page
Goto Documents

From Disney Common 2015 lab …

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.

XMLSERVICE REST Apache configuration (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/xmlservice/bash-cgi
    #!/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>'
    
  • /www/xmlservice/conf/fastcgi.conf (for PHP only)
    ; 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
    
  • /www/xmlservice/conf/httpd.conf
    # 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
    

XMLSERVICE REST HTML/XML

<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>

XMLSERVICE REST bash w/curl

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

XMLSERVICE REST php

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();

?>

XMLSERVICE REST python

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

XMLSERVICE REST node.js

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();

XMLSERVICE REST ruby

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

XMLSERVICE REST java

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);
}
}