Anmelden

View Full Version : systools httpPostClobVerbose Status ermitteln



Seiten : [1] 2

dschroeder
20-08-18, 16:38
Hallo,
wir verwenden die Funktion httpPostClobVerbose, um einen Webservice aufzurufen. Als Rückgabe bekommen wir 2 Clobs, nämlich die responseMsg und den responseHttpHeader.

Mein Kollege, der den Webservice erstellt hat, meinte, es sei Standard, dass man den Status der HTTP-Anfrage zurückerhält. Z.B 200 = OK oder 403 = Forbidden.

Weiß jemand, ob (und wie) man den Status ermitteln kann? Was wir zur Zeit zurückbekommen, ist eine leere responseMsg und im Fehlerfall ein responseHeader, in dem z.B. "Server Error" drinsteht. Die echten HTTP-Statuswerte wären uns aber lieber.

Wir setzen die Funktion im embedded SQL ein:



clear responseMsgClobDS;
clear responseHeaderClobDS;
exec sql select ifnull(responsemsg, ''), ifnull(responsehttpheader, '')
into :responseMsgClobDS, :responseHeaderClobDS
from table(SYSTOOLS.HTTPPOSTCLOBVERBOSE(:url,
cast (:header as clob(1k)),
cast (:body as clob(1k)) ) ) as a;

Dieter

dschroeder
20-08-18, 18:08
Ich glaube, ich habe den Status gefunden. Der Status scheint doch im Header mitgeliefert zu werden.

Das führt mich allerdings zu meinem nächsten Problem:

Der Rückgabe-Header sieht folgendermaßen aus (ich kann das in diesem Editor anscheinend nur als Grafik einfügen. (Irgendwie ist die Grafik jetzt 2 mal da)):

Man sieht, dass die XML-Datei aus dem Basisobjekt "httpHeader" mit der Eigenschaft "responseCode="404" besteht (ich weiß nicht, ob die Begrifflichkeiten richtig gewählt sind).

Irgendwie schaffe ich es im Moment nicht, diese Struktur mit xml-into korrekt einzulesen. Es gibt zwar keinen Fehler, aber die Result-Struktur ist leer.

Ich habe folgendes Kodiert:

//Struktur für XLM-Header:
dcl-ds httpHeaderTempl qualified template;
responseCode char(3);
end-ds;

dcl-ds httpHeaderDS likeds(httpHeaderTempl);
...
xml-into httpHeaderDS %xml(httpHeaderString :
'doc=string allowmissing=yes allowextra=yes path=httpHeader countprefix=count');


Vielleicht hat ja jemand auf Anhieb eine Idee.<httpheader responsecode="404"><header name="Keep-Alive" value="timeout=15, max=100"><header name="HTTP_RESPONSE_CODE" value="HTTP/1.1 404 Not Found"><header name="Connection" value="Keep-Alive"><header name="Content-Length" value="0"><header name="Date" value="Mon, 20 Aug 2018 15:46:48 GMT"><header name="Content-Type" value="text/plain; charset=UTF-8"><header name="Keep-Alive" value="timeout=15, max=100"><header name="HTTP_RESPONSE_CODE" value="HTTP/1.1 404 Not Found"><header name="Connection" value="Keep-Alive"><header name="Content-Length" value="0"><header name="Date" value="Mon, 20 Aug 2018 15:46:48 GMT"><header name="Content-Type" value="text/plain; charset=UTF-8"><httpheader responsecode="404"><header name="Keep-Alive" value="timeout=15, max=100"><header name="HTTP_RESPONSE_CODE" value="HTTP/1.1 404 Not Found"><header name="Connection" value="Keep-Alive"><header name="Content-Length" value="0"><header name="Date" value="Mon, 20 Aug 2018 15:46:48 GMT"><header name="Content-Type" value="text/plain; charset=UTF-8"></header></header></header></header></header></header></httpheader></header></header></header></header></header></header></header></header></header></header></header></header></httpheader>

andreaspr@aon.at
21-08-18, 06:06
Hallo Dieter,

ich löse das ganze via SQL.
Zuerst wird der response in eine Tabelle geschrieben:


Insert Into PRANLIB.HTTPRESPONSE
(MSG, HEADER, JOB)
(Select HTTPDATA.*, JOB_NAME
FROM TABLE (HTTPGETCLOBVERBOSE (...)) AS HTTPDATA)


Um dann den HTTP Status-Code zu ermitteln benötigst du folgendes SQL:


WITH
RespHead AS (
SELECT XMLPARSE(DOCUMENT HEADER) AS "doc"
FROM PRANLIB.HTTPRESPONSE
Where ID = 480984)
,
formated_header AS (
SELECT *
FROM XMLTABLE (
'$doc_header/httpHeader' PASSING
(SELECT "doc" FROM RespHead) AS "doc"
COLUMNS
Name VARCHAR(128) PATH '@responseCode',
Value VARCHAR(128) PATH 'responseMessage'
) MsgResponse
)
select * from formated_header


Du kannst dir aber auch eine Tabelle mit einer Auflistung aller HTTP-Headerinformationen ausgeben lassen.
Darin ist dann u.a. auch der HTTP Code enthalten.

lg Andreas

