Как мне сделать HTTP GET и POST в Progress / OpenEdge ABL? - PullRequest
5 голосов
/ 14 января 2010

Документы Progress проливают много чернил на SOAP, но мне не удается найти пример простого HTTP GET / POST с Progress ABL.

Как мне получать и отправлять строки в / из URL?

Может ли URL быть https: //?

Может ли Progress обеспечивать базовую аутентификацию HTTP или дайджест-проверку подлинности HTTP?

Ответы [ 4 ]

9 голосов
/ 15 января 2010

В Openedge есть встроенные операторы для обработки сервисов SOAP, но нет простого оператора для GET / POST.Однако он имеет механизм чтения / записи в определенные сокеты.Таким образом, вы можете использовать это для создания HTTP-подпрограммы или, в этом случае, подпрограммы для обработки любого другого протокола на основе сокетов.

Существует подпрограмма - http.p, которая сделает GET для вас.Позволит вам увидеть, как работает программирование сокетов, если ничего другого.Вы должны быть в состоянии изменить это довольно легко, чтобы сделать простой 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*/
8 голосов
/ 20 апреля 2016

Для будущих зрителей по этому вопросу:

Openedge сейчас (начиная с 11.5.1, я полагаю) имеет встроенную поддержку для вызова веб-сервисов на основе REST. Они включены в предоставленный архив .pl, который по умолчанию отсутствует в PROPATH, поэтому его необходимо обработать в первую очередь (или архив можно переместить в «лучшее место»).

Пропат может быть задан несколькими способами, файлами инициализации, реестром, программно и т. Д. Вот как это можно сделать в 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.

Документацию по 11.6 можно найти здесь.

2 голосов
/ 16 января 2010

Progress Kbase ID: 20011: «Пример кода для доступа к веб-сайту через HTTP с сокетами 4GL» также является хорошим, обобщенным примером.

0 голосов
/ 19 сентября 2013

Я рекомендую использовать приведенный выше пример кода Гордона Роберертсона, потому что в статье Progress KB вместо «WAIT-FOR» заменен цикл. Таким образом, процедура прекращается после истечения времени ожидания, если что-то пойдет не так.

Обратите внимание, что изменение чего-либо в requestString может привести к тайм-ауту. Но добавление User-Agent возможно, если вам нужно войти на ваш веб-сервер:

ASSIGN requestString = "GET " + Path + " HTTP/1.0" + {&HTTP-NEWLINE}
               + "Accept: */*" + {&HTTP-NEWLINE}
               + "User-Agent: " + "User Agent String" + {&HTTP-NEWLINE}
               + "Host: " + Host + {&HTTP-NEWLINE}
               + {&HTTP-NEWLINE}.

Спасибо Гордону за пример кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...