Как выполнить HTTP GET и POST in Progress / OpenEdge ABL?

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

Как мне ПОЛУЧИТЬ и отправить строки в / из URL-адреса?

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

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


person joeforker    schedule 14.01.2010    source источник
comment
На самом деле мы выделили отдельную программу (Python) для предоставления доступа по протоколу HTTP. Это было проще, чем пытаться реализовать такой же полнофункциональный HTTP в ABL.   -  person joeforker    schedule 20.09.2013


Ответы (4)


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

Существует процедура - 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*/
person Gordon Robertson    schedule 15.01.2010

Для будущих зевак, ответивших на этот вопрос:

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.

person Jensd    schedule 20.04.2016

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

person Tom Bascom    schedule 16.01.2010

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

Обратите внимание, что изменение чего-либо в 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}.

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

person Thomas Bluehmann    schedule 19.09.2013