|
Author:
Bob Cozzi
|
|
2010-07-27 07.45.48 |
Yes. That routine is named escapeXML and does escaping for data before wrapping
it inside of XML.
D escapeXML PR 10I 0
D xmlin 65535A Const Varying
D xmlOut 65535A OPTIONS(*VARSIZE)
D nOutLen 10I 0 Const
I know the In/Out parms are sort of backwards based on contemporary standards
(where the target is always first), but I apparently was asleep the day I wrote
this.
I am doing an update to RPGOpen.com and will add a contemporary version of
escapeXML to it. The name in RPG Open is encodeXML and will use more appropriate
parameter syntax. |
|
Author:
CityInd
|
|
2010-05-19 10.52.03 |
Please ignore the last post. Had the 3rd party take out the encode. |
|
Author:
CityInd
|
|
2010-05-18 12.46.00 |
One more time.
Bob, do you have a procedure like iSocketsCRLF, that would change the ampersand
+ LT; to '<'? Same for the ampersand + GT;? Thanks
|
|
Author:
CityInd
|
|
2010-05-18 12.43.40 |
Bob, do you have a procedure like iSocketsCRLF, that would change <
to >? Same for '>'? Thanks (I'll try again.)
|
|
Author:
CityInd
|
|
2010-05-18 12.42.04 |
Bob, do you have a procedure like iSocketsCRLF, that would change '<'
to '<'? Same for '>'? Thanks |
|
Author:
Bob Cozzi
|
|
2007-06-28 17.13.46 |
Yes. There are two subprocedures that turn these things on or off.
iSocketsDbg(*OFF);
iSocketsOptions('DBG' : *OFF);
The first one is used when you've already done a call such as:
iSocketsDbg(*ON : '/home/mylog.txt')
And now you want to turn off writing to the text log on the IFS as some
additional joblogging.
The second one turns of the original logging flag that allows additional
messages to be written to the job log.
In the next version (not release but full version) we're consolidating this
stuff and also providing a way to turn off a extra joblog writes except those
created by the OS; which we can't control.
|
|
Author:
joeye
|
|
2007-06-28 14.03.20 |
Is there anyway to cut off the comments that are sent to the joblog? |
|
Author:
joeye
|
|
2007-06-25 08.18.33 |
Thanks everyone. I changed the 1.1 to 1.0 and get sub-second response times
now. Thanks for all of your help. |
|
Author:
Bob Cozzi
|
|
2007-06-22 10.42.25 |
Okay, I've moved the working example to the RPGLAB (downloads page) on this website.
Here is the direct link if you want to go get the source code:
http://www.rpgiv.com/cgi-rpg/viewsrc?FILE=QRPGLESRC&LIB=RPGLAB&MBR=WEBSERVEX2 |
|
Author:
Bob Cozzi
|
|
2007-06-22 06.32.11 |
Oh, and one other thing; linefeeds.
The logic error I introduced into the example I created, is that I calculated
the Content-Length from %len(szSOAPText). Which is wrong since SendURLText()
will convert all \r\n to X'0D25'. Which means (in this example) there will be
about 16 fewer characters than the Content-Length indicates. So I had to call
iSocketsCRLF() and do the conversion of szSOAPText prior to calculating the
content-length. |
|
Author:
Bob Cozzi
|
|
2007-06-22 06.30.01 |
Looks like it was the HTTP/1.1 causing the problem and nothing else.
Changing it to HTTP/1.0 produces instant results.
I get the following XML returned, and using XML-INTO to parse it, I get 95 F
degress when I pass in 35 C.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<CelsiusToFahrenheitResponse xmlns="http://tempuri.org/">
<CelsiusToFahrenheitResult>95</CelsiusToFahrenheitResult>
</CelsiusToFahrenheitResponse>
</soap:Body>
</soap:Envelope> |
|
Author:
Bob Cozzi
|
|
2007-06-21 19.36.20 |
Well, I got it "working" too. I'm not sure which of the three changes made a
difference, but I'll check that out shortly.
Thanks. |
|
Author:
MarkBoyer
|
|
2007-06-21 18.18.31 |
Yes, I changed the HTTP version, I removed the new lines from within the XML
envelope (which could be related to your comment about the content-length) and
finished everything up with two new lines.
szSOAPText =
'<?xml version="1.0" encoding="utf-8"?>\n' +
'<soap:Envelope ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+
'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
'<soap:Body>' +
'<FahrenheitToCelsius xmlns="http://tempuri.org/">' +
'<Fahrenheit>' + %char(nFahren) + '</Fahrenheit>' +
'</FahrenheitToCelsius>' +
'</soap:Body>' +
'</soap:Envelope>\n';
hUrl = OpenURL('www.w3schools.com');
SendURLText(hURL : 'POST /webservices/tempconvert.asmx HTTP/1.0\n');
SendURLText(hURL : 'Host: www.w3schools.com\n');
SendURLText(hURL : 'Content-Type: text/xml; charset=utf-8\n');
SendURLTExt(hURL : 'Content-Length: ' + %char(%len(szSoapText))+'\n');
SendURLTExt(hURL : 'SOAPAction: ' +
'"http://tempuri.org/FahrenheitToCelsius"\n\n');
SendURLText(hUrl: szSOAPText);
SendURLTExt(hURL : '\n\n'); |
|
Author:
Bob Cozzi
|
|
2007-06-21 17.46.21 |
Mark,
Are you saying you changed HTTP/1.1 to HTTP/1.0 and it worked?
I tried that and got an invalid request response.
I did notice that I'm passing an invalid content-length and corrected that,
(which was causing my 2 minutes or so of wait before failing). That's fixed and
not I also get an instant response, but with "Bad Request" or "Invalid Verb".
|
|
Author:
MarkBoyer
|
|
2007-06-21 16.50.24 |
I was having a similar problem with Brad Stone's GetUri tool with a web service
interface I recently wrote. If you change the "HTTP/1.1" to "HTTP/1.0" the
first header ("HTTP 100 Continue") isn't returned from the server and control
returns to the program almost immediately.
I used Bob's version as a base, changed the HTTP version to 1.0, I also (and I
know this should make no difference) removed all the new lines (\n) between the
<soap:Envelope> and </soap:Envelope> tags and finish off by sending two new
lines after szSoapText and the program runs with sub-second response.
Hope this helps. |
|
Author:
joeye
|
|
2007-06-21 13.21.04 |
Just incase anyone wants to see the code, here it is.
H DFTACTGRP(*NO) BNDDIR('ISOCKETS/ISOCKETS')
D#Domain S 128A Varying
D Inz('www.w3schools.com')
d#XMLInput s 4096a varying
d inz(' ')
d#XMLOutput s 4096a varying
d inz(' ')
D nCelsius S 10I 0 inz(70)
D nFahrenheit S 10I 0
D szPage S 100A varying
D szPage1 S 100A varying
D szPage2 S 100A varying
D szPage3 S 100A varying
D szPage4 S 100A varying
D NBYTES S 10I 0
D nDataPos S 10I 0
D nLen S 10I 0
D nFahren S 10I 0
d nCel s 10i 0
d hURL s 10i 0
D pHTML S *
dNBytesRtn s 10i 0
/free
// build header records
szPage = 'POST /webservices/tempconvert.asmx HTTP/1.1\n';
szPage1 = 'Host: www.w3schools.com\n';
szpage2 = 'Content-Type: text/xml; charset=utf-8\n';
szpage4 = 'SOAPAction: "http://tempuri.org/CelsiusToFahrenheit"\n\n';
// build XML
#XMLInput = '<?xml version="1.0" encoding="utf-8"?>';
#XMLInput +='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/+
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/+
XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/+
soap/envelope/">';
#XMLInput += '<soap:Body>';
#XMLInput += '<CelsiusToFahrenheit xmlns="http://tempuri.org/">';
#XMLInput += '<Celsius>70';
#XMLInput += '</Celsius>';
#XMLInput += '</CelsiusToFahrenheit>';
#XMLInput += '</soap:Body>';
#XMLInput += '</soap:Envelope>';
hURL = OpenUrl(#Domain);
nbytes = SendURLText(hURL : szpage );
nbytes = SendURLText(hURL : szpage1);
nbytes = SendURLText(hURL : szpage2);
nbytes = SendURLText(hURL : szpage3);
nbytes = SendURLText(hURL : szpage4);
nbytes = SendURLText(hURL : #XMLInput);
nBytes += SendURLText(hUrl:'\r\n');
if Nbytes > 0;
Nbytes = 0;
dou nBytesRtn <= 0 and (NBytes < %size(#XMLOutput));
NBytesRtn = RecvURLData(hURL: %addr(#XMLOutput) + nBytes:
%size(#XMLOutput) - nbytes);
nbytes += NBytesRtn;
enddo;
if GetHTTPStatus(%Addr(#XMLOutput): nBytes) = 200;
joblog('Return OK -- %s -- %s':
%char(GetHTTPStatus(%Addr(#XMLOutput): nBytes)));
else;
joblog('Return Error -- %s -- %s':
%char(GetHTTPStatus(%Addr(#XMLOutput): nBytes)));
endif;
endif;
CloseUrl(hURL);
*INLR = *ON;
/end-free |
|
Author:
Bob Cozzi
|
|
2007-06-21 13.13.39 |
Hmmm... mine isn't working. :( |
|
Author:
joeye
|
|
2007-06-21 13.09.58 |
Its working, but its just slow. Bellow is the joblog when it is finished.
ParseURL Domain() Port(0)
OpenURL(www.w3schools.com:80)
gethostbyname(www.w3schools.com) returned 216.128.27.100
Connecting to www.w3schools.com on port 80...
SendUrlData sent 44 bytes.
SendUrlData sent 24 bytes.
SendUrlData sent 38 bytes.
SendUrlData sent 20 bytes.
SendUrlData sent 54 bytes.
SendUrlData sent 338 bytes.
SendUrlData sent 2 bytes.
A connection with a remote socket was reset by that socket.
Return OK -- 200 --
Closing socket 11
From start to finish is almost exactly 2 minutes. |
|
Author:
Bob Cozzi
|
|
2007-06-21 12.54.57 |
Is yours working but just running slowly, or is it slow and not working?
If the request is bad, it will either timeout after X seconds (usually 20 to 120
seconds) or it will return immediately with an error of some kind. |
|
Author:
joeye
|
|
2007-06-21 12.44.32 |
Bob,
That is exactly what I did as well (coping from w3schools). Its driving me
nuts, I cannot figure out why one method would be so much faster than the
other. |
|
Author:
Ringer
|
|
2007-06-21 12.37.12 |
Ok... Thanks for the t\ra\nslatio\n... |
|
Author:
Bob Cozzi
|
|
2007-06-21 12.29.31 |
Cheeze! Good catch. I'll try it again.
The \n are built into iSockets and my other products, such as the CGILIB in
xTools. The iSockets library automatically converts \n to X'25', and \r to
X'0D'. As you probably know, X'0D' is passed through and X'25' is considered a
linefeed to the HTTP/iSeries world. |
|
Author:
Ringer
|
|
2007-06-21 11.59.37 |
Bob,
I don't see where you are passing szSOAPText in the body of the request, for
the POST. And wouldn't X'0D25' make more sense than '\n'?
Chris |
|
Author:
Bob Cozzi
|
|
2007-06-21 11.52.41 |
I just tried it on my box, and it just sits there for about a minute or so, and
then returns an "HTTP 100 Continue" message. It is supposed to return an HTTP
200 header and then the rest of the results.
I cut/pasted the request directly from the W3schools example so I'm sure it is
correct. If anyone else wants to have a look at it, here's the code (you need
to install iSockets on your system). iSockets is a completely free service program.
H OPTION(*NODEBUGIO:*SRCSTMT) BNDDIR('ISOCKETS':'QC2LE')
H DFTACTGRP(*NO)
/COPY iSockets/qCPYsrc,iSockets
/COPY iSockets/qCPYsrc,cProtos
D hURL S 10I 0
D nBytes S 10I 0
D nBytesRtn S 10I 0
D nFahren S 10I 0
D nCelsius S 10I 0
D szXML S 65535A
D pXML S * Inz(%addr(szXML))
D nLen S 10I 0
D nDataPos S 10I 0
D szSOAPText S 2048A Varying
D
C *ENTRY PLIST
C PARM TEMP 15 5
C eval *INLR = *ON
/free
iSocketsDbg(*ON:'/cozzi/soap_example.txt');
if (%Parms() >= 1);
nFahren = Temp;
else;
nFahren = 32;
endif;
szSOAPText =
'<?xml version="1.0" encoding="utf-8"?>\n' +
'<soap:Envelope ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+
'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\n' +
'<soap:Body>\n' +
'<FahrenheitToCelsius xmlns="http://tempuri.org/">\n' +
'<Fahrenheit>' + %char(nFahren) + '</Fahrenheit>\n' +
'</FahrenheitToCelsius>\n' +
'</soap:Body>\n' +
'</soap:Envelope>\n';
hUrl = OpenURL('www.w3schools.com');
SendURLText(hURL : 'POST /webservices/tempconvert.asmx HTTP/1.1\n');
SendURLText(hURL : 'Host: www.w3schools.com\n');
SendURLText(hURL : 'Content-Type: text/xml; charset=utf-8\n');
SendURLTExt(hURL : 'Content-Length: ' + %char(%len(szSoapText))+'\n');
SendURLTExt(hURL : 'SOAPAction: ' +
'"http://tempuri.org/FahrenheitToCelsius"\n\n');
SendURLText(hUrl: szSOAPText);
dou nBytesRtn <= 0 or (nBytes >= %size(szXML));
nBytesRtn = RecvURLData(hURL: pXML + nBytes:
%size(szXML) - nbytes);
nBytes += nBytesRtn;
enddo;
if (nBytes > 0);
nDataPos = ParseHTTPReply(pXML:nBytes);
nLen = nBytes-(nDataPos-1);
Joblog(%subst(szXML:nDataPos:nLen));
XML-INTO nFahren %xml(%subst(szXML:nDataPos:nBytes):
'path=FahrenheitToCelsiusResult allowextra=yes');
joblog('%s Fahrenheit is %s Celsius':
%char(nFahren):%char(nCelsius));
endif;
return;
|
|
Author:
joeye
|
|
2007-06-21 09.18.30 |
I'm sorry to be so confusing. From what I have seen, there is a HTTP Post
method, Soap 1.1, and Soap 1.2. When using HTTP Post it runs instantly, but
when using Soap 1.1 it takes over 2 minutes. I'm really new to using
webservices, and may get some terminology wrong, but thanks for being patient
with a newbie. |
|
Author:
Ringer
|
|
2007-06-21 09.01.57 |
I'm confused. Your code shows you using the POST method. You say it takes 2
minutes to run. Then in your last message, you say when you use the POST
method, it runs instantly. Which is it? Are you using some other method besides
POST (maybe a GET?).
Chris |
|
Author:
joeye
|
|
2007-06-21 08.50.33 |
I tried the %char(%len(%TrimR(#XMLInput))) but it did not speed it up any.
Could it be a networking issue. Would you mind sending your code so that I
can compare it with mine. When I run the program it is consistently running
in 2 - 2.5 minutes, and has to reset the socket.
The funny thing is when using the post method, it runs instantly. This makes
me think that maybe I'm doing something wrong. |
|
Author:
Ringer
|
|
2007-06-21 07.32.07 |
The Content-Length would be %Len(%TrimR(#XMLInput)), right? And it does look
like "SOAPAction:" is a header, didn't know about that one. So, the blank line
(extra \n) would be after that header.
Chris |
|
Author:
Bob Cozzi
|
|
2007-06-21 06.53.24 |
Did you change the content-length or is it still at 2?
The thing about HTML/HTTP stuff is there's no real syntax checker. You have to
keep trying stuff until it works. A subtle typo is all it takes to screw things up! |
|
Author:
Ringer
|
|
2007-06-20 20.02.35 |
I would guess your Content-Length is too short and the socket server times out,
waiting for data that never arrives. Just for kicks, remove the
"Content-Length:" from the request and see if the HTTP server calculates it for
you. I know that tricks works in Java for an HttpURLConnection.
Chris |
|
Author:
MarkBoyer
|
|
2007-06-20 17.50.21 |
I ran a test and got sub-second response. Your two minutes is not normal. |
|
Author:
joeye
|
|
2007-06-20 16.05.07 |
Thanks so much for all of your help. That worked, but it is pretty slow. I
have the following in my joblog every time I run the program.
A connection with a remote socket was reset by that socket.
Any suggestions? The results are returned, but it takes about 2 minutes to
run, is that normal? |
|
Author:
Bob Cozzi
|
|
2007-06-20 14.22.19 |
Joeye,
Ringer is right. You are missing a blank line, which in HTTP/HTML means a
second, consecutive linefeed.
szpage3 = 'Content-Length: 2\n'
should be:
szpage3 = 'Content-Length: 2\n\n'
Or if the <SOAP> is still part of the HTTP header, then it goes on that line
instead.
Last, the content-length needs to be the same as the XML body being sent (not
including the headers). |
|
Author:
Ringer
|
|
2007-06-20 13.23.07 |
Where's the blank line between the headers and the XML body payload?
Try adding an extra \n like this:
szpage3 = 'Content-Length: 100\n\n';
Chris |
|
Author:
joeye
|
|
2007-06-20 10.42.57 |
I have tried playing with the length making it the size of the XML, the size
of the parm inside the XML, and even the size of all the transmitions. I'm
getting a little frustrated with this. I've been working on it for almost 4
days now. |
|
Author:
MarkBoyer
|
|
2007-06-20 10.29.12 |
Your Content-Length header says the length is 2? Your XML message is longer
than that. I don't know if that is the problem, but it's a place to start. |
|
Author:
joeye
|
|
2007-06-20 10.04.05 |
Ok, here is what I'm doing:
szPage = 'POST /webservices/tempconvert.asmx HTTP/1.1\n';
szPage1 = 'Host: www.w3schools.com\n';
szpage2 = 'Content-Type: text/xml; charset=utf-8\n';
szpage3 = 'Content-Length: 2\n';
szpage4 = 'SOAPAction: "http://tempuri.org/CelsiusToFahrenheit"\n';
#XMLInput = '<?xml version="1.0" encoding="utf-8"?>';
#XMLInput +='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/+
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/+
XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/+
soap/envelope/">';
#XMLInput += '<soap:Body>';
#XMLInput += '<CelsiusToFahrenheit xmlns="http://tempuri.org/">';
#XMLInput += '<Celsius>';
#XMLInput += %char(nCelsius);
#XMLInput += '</Celsius>';
#XMLInput += '</CelsiusToFahrenheit>';
#XMLInput += '</soap:Body>';
#XMLInput += '</soap:Envelope>';
hURL = OpenUrl(#Domain);
nbytes = SendURLText(hURL : szpage );
nbytes = SendURLText(hURL : szpage1);
nbytes = SendURLText(hURL : szpage2);
nbytes = SendURLText(hURL : szpage3);
nbytes = SendURLText(hURL : szpage4);
nbytes = SendURLText(hURL : ' \n');
nbytes = SendURLText(hURL : #XMLInput);
if Nbytes > 0;
Nbytes = 0;
dou nBytesRtn <= 0 and (NBytes < %size(#XMLOutput));
NBytesRtn = RecvURLData(hURL: %addr(#XMLOutput) + nBytes:
%size(#XMLOutput) - nbytes);
nbytes += NBytesRtn;
enddo;
#XMLOutput is then set to:
HTTP/1.1 400 Bad RequestContent-Type: text/htmlDate: Wed,
20 Jun 2007 15:04:17 GMTConnection: closeContent-Length:
42<h1>Bad Request (Invalid Header Name)</h1>
Any ideas? |
|
Author:
joeye
|
|
2007-06-20 07.25.14 |
I have tried using isockets, and it works great for HTTP Post, but I cannot
seem to figure out how to get the SOAP to work. I'm sure its a user error
(me), because Cozzi said that it would work, but I have not been able to find
even a small example of it.
Thanks for your help thought, I'll look into httpapi. |
|
Author:
sydcor
|
|
2007-06-19 11.21.52 |
check isockets (Cozzi) and httpapi (Scott Klement). both should get you
started. |
|
Author:
joeye
|
|
2007-06-19 09.51.58 |
I'm trying to write a RPG IV application that will interact with a
webservice. The webservice uses SOAP 1.1. Do you have an example of this,
maybe using the TempConvert service? |