# RXS_Transmit()

Performs a HTTP/HTTPS request - allowing you to exchange data with a remote web service.

To properly communicate with a web service, you will need to configure the RXS_TransmitDS_t data structure passed in as a parameter.

## Subprocedure Prototype

### IBM i 7.1+

```rpgle
      // Returns the response data. Note that if RXS_TransmitDS_t.ResponseStmf is
      //   set to an IFS path, the response will be stored there instead.
     D RXS_Transmit...
     D                 PR                  Extproc('RXS_Transmit') Opdesc
     D                                     Like(RXS_Var16Mv_t)
     D                                     Rtnparm

      // Holds the request data. Note that if RXS_TransmitDS_t.RequestStmf is set
      //   to an IFS path, the request will be read from there instead.
     D  pRequest                           Like(RXS_Var16Mv_t) Const
     D                                     Options(*Omit:*Varsize)

      // Controls how RXS_Transmit performs the HTTP/HTTPs request. Uses
      //   RXS_TransmitDS_t as a template.
     D  pDS                                LikeDS(RXS_TransmitDS_t)
     D                                     Options(*Varsize)
```


## Example Code

### IBM i 7.1+

#### HTTP GET
```rpgle
      *--------------------------------------------------------------
      * This example performs a simple HTTP GET operation against the URL example.com and stores the retrieved response data in the field Response.
      * Because this is a HTTP GET, we don't need to pass a Request parameter.
      * During the execution of RXS_Transmit(), the API will create a log file at '/tmp/rxs_transmit1_log.txt'
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'https://example.com/';
        TransmitDS.HTTPMethod = RXS_HTTP_METHOD_GET;
        TransmitDS.LogFile = '/tmp/rxs_transmit1_log.txt';
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

#### HTTP POST
```rpgle
      *--------------------------------------------------------------
      * This example performs a HTTP POST against a public web service that provides conversion between Fahrenheit and Celsius.
      * This is a HTTP POST, so we need to provide a Request parameter.
      * Because this is using SOAP, we need to specify Content-type and SOAPAction headers.
      * Lastly, this example uses RXS_JobLog() to write the full response XML to the job log.
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Request         S                   Like(RXS_Var64Kv_t)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        Request = '<?xml version="1.0" encoding="utf-8"?>' +
         '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'+
         ' xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="' +
         'http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>' +
         '<FahrenheitToCelsius xmlns="http://www.w3schools.com/webservices/">'+
         '<Fahrenheit>100</Fahrenheit></FahrenheitToCelsius>' +
         '</soap:Body></soap:Envelope>';

        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI =
          'http://www.w3schools.com/webservices/tempconvert.asmx';
        TransmitDS.HTTPMethod = RXS_HTTP_METHOD_POST;
        TransmitDS.LogFile = '/tmp/rxs_transmit2_log.txt';
        TransmitDS.HeaderContentType = 'text/xml; charset=utf-8';
        TransmitDS.HeaderSOAPAction =
          '"http://www.w3schools.com/webservices/FahrenheitToCelsius"';
        Response = RXS_Transmit( Request : TransmitDS );

        RXS_JobLog( Response );

        *INLR = *ON;
      /end-free
```

#### HTTP Custom Headers
```rpgle
      *--------------------------------------------------------------
      * This example demonstrates how to set custom HTTP headers with RXS_Transmit(). 
      * You may specify up to 50 custom HTTP headers sent with a request.
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'https://example.com/';
        // Set a custom HTTP header that looks like this:
        // X-API-Token: [your-api-token]
        TransmitDS.CustomHeaderName(1) = 'X-API-Token';
        TransmitDS.CustomHeaderValue(1) = '[your-api-token]'; 
        // Set a custom HTTP header that looks like this:
        // ExampleHeader: hello world
        TransmitDS.CustomHeaderName(2) = 'ExampleHeader';  
        TransmitDS.CustomHeaderValue(2) = 'hello world';
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

#### HTTP Basic Authentication
```rpgle
      *--------------------------------------------------------------
      * This example demonstrates how to specify a username and
      * password for HTTP Basic Authentication with RXS_Transmit().
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'https://example.com/';
        TransmitDS.BasicAuthUser = 'username';
        TransmitDS.BasicAuthPassword = 'password';    
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

#### HTTP Bearer Authentication
```rpgle
      *--------------------------------------------------------------
      * This examples showcases using RXS_Transmit to set an Authorization header. 
      * When using CustomHeaderName and CustomHeaderValue arrays with RXS_Transmit()
      * to set an Authorization header, the Bearer portion needs to go in the Value 
      * field, followed by a space before the API key is concatenated to the Value field. 
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'https://example.com/';
        TransmitDS.CustomHeaderName(1) = 'Authorization';
        TransmitDS.CustomHeaderValue(1) = 'Bearer ' + '[your-api-token]';
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