Fuerchau
21-08-18, 08:58
Wofür ist das '@' im Pfad?
Name VARCHAR(128) PATH '@responseCode',

Im Text heißt das ja nicht so.

AG1965_2
21-08-18, 09:36
@ liest Attribute - sonst liest man ja den Elementinhalt.

&lt;element attribut="wertAttribut">wertElement&lt;/element>

dschroeder
21-08-18, 11:13
Hallo Andreas,
vielen Dank. Ich werde mal versuchen, das mit der SQL-Funktion hinzubekommen. Es würde mich trotzdem interessieren, weshalb das mit dem XML-INTO nicht klappt. Das fände ich etwas lesbarer.

Das mit dem @ war mir übrigens auch neu. Genau das ist auch mein Problem beim XML-INTO, glaube ich. Der Response Code ist ein Attribut, kein Element. Vielleicht klappt das ja auch noch irgendwie.

Fuerchau
21-08-18, 16:50
Bisher war da eine Unterscheidung eigentlich nicht nötig.
Der Pfad verweist auf die Knoten, ein Name entweder auf den Knoten- oder Attributnamen.
Es mag sein, dass "@" für die Unterscheidung zwischen Knoten und Attribut bei Namensgleichheit ist.

Ansonsten habt ihr natürlich ein typisches CCSID-Problem, da der "@" je nach Codepage unterschiedlich kodiert ist.
Nun kommt es darauf an, welche CCSID eure Quelle und der Job zur Umwandlungszeit haben und anschließend ob die Job-CCSID wiederum von der HTTP-Funktion korrekt ausgewertet wird.
Hier kann es durchaus zu Schwierigkeiten kommen, denn eine Programmkonstante unterliegt wiederum keiner Codeanpassung, insbesonders wenn der Job wie blöderweise üblich auf *HEX steht.

dschroeder
21-08-18, 16:54
Leider klappt das ganze noch nicht so, wie ich mir das vorstelle, Ich wollte die SQL-Lösung von Andreas etwas auseinanderziehen, damit es übersichtlicher wird. Außerdem möchte ich den Response nicht in einer Extra-Datei speichern, sondern lieber in einer Hostvariablen des SQLRPGLE-Programms ablegen.

Jetzt habe ich anscheinend aber ein Zeichensatzproblem. Ich speichere den ResponseHeader zunächst in einem Clob, das folgendermaßen deklariert ist:

dcl-s responseHeaderClobDS sqltype(CLOB:100000);

Dann speichere ich den Clob-Inhalt in eine "normale" Variable vom Typ varucs2:

dcl-s httpHeaderString varucs2(2000);
httpHeaderString = %subst(responseHeaderClobDS_data:1:responseHeaderC lobDS_len);


Jetzt lese ich aus dem Header die gewünschten Werte:

exec sql select * into :responseCode, :responseMsg
from xmltable('/httpHeader' passing xmlparse(document :httpHeaderString)
columns resCode varchar(128) path '@responseCode',
resMsg varchar(128) path 'responseMessage') msg;

Dabei bekomme ich den SQL Fehlercode -16168. Der erweiterte Fehlertext (für die aufgetretene Fehlerart 7) ist: XML-Deklaration in XML-Dokument ungültig. ... Angegebene Codierung wird nicht unterstützt oder interne Codierung weicht von externer Codierung ab.

Ich glaube, dass das an dem Beginn des XML-Strings liegt. Dort steht ?xml version="1.0" encoding="UTF-8" drin. Wenn ich diesen Teil manuell aus dem XML-String entferne, liefert mir die xmltable-Funktion die korrekten Werte.

Ich dachte, wenn ich die HeaderString Variable ucs2 deklariere, müsste das auch UTF-8 umfassen.

Hat jemand eine Idee?

Dieter

dschroeder
21-08-18, 17:08
Hallo Baldur, wir haben eben fast zeitgleich gepostet. Ich habe nochmal einen Test gemacht und das @-Zeichen einfach weggelassen. Ich hätte dann eine andere Fehlermeldung erwartet. Aber ich bekomme immer noch die gleiche Fehlermeldung "XML-Deklaration ... ungültig".
Ich habe wahrscheinlich ein Zeichensatzproblem, aber es liegt nicht (allein) am @-Zeichen, denke ich.

Andreas hat in seinem Post noch geschrieben:
Du kannst dir aber auch eine Tabelle mit einer Auflistung aller HTTP-Headerinformationen ausgeben lassen. Darin ist dann u.a. auch der HTTP Code enthalten.

Heißt das, dass es da noch eine einfachere Lösung gibt?

B.Hauser
21-08-18, 17:22
Baldur!

Die Pfad-Angaben in XML-Table basieren auf der XPATH-Syntax, so wie sie vom W3C vorgegeben ist.
Auch wenn Db2 XPATH noch nicht alles abdeckt, beruht die Syntax auf diesem Standard.
W3C XPath Syntax (https://www.w3schools.com/xml/xpath_syntax.asp)


Da die XPATH Syntax in Hochkommata angegeben wird, erfolgt auch keine Konvertierung innerhalb der Quellen. Ausserdem wird von SQL alles automatisch in UTF-8 umgesetzt.

Vielleicht sollte man sich auch mal das folgende White Paper anschauen:
SQL XML Programming (https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/rzasp/rzasppdf.pdf)