XTHC10 ;HCIOFO/SG - HTTP 1.1 CLIENT ; Oct 01, 2025 10:54
;;7.3;TOOLKIT;**123,566,162**;Apr 25, 1995;Build 4
;Per VA Directive 6402, this routine should not be modified.
;
Q
;##### GETS THE DATA FROM THE PROVIDED URL USING HTTP 1.1
;
; URL URL (http://host:port/path) (https://host:port/path)
;
; [XT8FLG] (Optional) Timeout and flags to control processing.
; If a value of this parameter starts with a number
; then this number is used as a value of the timeout
; (in seconds). Otherwise, the default value of 5
; seconds is used.
;
; [XT8RDAT] (Optional) Closed root of the variable where the message
; body is returned. Data is stored in consecutive
; nodes (numbers starting from 1). If a line is
; longer than 245 characters, only 245 characters
; are stored in the corresponding node. After that,
; overflow sub-nodes are created. For example:
;
; @XT8DATA@(1)="<html>"
; @XT8DATA@(2)="<head><title>VistA</title></head>"
; @XT8DATA@(3)="<body>"
; @XT8DATA@(4)="<p>"
; @XT8DATA@(5)="Beginning of a very long line"
; @XT8DATA@(5,1)="Continuation #1 of the long line"
; @XT8DATA@(5,2)="Continuation #2 of the long line"
; @XT8DATA@(5,...)=...
; @XT8DATA@(6)="</p>"
; ...
;
; [.XT8RHDR] (Optional) Reference to a local variable where the parsed
; headers are returned. Header names are converted to
; upper case and the values are left "as is". The root
; node contains the status line. For example:
;
; XT8HDR="HTTP/1.1 200 OK"
; XT8HDR("ACCEPT-RANGES")="bytes"
; XT8HDR("CONNECTION")="close"
; XT8HDR("CONTENT-LENGTH")="16402"
; XT8HDR("CONTENT-TYPE")="text/html; charset=UTF-8"
; XT8HDR("DATE")="Thu, 25 Jun 2015 14:43:01 GMT"
; XT8HDR("ETAG")="a93a2-4012-5180156550680"
; XT8HDR("LAST-MODIFIED")="Mon, 08 Jun 2015 13:08:26 GMT"
; XT8HDR("SERVER")="Apache/2.2.15 (CentOS)"
;
; [XT8SDAT] (Optional) Reference to a local variable containing the
; request message body. Data should be formatted as in
; variable XT8RDAT above.
;
; [.XT8SHDR] (Optional) Reference to a local variable containing header
; values, which will be added to the request.
; XT8SHDR("CONTENT-TYPE")="text/html"
;
; [XT8METH] (Optional) Flag to indicate the request method.
; "GET" - Default if XT8SDAT contains no data
; "POST" - Default if XT8SDAT contains data
; "HEAD"
; "PUT"
; "OPTIONS"
; "DELETE"
; "TRACE"
;
; Return values:
;
; <0 Error Descriptor
; >0 HTTP Status Code^Description
;
; Common HTTP status codes returned:
; 200 OK
; 301 Moved Permanently
; 400 Bad Request
; 401 Unauthorized
; 402 Payment Required
; 403 Forbidden
; 404 Not Found
; 405 Method Not Allowd
; 406 Not Acceptable
; 407 Proxy Authentication Required
; 408 Request Time-out
; 500 Internal Server Error
; 501 Not Implemented
; 502 Bad Gateway
; 503 Service Unavailable
; 504 Gateway Time-out
; 505 HTTP Version not supported
;
; See: www.ietf.org/rfc/rfc2616.txt (HTTP/1.1)
; www.ieft.org/rfc/rfc2617.txt (HTTP Authentication)
;
GETURL(URL,XT8FLG,XT8RDAT,XT8RHDR,XT8SDAT,XT8SHDR,XT8METH) ;
;ZEXCEPT: %Net,%New,ContentType,HttpRequest,Https,Location,OpenTimeout,Port,Server,SSLCheckServerIdentity,SSLConfiguration,class ; Cache ObjectScript methods and properties
;ZEXCEPT: Data,Get,GetHeader,GetNextHeader,Head,HttpResponse,Post,Put,ReadLine,ReasonPhrase,Send,SocketTimeout,StatusCode,StatusLine ; Cache ObjectScript methods and properties
N EOL,ERR,ESTATUS,HOST,I,J,K,LINENUM,NEWLINE,OVERFLOW,PATH,PORT,RDLEN,REQUEST,RESPONSE,STATUS,X,Y
N REDIRECTCOUNT,MAXDIRECTS,XX,XLENGTH,XPIECE,XLEFTOVER,YY,HASLF
;
S $ZT="ERROR"
;
S URL=$G(URL) I URL="" Q "-1^Missing URL"
S XT8FLG=$G(XT8FLG) S:XT8FLG'?1.N.E XT8FLG="5"_XT8FLG
;
I $G(XT8METH)'?1(1"GET",1"POST",1"HEAD",1"PUT",1"OPTIONS",1"DELETE",1"TRACE") D
. I $D(XT8SDAT) S XT8METH="POST"
. I '$D(XT8SDAT) S XT8METH="GET"
;
;Check IO
I '$D(IO(0)) D HOME^%ZIS
;
S STATUS=0,MAXDIRECTS=5
F REDIRECTCOUNT=1:1:MAXDIRECTS D Q:+STATUS'=""&(+STATUS'?1"3".E)
. S REQUEST=##class(%Net.HttpRequest).%New()
. I '$IsObject(REQUEST) S STATUS="-1^Unable to create HTTP Request object" Q
. S REQUEST.SSLConfiguration="encrypt_only_tlsv12" ;"encrypt_only_all"
. S REQUEST.SSLCheckServerIdentity=1
. S I=$$PARSEURL^XTHCURL(URL,.HOST,.PORT,.PATH) I I<0 S STATUS=I Q
. ;
. S REQUEST.Https=($$UP^XLFSTR(URL)?1"HTTPS://".E)
. S REQUEST.Server=HOST
. S REQUEST.Port=PORT
. I $G(PATH)'="" S REQUEST.Location=PATH
. S REQUEST.ContentType="text/html" ;Default. Can be overwritten by a custom header in XT8SHDR
. S REQUEST.UserAgent="VistA/2.0" ;Default. Can be overwritten by a custom header in XT8SHDR
. S REQUEST.OpenTimeout=+XT8FLG
. S REQUEST.SocketTimeout=0
. ;
. ;Set custom headers
. S I="" F S I=$O(XT8SHDR(I)) Q:I="" D REQUEST.SetHeader(I,XT8SHDR(I))
. ;
. I XT8METH?1(1"POST",1"PUT",1"OPTIONS",1"DELETE",1"TRACE") D
. . S I=""
. . F S I=$O(@XT8SDAT@(I)) Q:I="" D ;load an entire page, not just key/value pairs
. . . S NEWLINE=$G(@XT8SDAT@(I))
. . . D REQUEST.EntityBody.Write(NEWLINE)
. . . S J=""
. . . F S J=$O(@XT8SDAT@(I,J)) Q:J="" D REQUEST.EntityBody.Write($G(@XT8SDAT@(I,J)))
. . . D REQUEST.EntityBody.WriteLine("")
. ;
. S REQUEST.FollowRedirect=0 ;disable redirects, we will handle it
. S ESTATUS=REQUEST.Send(XT8METH,"")
. I 'ESTATUS D $system.Status.DecomposeStatus(ESTATUS,.ERR) S STATUS="-1^"_ERR(1) D APPERROR^%ZTER(ERR(1)) Q
. ;
. S RESPONSE=REQUEST.HttpResponse ;Sets the %Net.HttpResponse object
. I '$IsObject(RESPONSE) S STATUS="-1^Did not receive HTTP Response" Q
. S STATUS=RESPONSE.StatusCode_"^"_RESPONSE.ReasonPhrase
. I +STATUS?1"3".E D
. . S URL=RESPONSE.GetHeader("Location") I URL="" S STATUS="-1^Missing redirection URL." Q
. . I XT8METH'="GET" S XT8METH="GET"
. . D REQUEST.EntityBody.Clear()
. . Q
. ;
. ;--- Header - Enter header into XT8RHDR
. S XT8RHDR=RESPONSE.StatusLine
. S I=""
. F D Q:I=""
. . S I=RESPONSE.GetNextHeader(I) Q:I="" ;Name of header
. . S XT8RHDR(I)=RESPONSE.GetHeader(I) ;Value of header I
. ;--- Data - Read stream one line at a time and enter into XT8RDAT
. S LINENUM=1
. S OVERFLOW=0
. S (XLEFTOVER,HASLF)=""
. F J=1:1 D Q:(RESPONSE.Data.AtEnd)!(+STATUS=-1) ;quit if at end of data stream or error
. . S ESTATUS="" ;Status object
. . S EOL=""
. . S RDLEN=245
. . S X=RESPONSE.Data.ReadLine(.RDLEN,.ESTATUS,.EOL) I X[$C(10),HASLF="" S HASLF=1
. . I 'ESTATUS D
. . . D $system.Status.DecomposeStatus(ESTATUS,.ERR) S STATUS="-1^"_ERR(1)
. . E I $D(XT8RDAT)>0 D
. . . I HASLF D
. . . . S X=XLEFTOVER_X I X'[$C(10) S XLEFTOVER=X Q
. . . . S XLENGTH=$L(X,$C(10))
. . . . F XX=1:1:XLENGTH D
. . . . . I XX=XLENGTH S XLEFTOVER=$P(X,$C(10),XX) Q
. . . . . S XPIECE=$P(X,$C(10),XX)
. . . . . I $L(XPIECE)>RDLEN D
. . . . . . S YY=$E(XPIECE,1,RDLEN)
. . . . . . S @XT8RDAT@(LINENUM)=YY
. . . . . . S XPIECE=$E(XPIECE,RDLEN+1,$L(XPIECE))
. . . . . . D OVERFLOW(XPIECE,XT8RDAT,RDLEN,LINENUM)
. . . . . E S @XT8RDAT@(LINENUM)=XPIECE
. . . . . S LINENUM=LINENUM+1
. . . E D
. . . . I 'OVERFLOW S @XT8RDAT@(LINENUM)=X
. . . . I OVERFLOW S @XT8RDAT@(LINENUM,OVERFLOW)=X
. . . . S OVERFLOW=OVERFLOW+1
. . . . I EOL D
. . . . . S LINENUM=LINENUM+1
. . . . . S OVERFLOW=0
I +STATUS?1"3".E S STATUS="-1^Too many redirects"
Q STATUS
;
OVERFLOW(DATA,XT8RDAT,RDLEN,LINENUM) ;XT162
I $G(DATA)=""!($G(XT8RDAT)="")!($G(LINENUM)="") Q
;
S $ZT="ERROR"
S RDLEN=$G(RDLEN,245)
N DONE,OVERFLOW,XDATA
S DONE="",OVERFLOW=0
F D Q:DONE
. S XDATA=$E(DATA,1,RDLEN) I $L(DATA)<=RDLEN S DONE=1
. S OVERFLOW=OVERFLOW+1
. S @XT8RDAT@(LINENUM,OVERFLOW)=XDATA
. S DATA=$E(DATA,RDLEN+1,$L(DATA))
Q
;
ERROR ;capture the error
S $ZT=""
D BACK^%ETN
Q
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HXTHC10 8796 printed Sep 17, 2026@21:27:05 Page 2
XTHC10 ;HCIOFO/SG - HTTP 1.1 CLIENT ; Oct 01, 2025 10:54
+1 ;;7.3;TOOLKIT;**123,566,162**;Apr 25, 1995;Build 4
+2 ;Per VA Directive 6402, this routine should not be modified.
+3 ;
+4 QUIT
+5 ;##### GETS THE DATA FROM THE PROVIDED URL USING HTTP 1.1
+6 ;
+7 ; URL URL (http://host:port/path) (https://host:port/path)
+8 ;
+9 ; [XT8FLG] (Optional) Timeout and flags to control processing.
+10 ; If a value of this parameter starts with a number
+11 ; then this number is used as a value of the timeout
+12 ; (in seconds). Otherwise, the default value of 5
+13 ; seconds is used.
+14 ;
+15 ; [XT8RDAT] (Optional) Closed root of the variable where the message
+16 ; body is returned. Data is stored in consecutive
+17 ; nodes (numbers starting from 1). If a line is
+18 ; longer than 245 characters, only 245 characters
+19 ; are stored in the corresponding node. After that,
+20 ; overflow sub-nodes are created. For example:
+21 ;
+22 ; @XT8DATA@(1)="<html>"
+23 ; @XT8DATA@(2)="<head><title>VistA</title></head>"
+24 ; @XT8DATA@(3)="<body>"
+25 ; @XT8DATA@(4)="<p>"
+26 ; @XT8DATA@(5)="Beginning of a very long line"
+27 ; @XT8DATA@(5,1)="Continuation #1 of the long line"
+28 ; @XT8DATA@(5,2)="Continuation #2 of the long line"
+29 ; @XT8DATA@(5,...)=...
+30 ; @XT8DATA@(6)="</p>"
+31 ; ...
+32 ;
+33 ; [.XT8RHDR] (Optional) Reference to a local variable where the parsed
+34 ; headers are returned. Header names are converted to
+35 ; upper case and the values are left "as is". The root
+36 ; node contains the status line. For example:
+37 ;
+38 ; XT8HDR="HTTP/1.1 200 OK"
+39 ; XT8HDR("ACCEPT-RANGES")="bytes"
+40 ; XT8HDR("CONNECTION")="close"
+41 ; XT8HDR("CONTENT-LENGTH")="16402"
+42 ; XT8HDR("CONTENT-TYPE")="text/html; charset=UTF-8"
+43 ; XT8HDR("DATE")="Thu, 25 Jun 2015 14:43:01 GMT"
+44 ; XT8HDR("ETAG")="a93a2-4012-5180156550680"
+45 ; XT8HDR("LAST-MODIFIED")="Mon, 08 Jun 2015 13:08:26 GMT"
+46 ; XT8HDR("SERVER")="Apache/2.2.15 (CentOS)"
+47 ;
+48 ; [XT8SDAT] (Optional) Reference to a local variable containing the
+49 ; request message body. Data should be formatted as in
+50 ; variable XT8RDAT above.
+51 ;
+52 ; [.XT8SHDR] (Optional) Reference to a local variable containing header
+53 ; values, which will be added to the request.
+54 ; XT8SHDR("CONTENT-TYPE")="text/html"
+55 ;
+56 ; [XT8METH] (Optional) Flag to indicate the request method.
+57 ; "GET" - Default if XT8SDAT contains no data
+58 ; "POST" - Default if XT8SDAT contains data
+59 ; "HEAD"
+60 ; "PUT"
+61 ; "OPTIONS"
+62 ; "DELETE"
+63 ; "TRACE"
+64 ;
+65 ; Return values:
+66 ;
+67 ; <0 Error Descriptor
+68 ; >0 HTTP Status Code^Description
+69 ;
+70 ; Common HTTP status codes returned:
+71 ; 200 OK
+72 ; 301 Moved Permanently
+73 ; 400 Bad Request
+74 ; 401 Unauthorized
+75 ; 402 Payment Required
+76 ; 403 Forbidden
+77 ; 404 Not Found
+78 ; 405 Method Not Allowd
+79 ; 406 Not Acceptable
+80 ; 407 Proxy Authentication Required
+81 ; 408 Request Time-out
+82 ; 500 Internal Server Error
+83 ; 501 Not Implemented
+84 ; 502 Bad Gateway
+85 ; 503 Service Unavailable
+86 ; 504 Gateway Time-out
+87 ; 505 HTTP Version not supported
+88 ;
+89 ; See: www.ietf.org/rfc/rfc2616.txt (HTTP/1.1)
+90 ; www.ieft.org/rfc/rfc2617.txt (HTTP Authentication)
+91 ;
GETURL(URL,XT8FLG,XT8RDAT,XT8RHDR,XT8SDAT,XT8SHDR,XT8METH) ;
+1 ;ZEXCEPT: %Net,%New,ContentType,HttpRequest,Https,Location,OpenTimeout,Port,Server,SSLCheckServerIdentity,SSLConfiguration,class ; Cache ObjectScript methods and properties
+2 ;ZEXCEPT: Data,Get,GetHeader,GetNextHeader,Head,HttpResponse,Post,Put,ReadLine,ReasonPhrase,Send,SocketTimeout,StatusCode,StatusLine ; Cache ObjectScript methods and properties
+3 NEW EOL,ERR,ESTATUS,HOST,I,J,K,LINENUM,NEWLINE,OVERFLOW,PATH,PORT,RDLEN,REQUEST,RESPONSE,STATUS,X,Y
+4 NEW REDIRECTCOUNT,MAXDIRECTS,XX,XLENGTH,XPIECE,XLEFTOVER,YY,HASLF
+5 ;
+6 SET $ZT="ERROR"
+7 ;
+8 SET URL=$GET(URL)
IF URL=""
QUIT "-1^Missing URL"
+9 SET XT8FLG=$GET(XT8FLG)
if XT8FLG'?1.N.E
SET XT8FLG="5"_XT8FLG
+10 ;
+11 IF $GET(XT8METH)'?1(1"GET",1"POST",1"HEAD",1"PUT",1"OPTIONS",1"DELETE",1"TRACE")
Begin DoDot:1
+12 IF $DATA(XT8SDAT)
SET XT8METH="POST"
+13 IF '$DATA(XT8SDAT)
SET XT8METH="GET"
End DoDot:1
+14 ;
+15 ;Check IO
+16 IF '$DATA(IO(0))
DO HOME^%ZIS
+17 ;
+18 SET STATUS=0
SET MAXDIRECTS=5
+19 FOR REDIRECTCOUNT=1:1:MAXDIRECTS
Begin DoDot:1
+20 SET REQUEST=##class(%Net.HttpRequest).%New()
+21
*** ERROR ***
IF '$IsObject(REQUEST)
SET STATUS="-1^Unable to create HTTP Request object"
QUIT
+22 ;"encrypt_only_all"
SET REQUEST.SSLConfiguration="encrypt_only_tlsv12"
+23 SET REQUEST.SSLCheckServerIdentity=1
+24 SET I=$$PARSEURL^XTHCURL(URL,.HOST,.PORT,.PATH)
IF I<0
SET STATUS=I
QUIT
+25 ;
+26 SET REQUEST.Https=($$UP^XLFSTR(URL)?1"HTTPS://".E)
+27 SET REQUEST.Server=HOST
+28 SET REQUEST.Port=PORT
+29 IF $GET(PATH)'=""
SET REQUEST.Location=PATH
+30 ;Default. Can be overwritten by a custom header in XT8SHDR
SET REQUEST.ContentType="text/html"
+31 ;Default. Can be overwritten by a custom header in XT8SHDR
SET REQUEST.UserAgent="VistA/2.0"
+32 SET REQUEST.OpenTimeout=+XT8FLG
+33 SET REQUEST.SocketTimeout=0
+34 ;
+35 ;Set custom headers
+36 SET I=""
FOR
SET I=$ORDER(XT8SHDR(I))
if I=""
QUIT
DO REQUEST.SetHeader(I,XT8SHDR(I))
+37 ;
+38 IF XT8METH?1(1"POST",1"PUT",1"OPTIONS",1"DELETE",1"TRACE")
Begin DoDot:2
+39 SET I=""
+40 ;load an entire page, not just key/value pairs
FOR
SET I=$ORDER(@XT8SDAT@(I))
if I=""
QUIT
Begin DoDot:3
+41 SET NEWLINE=$GET(@XT8SDAT@(I))
+42 DO REQUEST.EntityBody.Write(NEWLINE)
+43 SET J=""
+44 FOR
SET J=$ORDER(@XT8SDAT@(I,J))
if J=""
QUIT
DO REQUEST.EntityBody.Write($GET(@XT8SDAT@(I,J)))
+45 DO REQUEST.EntityBody.WriteLine("")
End DoDot:3
End DoDot:2
+46 ;
+47 ;disable redirects, we will handle it
SET REQUEST.FollowRedirect=0
+48 SET ESTATUS=REQUEST.Send(XT8METH,"")
+49 IF 'ESTATUS