#### HTTP Cookie Header Data
```rpgle
      *--------------------------------------------------------------
      * This example showcases sending cookie data. However, instead of 
      * reading the data from a file, you may specify it by utilizing
      * HeaderCookieData.
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'example.com';
        TransmitDS.HeaderCookieData = 'your cookie data';
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

#### HTTP Cookie Header File
```rpgle
      *--------------------------------------------------------------
      * This example showcases sending cookie data, utilizing an IFS
      * file which contains said data.
      *--------------------------------------------------------------
     H DFTACTGRP(*NO) BNDDIR('RXSBND') ACTGRP(*CALLER)

      /copy QRPGLECPY,RXSCB

     D TransmitDS      DS                  LikeDS(RXS_TransmitDS_t)
     D                                     Inz(*LikeDS)
     D Response        S                   Like(RXS_Var64Kv_t)
      /free
        RXS_ResetDS( TransmitDS : RXS_DS_TYPE_TRANSMIT );
        TransmitDS.URI = 'example.com';
        TransmitDS.HeaderCookieFiles(1) = '/tmp/cookie.txt';
        Response = RXS_Transmit( *Omit : TransmitDS );

        *INLR = *ON;
      /end-free
```

## Data Structures

### RXS_TransmitDS_t

```rpgle
     D RXS_TransmitDS_t...
     D                 DS                  Qualified Template Inz

      // If an error occurs during processing, additional error information may
      //   be returned in this data structure.
     D   ReturnedErrorInfo...
     D                                     LikeDS(RXS_ReturnedErrorInfoDS_t) Inz

      // Internal use only
     D   DataStructureType...
     D                                5I 0 Inz(RXS_DS_TYPE_TRANSMIT)

     D   OnErrorMessageType...
     D                                5I 0

      // Specify the full URI used for the request. If a non-standard port (e.g.
      //   other than 80 for an HTTP request, and 443 for an HTTPS request) is
      //   needed, this must be specified in the request.
      // Example: https://testuri.org:9001/webservice
     D   URI                               Like(RXS_Var8Kv_t)

      // An IFS path can be specified in this subfield - if it is, it will be
      //   used as the request data instead of the value of the pRequest parm.
     D   RequestStmf                       Like(RXS_Var1Kv_t)

      // Specify the CCSID of the data to be sent to the remote server. If
      //   required, the data in the Request parameter will be converted to this
      //   CCSID before transmission to the remote server.
      // Default: RXS_CCSID_UTF8
     D   RequestCcsid                10I 0 Inz(RXS_CCSID_UTF8)

      // An IFS path can be specified in this subfield - if it is, any output of
      //   the RXS_Transmit operation will be stored in the specified IFS file.
     D   ResponseStmf                      Like(RXS_Var1Kv_t)

      // If the response is being stored in an IFS stream file (determined by
      //   whether or not the ResponseStmf subfield is occupied), the response data
      //   will be converted to this CCSID. The stream file will also be created
      //   with this CCSID.
      // Default: RXS_CCSID_UTF8
     D   ResponseStmfCcsid...
     D                               10I 0 Inz(RXS_CCSID_UTF8)

      // Specify a value in seconds for a timeout on the request.
      // Default: 60
     D   Timeout                     10U 0 Inz(60)

      // Determines the HTTP request method used.
      // Valid values: RXS_HTTP_METHOD_GET, RXS_HTTP_METHOD_POST,
      //   RXS_HTTP_METHOD_PUT, RXS_HTTP_METHOD_DELETE, RXS_HTTP_METHOD_PATCH,
      //   RXS_HTTP_METHOD_HEAD, RXS_HTTP_METHOD_OPTIONS
      // Default: RXS_HTTP_METHOD_POST
     D   HTTPMethod                   3I 0 Inz(RXS_HTTP_METHOD_POST)

      // An IFS path can be specified to log the request & response, as well as
      //   additional HTTP request debugging information. This option is disabled
      //   by default, and should not be left enabled in production environments
      //   due to increased execution time and privacy concerns.
     D   LogFile                           Like(RXS_Var1Kv_t)

      // Specify a value in seconds to cause a timeout during an SSL handshake.
      // Default: 300
     D   SSLTimeout                  10U 0 Inz(300)

      // Used to assign an application ID for RXS_Transmit.
     D   SSLApplicationID...
     D                                     Like(RXS_Var1Kv_t)

      // If a SSL certificate store other than the *SYSTEM store should be used,
      //   the IFS path can be specified here.
     D   SSLCertStore...
     D                                     Like(RXS_Var1Kv_t)

      // If using a non-*SYSTEM SSL certificate store, the password can be
      //   specified here.
     D   SSLCertStorePassword...
     D                                     Like(RXS_Var1Kv_t)

      // This option determines whether RXS_Transmit verifies the authenticity of
      //   the peer's certificate. Setting this to RXS_NO this in a production
      //   capacity is strongly discouraged.
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_YES
     D   SSLVerifyPeer...
     D                                 N   Inz(RXS_YES)

      // This option determines whether RXS_Transmit verifies that the server
      //   certificate is for the server it is known as. Setting this to RXS_NO
      //   this in a production capacity is strongly discouraged.
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_YES
     D   SSLVerifyHost...
     D                                 N   Inz(RXS_YES)

      // Specify the HTTP protocol version being used.
      // Valid values: RXS_HTTP_VERSION_ANY, RXS_HTTP_VERSION_11,
      //   RXS_HTTP_VERSION_10
      // Default: RXS_HTTP_VERSION_ANY
     D   HTTPVersion                  4P 2 Inz(RXS_HTTP_VERSION_ANY)

      // Specify the user ID for this parameter if Basic Authentication is used
      //   on this request.
     D   BasicAuthUser...
     D                                     Like(RXS_Var1Kv_t)

      // Specify the password for this parameter if Basic Authentication is used
      //   on this request.
     D   BasicAuthPassword...
     D                                     Like(RXS_Var1Kv_t)

      // Specifies the URI used as a proxy for the request.
     D   ProxyURI                          Like(RXS_Var1Kv_t)

      // If using a proxy on this request that requires a user id and password,
      //   specify the proxy user id in this subfield.
     D   ProxyUser...
     D                                     Like(RXS_Var1Kv_t)

      // If using a proxy on this request that requires a user id and password,
      //   specify the proxy password in this subfield.
     D   ProxyPassword...
     D                                     Like(RXS_Var1Kv_t)

      // Specifies if HTTP headers should be sent with the request. RXS_YES will
      //   tell RXS_Transmit that all HTTP headers as well as the user defined
      //   headers are sent with the request. RXS_NO will tell RXS_Transmit that no
      //   HTTP headers are sent with the request - only the request data is sent.
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_YES
     D   SendHTTPHeaders...
     D                                 N   Inz(RXS_YES)

      // Specify any cookie data to be sent with this request. Further
      //   instructions for formatting this data is available at RFC2109.
     D   HeaderCookieData...
     D                                     Like(RXS_Var8Kv_t)

      // Paths to IFS files may be specified which contain cookie data. Further
      //   instructions for formatting this data is available at RFC2109. Size of
      //   array reduced from 50 to 10 in RXS 3.4.3.
     D   HeaderCookieFiles...
     D                                     Like(RXS_Var1Kv_t) Dim(10)

      // If calling a SOAP web service, the SOAPAction HTTP header field is
      //   generally required. This is typically surrounded by double quotes.
      // Example: "http://electrocommerce.org/abc#MyMessage"
     D   HeaderSOAPAction...
     D                                     Like(RXS_Var1Kv_t)

      // Some web applications may function differently depending upon the user
      //   agent specified.
      // Default: KrengelTech HTTP Client
     D   HeaderUserAgent...
     D                                     Like(RXS_Var1Kv_t)
     D                                     Inz('KrengelTech HTTP Client')

      // Populates the HTTP Accept header, used to specify which data type(s)
      //   this service will accept in a response.
     D   HeaderAccept                      Like(RXS_Var1Kv_t)

      // Populates the HTTP Host header, which specifies the host address and
      //   port number of the requested resource. This information is generally
      //   obtained from the service URI. This field is required for HTTP/1.1
      //   communications.
     D   HeaderHost                        Like(RXS_Var1Kv_t)

      // Sets the HTTP Referer header, which can be used to specify a URI from
      //   which this service address was obtained.
     D   HeaderReferer...
     D                                     Like(RXS_Var1Kv_t)

      // Sets the HTTP Connection header, which is used to specify
      //   connection-specific options.
     D   HeaderConnection...
     D                                     Like(RXS_Var1Kv_t)

      // The MIME type of the body of the request (used with POST requests).
      // Default: text/xml
     D   HeaderContentType...
     D                                     Like(RXS_Var1Kv_t)

      // Specifies the name of up to 50 custom HTTP headers sent with the
      //   request. These names are paired with the values, below.
     D   CustomHeaderName...
     D                               64A   Varying Dim(50)

      // Specifies the value of up to 50 custom HTTP headers sent with the
      //   request. These values are paired with the names, above. Size increased
      //   from 1k to 4k in RXS 3.4.3.
     D   CustomHeaderValue...
     D                                     Like(RXS_Var4Kv_t) Dim(50)

      // Populated by RXS_Transmit at the end of the request. Contains response
      //   information from the completed HTTP communication.
     D   HTTPResponse                      LikeDS(RXS_HTTPResponseDS_t)
     D                                     Inz(*LikeDS)

      // Internal use only
     D   InputPointer...
     D                                 *

      // Internal use only
     D   InputLength                 10I 0

      // Internal use only
     D   OutputPointer...
     D                                 *

      // Internal use only
     D   OutputLength                10I 0

      // The CCSID of the data supplied in the Request parameter of
      //   RXS_Transmit(). If required, the data will be converted from the
      //   InputCcsid into the RequestCcsid before being transmitted.
      // Default: RXS_CCSID_JOB
     D   InputCCSID                  10I 0 Inz(RXS_CCSID_JOB)

      // The CCSID of the data to be returned in the Response parameter of
      //   RXS_Transmit().
      // Default: RXS_CCSID_JOB
     D   OutputCCSID                 10I 0 Inz(RXS_CCSID_JOB)

      // The CCSID of the data to be written to the logfile, when logfile
      //   creation is enabled.
      // Default: RXS_CCSID_UTF8
     D   LogFileCCSID                10I 0 Inz(RXS_CCSID_UTF8)

      // Controls whether new logging data will be appended to the logfile, or if
      //   any existing data will be overwritten.
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_NO
     D   LogFileAppend...
     D                                 N   Inz(RXS_NO)

      // Specify a procedure pointer to a custom logging handler
     D   LogHandler...
     D                                 *   Procptr

      // Internal use only
     D   LogHandlerData...
     D                                 *

      // Internal use only
     D   LogHandlerDataLength...
     D                               10I 0

      // Specifies that the expect header should be sent with the request
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_NO
     D   EnableExpectHeader...
     D                                 N   Inz(RXS_NO)

      // Specify the IP address and optionally the port of the desired interface
      //   to bind to when transmiting to the remote server. When a port is
      //   specified, it will be separated from the IP with a colon: IP:Port
     D   LocalInterface...
     D                               64A   Varying

      // Allow RXS_Transmit() to use IPv6 protocol
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_NO
     D   EnableIPv6...
     D                                 N   Inz(RXS_NO)

      // Controls whether RXS_Transmit() should follow HTTP 3XX redirects
      // Valid values: RXS_YES, RXS_NO
      // Default: RXS_YES
     D   FollowRedirects...
     D                                 N   Inz(RXS_YES)
```


### RXS_HTTPResponseDS_t

```rpgle
     D RXS_HTTPResponseDS_t...
     D                 DS                  Qualified Template Inz

      // HTTP status code returned by the remote server
     D   StatusCode...
     D                               10I 0

      // A string containing all headers returned by the server. These headers
      //   are further parsed individually below.
     D   UnparsedHeaders...
     D                                     Like(RXS_Var64Kv_t)

      // An array of the parsed header names. These are paired with the header
      //   values, below.
     D   HeaderName                  64A   Varying Dim(50)

      // An array of the parsed header values. These are paired with the header
      //   names, above. Size increased from 1k to 4k in RXS 3.4.3.
     D   HeaderValue                       Like(RXS_Var4Kv_t) Dim(50)

      // Timestamp for the start of the connection
     D   TimeStart                     Z   Inz(*LOVAL)

      // Timestamp for the end of the connection
     D   TimeEnd                       Z   Inz(*LOVAL)

      // Total duration of the HTTP communication
     D   TimeDuration                 8F   Inz(*ZERO)
```

