Progress ドキュメントは SOAP に多くのインクをこぼしますが、Progress ABL を使用した単純な HTTP GET/POST の例を見つけるのに苦労しています。
URL との間で文字列を GET および POST するにはどうすればよいですか?
URL を https:// にすることはできますか?
Progress は HTTP Basic または HTTP Digest 認証を提供できますか?
Progress ドキュメントは SOAP に多くのインクをこぼしますが、Progress ABL を使用した単純な HTTP GET/POST の例を見つけるのに苦労しています。
URL との間で文字列を GET および POST するにはどうすればよいですか?
URL を https:// にすることはできますか?
Progress は HTTP Basic または HTTP Digest 認証を提供できますか?
この質問の将来の傍観者のために:
現在、Openedge には (11.5.1 以降だと思います)、REST ベースの Web サービスを呼び出すためのサポートが組み込まれています。これらは、デフォルトでは PROPATH にない提供された .pl アーカイブに含まれているため、最初に処理する必要があります (または、アーカイブを「より適切な場所」に移動できます)。
propath は、init ファイル、レジストリ、プログラムなど、さまざまな方法で設定できます。これが ABL で行う方法です (この方法で行う場合は、新しいセッションごとに繰り返す必要があります)。
PROPATH = PROPATH + ",c:\pathtoprogress\OpenEdge\gui\OpenEdge.Net.pl".
「tty」ディレクトリにもバージョンがあり、「src」ディレクトリにはソース コードを含むアーカイブがあります。
非常に基本的な例を次に示します。
USING OpenEdge.Net.HTTP.IHttpRequest.
USING OpenEdge.Net.HTTP.IHttpResponse.
USING OpenEdge.Net.HTTP.ClientBuilder.
USING OpenEdge.Net.HTTP.RequestBuilder.
DEFINE VARIABLE oRequest AS IHttpRequest NO-UNDO.
DEFINE VARIABLE oResponse AS IHttpResponse NO-UNDO.
oRequest = RequestBuilder:Get('http://stackoverflow.com/'):Request.
oResponse = ClientBuilder:Build():Client:Execute(oRequest).
MESSAGE
oResponse:StatusCode SKIP
oResponse:StatusReason SKIP
VIEW-AS ALERT-BOX.
Openedge には、SOAP サービスを処理するためのステートメントが組み込まれていますが、GET/POST のための単純なステートメントはありません。ただし、特定のソケットに読み書きするメカニズムがあります。したがって、これを使用して HTTP ポスト ルーチンを作成したり、その他のソケット ベースのプロトコルを処理するルーチンを作成したりできます。
GET を実行する http.p というルーチンがあります。他に何もなければ、ソケットプログラミングがどのように機能するかを確認できます。単純な POST を実行するように非常に簡単に変更できるはずですが、SSL を使用したり、認証を行ったりするには、かなりの作業が必要になる場合があります。この場合、CURL にドロップアウトする方が簡単かもしれません。
http.p は以前 freeframework.org から入手できましたが、確認したところそのドメインの有効期限が切れているため、以下のコードを投稿しました。
/*-----------------------------------------------------------------------*
File........: http.p
Version.....: 1.1
Description : Makes a "Get" request from an HTTP server
Input Param : pHost = host name (without the "http://")
pPort = port number (usually 80)
pURL = begin with the first slash after the domain name.
Output Param: pResult = 0 or 1 (character)
pResponse = http headers returned
pContent = the document returned.
Author......: S.E. Southwell, Mario Paranhos - United Systems, Inc. (770) 449-9696
Created.....: 12/13/2000
Notes.......: Will not work with HTTPS.
Usage:
define var v-result as char no-undo.
define var v-response as char no-undo.
define var v-content as char no-undo.
{&out} "Hello" skip.
put stream webstream control null(0).
run proc/http.p("www.whosplayin.com","80","/",output v-result,output v-response,output v-content).
{&out} v-result "<hr>" skip
html-encode(v-response) "<hr>" skip
html-encode(v-content) "<hr>" skip
.
Last Modified: 10/20/01 - SES - Fixed to work in batch mode, or within a UDF.
--------------------------------------------------------------------------*/
&SCOPED-DEFINE HTTP-NEWLINE CHR(13) + CHR(10)
&SCOPED-DEFINE RESPONSE-TIMEOUT 45
DEFINE INPUT PARAMETER pHOST AS CHAR NO-UNDO.
DEFINE INPUT PARAMETER pPORT AS CHAR NO-UNDO.
DEFINE INPUT PARAMETER pURL AS CHAR NO-UNDO.
DEFINE OUTPUT PARAMETER pRESULT AS CHAR NO-UNDO.
DEFINE OUTPUT PARAMETER pRESPONSE AS CHAR NO-UNDO.
DEFINE OUTPUT PARAMETER pContent AS CHAR NO-UNDO.
DEFINE VARIABLE requestString AS CHAR NO-UNDO.
DEFINE VARIABLE vSocket AS HANDLE NO-UNDO.
DEFINE VARIABLE vBuffer AS MEMPTR NO-UNDO.
DEFINE VARIABLE vloop AS LOGICAL NO-UNDO.
DEFINE VARIABLE vPackets AS INTEGER NO-UNDO.
DEFINE VARIABLE wStatus AS LOGICAL NO-UNDO.
ASSIGN requestString = "GET " + pURL + " HTTP/1.0" + {&HTTP-NEWLINE} +
"Accept: */*" + {&HTTP-NEWLINE} +
"Host: " + phost + {&HTTP-NEWLINE} +
/*"Connection: Keep-Alive" + {&HTTP-NEWLINE} + */
{&HTTP-NEWLINE}.
/*OPEN THE SOCKET*/
CREATE SOCKET vSocket.
vSocket:SET-READ-RESPONSE-PROCEDURE ("readHandler",THIS-PROCEDURE).
ASSIGN wstatus = vSocket:CONNECT("-H " + phost + " -S " + pport) NO-ERROR.
/*Now make sure the socket is open*/
IF wstatus = NO THEN DO:
pResult = "0:No Socket".
DELETE OBJECT vSocket.
RETURN.
END.
/*Got socket - Now make HTTP request*/
SET-SIZE(vBuffer) = LENGTH(requestString) + 1.
PUT-STRING(vBuffer,1) = requestString.
vSocket:WRITE(vBuffer, 1, LENGTH(requestString)).
SET-SIZE(vBuffer) = 0.
/*Wait for a response*/
ASSIGN vloop = TRUE. /*Turns off automatically when request is done*/
DEFINE VAR vstarttime AS INTEGER.
ASSIGN vstarttime = etime.
WAITLOOP: DO WHILE vloop:
PROCESS EVENTS.
PAUSE 1.
/* Build in timer in case sending is never set to NO
this will terminate the program after 60 seconds
start-Etime will be reset by WriteData each time there
is activity on the socket to allow for long transmissions */
IF vstarttime + ({&RESPONSE-TIMEOUT} * 1000) < ETIME
THEN DO:
MESSAGE "timed out at " + string(etime - vstarttime) + " msec".
vSocket:DISCONNECT().
ASSIGN pResult = "0:Failure".
RETURN.
END. /*No Response, or timed out*/
END.
/*At this point, pResponse should be populated with the result (up to 32K)*/
vSocket:DISCONNECT().
DELETE OBJECT vSocket.
/*All Done!*/
ASSIGN pResult = "1:Success".
ASSIGN
pContent = SUBSTRING(pResponse,INDEX(pResponse,{&HTTP-NEWLINE} + {&HTTP-NEWLINE}),-1)
.
ASSIGN
pResponse = SUBSTRING(pResponse,1,INDEX(pResponse,{&HTTP-NEWLINE} + {&HTTP-NEWLINE}))
.
RETURN.
/*Handle the response from the webserver*/
PROCEDURE readHandler:
DEFINE VARIABLE bytesAvail AS INTEGER NO-UNDO.
DEFINE VARIABLE b AS MEMPTR NO-UNDO.
DEFINE VARIABLE lastBytes AS INTEGER NO-UNDO.
IF vSocket:connected() THEN ASSIGN bytesAvail = vSocket:GET-BYTES-AVAILABLE().
IF bytesAvail = 0 THEN DO: /*All Done*/
ASSIGN vloop = FALSE.
RETURN.
END.
/*OK, there's something on the wire... Read it in*/
SET-SIZE(b) = bytesAvail + 1.
vSocket:READ(b, 1, bytesAvail, 1).
ASSIGN pResponse = pResponse + GET-STRING(b,1).
SET-SIZE(b) = 0.
END PROCEDURE. /*readHandler*/
Progress Kbase ID: 20011: 「4GL ソケットを使用して HTTP 経由で Web サイトにアクセスするためのサンプル コード」も、一般的な良い例です。