HttpCommand
Repository | https://github.com/dyalog/httpcommand |
Copyright | Made with Material for MkDocs Copyright © 2015-2024 Dyalog, LTD |
HttpCommand
is a utility is designed to make it easy for the APL user to send requests to and receive responses from HTTP servers like web servers and web services.
Note
While HttpCommand
itself is ⎕IO
and ⎕ML
insensitive, the examples in this documentation assume an environment of (⎕IO ⎕ML)←1
.
Loading HttpCommand
HttpCommand
is included with your Dyalog APL installation. To bring it into your workspace:
Dyalog APL Version 19.0 and later
]import {ns} HttpCommand
or, under program control, do:
⎕SE.Link.Import {ns} 'HttpCommand'
where {ns}
is an optional namespace name or reference.
Dyalog APL versions before 19.0
]load HttpCommand {-target=ns}
or, under program control, do:
⎕SE.SALT.Load 'HttpCommand {-target=ns}'
{-target=ns}
optionally specifies the namespace in which to load HttpCommand
. ns
is the namespace name.
Upgrading to the Latest HttpCommand
This documentation describes the latest version of HttpCommand
, which may be more recent than the version of HttpCommand
that came pre-installed with your Dyalog APL. Use HttpCommand.Upgrade
upgrade your in-workspace copy of HttpCommand
. Note that this only upgrades your in-workspace copy of HttpCommand
and does not overwrite the version included in your Dyalog installation.
If HttpCommand.Version
reports a version earlier than 4.0.14, HttpCommand.Upgrade
will need to be run twice to upgrade to the latest version.
HttpCommand.Upgrade
does not work with Classic interpreters. See Upgrade
for more information.
For example, HttpCommand
version 3.4 may be found in Dyalog version 18.0.
]load HttpCommand
#.HttpCommand
HttpCommand.Version
HttpCommand 3.4 2021-05-28
HttpCommand.Upgrade
0
HttpCommand.Version ⍝ verify that we upgraded to v4.0.14
HttpCommand 4.0.14 2022-09-04
HttpCommand.Upgrade ⍝ now upgrade to v5
0 Upgraded to HttpCommand 5.6.0 2024-03-17 from HttpCommand 4.0.14 2022-09-04
Note
When deploying HttpCommand
as a part of your application, you should save a copy with your application to ensure you know precisely what version of HttpCommand
is being used. You don't want to dynamically load or upgrade HttpCommand
in your application.
HttpCommand
is Available as a Tatin Package
Tatin is a package manager for APL-based packages. HttpCommand
is available as a Tatin package. If you have the Tatin client installed, you can load HttpCommand
using:
]TATIN.LoadPackages HttpCommand
The Tatin client will be included in your Dyalog installation beginning with Dyalog version 19.0. For earlier versions of Dyalog, refer to the Tatin website for instructions on installing the Tatin client.
Load Once, Use Often
It is strongly recommended that you save your own copy of HttpCommand
in your application rather than dynamically loading or upgrading it at runtime. In particular, it is bad practice to repeated load HttpCommand
as this may cause Conga to reinitialize each time HttpCommand
is loaded and may interfere with other components of your application that also use Conga. If HttpCommand
is being used within your application (as opposed to ad hoc usage in your APL session) it is recommended that all Conga-using components refer to the same Conga namespace. See HttpCommand and Conga
Typical Usage Patterns
HttpCommand
is implemented as a Dyalog class and its typical usage pattern is:
- Create an instance of the
HttpCommand
class using the functionHttpCommand.New
instance ← HttpCommand.New ''
- Set fields (settings) appropriate to describe the request
- Send the request
- Examine the response result
For example:
cmd←HttpCommand.New '' ⍝ create an instance
cmd.Command←'get' ⍝ specify the HTTP method
cmd.URL←'www.dyalog.com' ⍝ specify the URL
⊢response←cmd.Run ⍝ send the request
[rc: 0 | msg: "" | HTTP Status: 200 "OK" | ⍴Data: 21060]
50↑response.Data ⍝ examine the response payload
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans
The result of HttpCommand.Run
is a namespace containing information about the response from server. The display format for the namespace gives some useful information about the success of the request. The server's response data, also known as the content or payload, is found in the Data
element of the namespace.
HttpCommand
has several "shortcut" shared methods to perform common operations. For instance, the above example can be accomplished by using HttpCommand.Get
.
50↑(HttpCommand.Get 'www.dyalog.com').Data
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans
Philosophy
HttpCommand
has been designed to be easy to integrate into your application by having a small footprint (it's a single class) and making almost no assumptions about the environment in which you'll use it. HttpComand
attempts to use sensible default values for request settings while still giving you full control should you need it. HttpCommand
's feature set has expanded over time as new use cases and feature requests have arisen. We expect this trend to continue and encourage you to submit feature requests or report any bugs via GitHub.
This documentation should provide sufficient information to use HttpCommand
to make most HTTP requests. In some cases, some further knowledge of HTTP may be necessary. This documentation does not attempt to be an exhaustive HTTP reference.
Dyalog Classes
HttpCommand
is implemented as a Dyalog class. While it's not necessary to have an in-depth knowledge of Dyalog classes, it is useful to understand a couple basic concepts. A class can have "shared" methods and settings (known as fields) and "instance" methods and settings. For instance, the "shortcut" methods like Get
, GetJSON
, Do
and New
are shared methods whereas the instance methods like Show
and Run
are only available in an HttpCommand
instance. Similarly, Debug
and CongaPath
are shared settings whereas URL
and Command
are instance settings. We will attempt to make the distinction between shared and instance references throughout this documentation.
Use of Conga
HttpCommand
uses Conga, Dyalog's TCP/IP utility library, for communication. Conga is installed as a part of Dyalog APL. By default HttpCommand
will attempt to locate and use the installed Conga. Conga consists of two parts:
- Two shared library files that are specific to the operating system and implement the low-level communications and security interfaces.
- An APL object that implements a cross-platform interface to the shared libraries. The object will be either the
DRC
namespace or an instance of theConga.LIB
class. For the purposes of this document we will refer to this object as the Conga API.
See HttpCommand and Conga for more information on how HttpCommand
interacts with Conga. See Integrating HttpCommand for more information on how to package Conga and HttpCommand
in a distributed application.
If your application has other components that also use Conga, we recommend that you use the "multiple roots" feature of the Conga
namespace:
- Copy the
Conga
namespace from theconga
workspace.'Conga' #.⎕CY 'conga'
- Set
HttpCommand.CongaRef
setting to refer to theConga
namespace.HttpCommand.CongaRef←#.Conga
- Similarly configure the other Conga-using components to refer to the
Conga
namespace. - Now each component can create their own Conga "root" using
Conga.Init
.HttpCommand
does this for you automatically.
Further Reading
- This documentation does not attempt to be an in-depth examination of either Conga or the HTTP protocol. For more information on Conga, see the Conga User Guide
- There are many resources available to learn about HTTP; a good one may be found on the Mozilla Developer Network
- For more information on Dyalog classes, please refer to the Object Oriented Programming chapter in the Dyalog Programming Reference Guide.
Usage ↵
Shortcut Methods
HttpCommand
has several shared "shortcut" methods to perform common operations. An overview of these methods is presented here. See the Reference section of the documentation for detailed information on all features of HttpCommand.
HttpCommand
's Get
, GetJSON
, Do
, and New
methods each accept a right argument which is one of:
- a vector of positional arguments
- a namespace containing named arguments.
Positional arguments must be supplied in the position and order shown. If you do not need to use an intermediate argument, you should supply ''
. For instance, a request that needs a Headers
setting, but does not use a Params
setting would be:
HttpCommand.Get 'www.someurl.com' '' ('accept' 'image/png')
To use a namespace argument, create a namespace and assign the appropriate parameters for the request. For example:
ns←⎕NS ''
ns.(Command URL)←'post' 'www.someurl.com'
ns.Params←⎕JSON ⍳10
ns.Headers←'Content-Type' 'application/json'
r←HttpCommand.Do ns
Get
Sends an HTTP request using the HTTP GET method.
r← [ro] HttpCommand.Get URL [Params [Headers]]
r← [ro] HttpCommand.Get namespace
GetJSON
Sends an HTTP request to a JSON-based web service using the HTTP method you specify. Unless otherwise specified, request parameters and response payload are automatically converted between APL and JSON.
r← [ro] HttpCommand.GetJSON Command URL [Params [Headers]]
r← [ro] HttpCommand.GetJSON namespace
Do
Sends an HTTP request using the HTTP method you specify.
r← [ro] HttpCommand.Do Command URL [Params [Headers]]
r← [ro] HttpCommand.Do namespace
New
Creates a new instance of HttpCommand
.
h← [ro] HttpCommand.New Command URL [Params [Headers]]
h← [ro] HttpCommand.New namespace
Once the instance is created, additional settings can be assigned directly if necessary. Then use the Run
method to send the request.
r← h.Run
Arguments
Name | Description | Default Value |
---|---|---|
Command |
The HTTP method to use | 'GET' |
URL |
The URL to which the request will be sent. If URL begins with 'https://' HttpCommand will attempt create a secure connection to the host using either an anonymou)s certificate it creates or Cert if it is supplied |
'' |
Params |
Any parameters that are to be sent with the request. | '' |
Headers |
Any HTTP headers (name/value pairs) to send with the request | '' |
ro |
"Request Only" - when set to 1, HttpCommand will compose and return the HTTP request that it would send to the host, but not actually send it. This is useful for debugging to ensure your request is properly formed. |
0 |
See the Request-related Settings section for more detail on the arguments.
Each of the above methods also accept 3 additional positional arguments, [Cert [SSLFlags [Priority]]]
. These arguments are used to specify settings for secure connections but are seldom used in practice because HttpCommand
automatically supplies an anonymous certificate when using a secure connection. See Secure Connections and Conga-related Settings for more information.
Shortcut or Instance?
There are two ways to use HttpCommand
.
- Use one of its shortcut methods (
Get
,Do
,GetJSON
) to execute a single HTTP request and examine the response from the host. When you use a shortcut method,HttpCommand
will create a new, local, instance of itself and then use the instance'sRun
method to send the request and receive the response, then exit thereby destroying the local instance. This is generally fine when your requests are independent of one another and do not require any state to be maintained across requests. - Create an instance of
HttpCommand
using⎕NEW
or theNew
shared method, set whatever parameters are necessary, execute theRun
method, and examine the response from the host. Creating an instance ofHttpCommand
and using theRun
method to send the request and receive the response will persist the instance such that state information like connection information and HTTP cookies will be retained across requests.
HttpCommand
's Result
The result of the Run
method is a namespace containing information related to the result of the request. The display format (⎕DF
) of the result presents some useful information.
⊢r ← HttpCommand.Get 'https://www.dyalog.com'
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 20571]
r
is the namespace resultr.rc
isHttpCommand
's numeric return code. 0 meansHttpCommand
was able to create and send the request to the host, send it, and receive and process the response.Ifrc
is less than 0, it means there was some problem either composing/sending the request or processing the response.Ifrc
is greater than 0, it is the Conga return code and generally means that Conga encountered something unexpected. More information aboutrc
can be found here.r.msg
is a (hopefully meaningful) message describing whatever the issue was ifr.rc
is non-zero.r.HttpStatus
is the numeric HTTP status code returned by the host. A status code in the range 200-299 indicates a successful HTTP response with 200 being the most common code.r.HttpMessage
is the HTTP status message returned by the host.r.Data
is the payload of the response, if any, returned by the host. The result namespace contains other elements which are described in detail on the Request Results, Operational Results, and Response Results pages.
Typical Use in Code
Typical use of HttpCommand
might follow this pattern.
resp ← HttpCommand.Get 'some-url'
:If resp.IsOK ⍝ use the IsOK function from the result namespace
⍝ code to process the response
:Else
⍝ code to handle bad request
:EndIf
If you expect to make several HttpCommand
calls, you may want to create an instance and then update the necessary settings and execute the Run
method for each call. This can be useful when the requests are made to the same host as the connection to the host will be kept open, unless the host itself closes it.
hc←HttpCommand.New 'get' ⍝ here we expect all requests to be HTTP GET
urls←'url1' 'url2' 'url3'
:For url :In urls ⍝ loop over the URLs
hc.URL←url ⍝ set this URL
resp←hc.Run
:If resp.IsOK
⍝ process the response
:Else
⍝ process the exception/error
:EndIf
:EndFor
Timeout
and Long-running Requests
The default Timeout
setting (10 seconds) is adequate for most requests. There are a couple of patterns of long running requests. Timeout
can be set to a positive or negative number.
- Setting
Timeout
to a positive number means thatHttpCommand
will time out afterTimeout
seconds with a return code (rc
) of 100. Any partial payload received will returned inData
element of the result. - Setting
Timeout
to a negative number means thatHttpCommand
will not time out as long as data is being received. This is useful in the case where a large payload may be received but you are uncertain of how long it will take to receive. If no data is received within a period of|Timeout
seconds,HttpCommand
will time out with a return code (rc
) of 100. Any partial payload received will be returned in theData
element of the result.
Using a negativeTimeout
value is useful in the case where a large payload is being received in chunks but has no benefit if the entire payload is sent in one chunk or if the host takes more than|Timeout
seconds to begin sending its response. In that case, you'll need to set|Timeout
to a larger value.
Compressing Response Payload
HttpCommand
can accept and process response payloads that are compressed using either the gzip or deflate compression schemes. To accomplish this, you need to set the accept-encoding
header to 'gzip, deflate'
.
Interacting with Web Services
A web service will generally have a published API which describes how to interact with the service. This API will be your guide for how to build requests using HttpCommand
to access the web service. In many cases, the API will also describe the format of the data it returns in the content-type
header.
A web service may require authentication in order to gain access to certain resources or perform certain operations. GitHub is a good example of this - it does not require authentication to perform read-only queries on public resources, but authentication is necessary to perform write operations or to access private repositories.
Let's look at GitHub's REST API as an example. The GitHub API returns its data in JSON format.
Note: If you run these same examples, you may get slightly different results because of updates to Dyalog's content on GitHub.
c ← HttpCommand.New 'get' 'https://api.github.com/orgs/Dyalog'
⊢r ← c.Run ⍝ send the request
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 1101]
r.Headers c.Lookup 'content-type' ⍝ check the content-type
application/json; charset=utf-8
d←⎕JSON r.Data ⍝ convert the JSON
d.(name public_repos)
Dyalog 48
html ← 'HTML' ('<img src="',d.avatar_url,'"/>')
coord ← 'coord' 'pixel' ⋄ size ← 'size' (250 250)
'h' ⎕WC 'HTMLRenderer' html coord size
Authentication/Authorization
The example above uses no authentication and therefore returns only publicly-available information. Many web services require some form of authentication to provide authorization to access private resources or functionality. Two common authentication schemes are "token-based" and "HTTP Basic".
HTTP Basic Authentication
Some web services allow you to use HTTP Basic authentication using userid and password credentials. Any request that includes authentication data should be sent using HTTPS if possible. HttpCommand
allows you to specify these credentials in a few ways:
- in the
URL
by includinguserid:password@
before the domain name - by setting
AuthType
to'Basic'
andAuth
toHttpCommand.Base64Encode 'userid:password'
- by including an "Authorization" header in the format
'Basic ',HttpCommand.Base64Encode 'userid:password'
The following examples use the "basic-auth" endpoint of the website http://httpbin.org. httpbin.org provides many useful endpoints for testing HTTP requests. In this case, the userid and password are concatenated to the URL so the endpoint can validate the credentials.
First, let's try using credentials in the URL...
u ← 'userid'
p ← 'password'
endpoint ← 'httpbin.org/basic-auth/userid/password'
⊢url ← 'https://',u,':',p,'@',endpoint
https://userid:password@httpbin.org/basic-auth/userid/password
⊢r ← HttpCommand.Get url
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 49]
r.Data
{
"authenticated": true,
"user": "user"
}
If we alter the URL so that the credentials don't match, we'll get a 401 "UNAUTHORIZED"
HTTP status.
HttpCommand.Get url,'1'
[rc: 0 | msg: | HTTP Status: 401 "UNAUTHORIZED" | ⍴Data: 0]
Now, let's try setting the "Authorization" header...
⊢credentials ← HttpCommand.Base64Encode u,':',p
dXNlcmlkOnBhc3N3b3Jk
hdrs ← 'Authorization' ('Basic ',credentials)
url ← 'https://',endpoint
HttpCommand.Get url '' hdrs
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 49]
Finally, let's use the AuthType
and Auth
settings...
h ← HttpCommand.New 'get' url ⍝ create an instance
h.Auth ← credentials
h.AuthType ← 'Basic'
h.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 49]
Token-based Authentication
One common authentication method uses tokens which are issued by the web service provider. Tokens should be protected just as you would protect your password. A token may have an expiration date after which you'll need to get a new token. Any request that includes authentication data should be sent using HTTPS if possible.
For this next example we'll use a GitHub Personal Access Token which happens to provide more access to Dyalog's information on GitHub.
The API documentation for the web service you are using should provide information about the use of tokens. In GitHub's case, the token is passed in the HTTP request's "Authorization" header. HttpCommand
allows you to specify the token either by creating an "Authorization" header or by setting the Auth
configuration setting. If you set the Auth
setting, HttpCommand
will add the "Authorization" header automatically.
Let's assume that the token we're using in this example is in a variable named token
. (Obviously, we are not going to publish the actual token here.) Also note if you plan on making several requests to the same web service, it's easier to create an instance of HttpCommand
, set the Auth
configuration setting, then set any other configuration settings and run the Run
method for each request.
First, let's compare the difference between an authorized and a non-authorized request...
⊢HttpCommand.Get 'https://api.github.com/orgs/Dyalog'
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 1101]
hdr←'authorization' ('Token ',token)
⊢HttpCommand.Get 'https://api.github.com/orgs/Dyalog' '' hdr
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 1804]
Note more data is returned for the authorized request. This additional data will include things like organizational and administrative information.
Interacting with JSON-based Web Services
Many web services including those based on Jarvis, Dyalog's web service framework, use JSON to format their request and response payloads. Normally, to interact with a JSON-based web service, you would set the "content-type" header of the request to "application/json" if the request has a payload; then you would process the response's JSON payload, possibly with ⎕JSON
.
HttpCommand
's GetJSON
method is designed to make it easy to to interact with such services. GetJSON
will convert an APL array request payload to JSON format and conversely convert a JSON response payload to APL. We saw in the Interacting with Web Services example above that GitHub returns its result as JSON.
Posting Data to a Web Service
So far we've only read data from GitHub using the HTTP GET method. The GitHub API also allows authenticated users to create and update information. In this example we will create a new repository using the HTTP POST method and our GitHub Personal Access Token. For security reasons, we will use the same token
variable from the previous example. At the time of this writing, we are using the GitHub API documentation for creating a repository for an authenticated user as a guide.
For this example, we'll use a namespace, args
, to specify all the settings for our request...
args←⎕NS ''
args.Command ← 'post'
args.URL ← 'https://api.github.com/user/repos'
args.Params ← ⎕NS ''
args.Params.name ← 'TestRepository'
args.Params.description ← 'HttpCommand Example'
args.Params.auto_init ← ⊂'true' ⍝ APL's equivalent to JSON true
⊢r ← HttpCommand.GetJSON args
[rc: 0 | msg: | HTTP Status: 401 "Unauthorized" | ⍴Data: ⍬]
Oops! We didn't use our token for authentication and so the request was rejected as unauthorized. We also specify the authentication scheme as 'token'
, which is what the GitHub API uses.
args.(AuthType Auth) ← 'Token' token
⊢r ← HttpCommand.GetJSON args
[rc: 0 | msg: | HTTP Status: 201 "Created" | ⍴Data: ⍬]
Notice that the shape of the response's payload (Data) is ⍬
. This is because we used the GetJSON
method and HttpCommand
automatically converted the response's JSON payload into a Dyalog JSON object which contains all the information about the newly created repository...
]Box on
r.Data.(name created_at)
┌──────────────┬────────────────────┐
│TestRepository│2022-08-01T21:23:08Z│
└──────────────┴────────────────────┘
Downloading a File
If you want to download a file you can simply use HttpCommand.Get
with the URL of the file and then write the response's payload to a local file. Or, you can set the OutFile
setting to the local file name and have HttpCommand
write the file for you. This is especially advantageous for large files if the server uses "chunked" transfer encoding to send the payload in chunks. In that case, rather than buffering the entire payload in the workspace and then writing to the local file, HttpCommand
will write each chunk out as it is received.
args←⎕NS ''
args.OutFile ← '/tmp/test.pdf'
args.Command ← 'get'
args.URL ← 'https://www.dyalog.com/uploads/files/student_competition/2021_problems_phase1.pdf'
⊢r ← HttpCommand.Do args
[rc: 0 | msg: | HTTP Status: 200 "OK" | 179723 bytes written to c:/tmp/test.pdf]
Twitter Example
The GitHub examples above used the default AuthType
of 'Token'
. Twitter's v2 REST API uses OAuth 2.0's 'bearer'
authentication scheme. In this example our super secret bearer token is stored in a variable named bearerToken
.
apiURL ← 'https://api.twitter.com/2/' ⍝ set the base URL for each request
c ← HttpCommand.New ''
c.(AuthType Auth) ← 'bearer' bearerToken
First we need to get the id for the Twitter account we want to look at. Twitter returns its response payload in JSON, so we can have HttpCommand
automatically convert the JSON into an APL object by setting TranslateData
to 1. If there are no errors in the request, Twitter will put the response's data in an object called 'data'
.
c.TranslateData ← 1 ⍝ have HttpCommand translate known data types
c.URL ← apiURL,'users/by?usernames=dyalogapl'
⊢id ← ⊃(c.Run).Data.data.id ⍝ get the id for user "dyalogapl"
36050079
c.URL ← apiURL,'users/',id,'/tweets?tweet.fields=created_at'
⊢ r ← c.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: ⍬]
≢ tweets ← r.Data.data ⍝ how many tweets were returned?
10
↑(4↑tweets).((10↑created_at) (50↑text))
2022-07-26 Remember to submit your solutions to the annual AP
2022-07-25 Dyalog ’22 – make sure you register for Dyalog ’22
2022-07-20 The APL practice problems site https://t.co/1SEoa5
2022-07-15 There are only two weeks until the 10% Early Bird
In a perfect world, all HTTP requests would be well-formed, target hosts would be available, and APIs well-documented. Unfortunately, we don't live in a perfect world and so, in this section, we attempt to provide you with some guidance for troubleshooting requests that aren't working as you expect.
The result namespace returned by HttpCommand.Run
contains information that may help in troubleshooting. The display format of the result contains some useful information:
* rc
is the HttpCommand
's return code
* msg
is a diagnostic message if rc≠0
* HTTP Status
indicates the host's HTTP return code and status message
* ⍴Data
indicates the shape of the payload, if any, received in the response. This is the shape of the payload data after any automatic conversion done by HttpCommand
.
First check rc
and msg
If rc
is not 0, msg
should have relevant information about what went wrong. rc
values less than 0 indicate a problem that wasn't Conga-related. rc
values greater than 0 are the Conga return code if there was a Conga-related error.
HttpCommand.Get ''
[rc: ¯1 | msg: No URL specified | HTTP Status: "" | ⍴Data: 0]
HttpCommand.Get 'non_existent_url'
[rc: 1106 | msg: Conga client creation failed ERR_INVALID_HOST Host
identification not resolved | HTTP Status: "" | ⍴Data: 0]
Check HttpMessage
and Data
If rc=0
, but HttpStatus
is not what you expect, examine both HttpMessage
and Data
. In the example below, GitHub returns a URL pointing to their API documentation for getting information about an organization.
⊢r ← HttpCommand.Get 'https://api.github.com/orgs/bloofo'
[rc: 0 | msg: | HTTP Status: 404 "Not Found" | ⍴Data: 109]
r.HttpMessage
Not Found
r.Data
{"message":"Not Found","documentation_url":"https://docs.github.com/rest/reference/orgs#get-an-organization"}
Examine the request that HttpCommand
will send
It can be useful to examine the actual request that HttpCommand
will send to the host. Many web services will publish sample requests that you can use for comparison. Check that the headers, particularly content-type
, are correct.
The instance setting RequestOnly
controls whether HttpCommand
will send the request to the host or simply return the request that would be sent to the host. You can set RequestOnly
in several ways:
* Pass 1 as the optional left argument to the shortcut methods Get
, GetJSON
, or Do
.
method ← 'post'
url ← 'www.someurl.net'
payload ← ⍳10
headers ← 'a-header' 'some value'
1 HttpCommand.GetJSON method url payload headers
POST / HTTP/1.1
a-header: some value
Host: www.someurl.net
User-Agent: Dyalog/HttpCommand
Accept: */*
Content-Type: application/json;charset=utf-8
Content-Length: 22
[1,2,3,4,5,6,7,8,9,10]
- Pass 1 as the optional left argument to the
New
shortcut method and then run theRun
method. Be sure to setRequestOnly
back to 0 before sending the request to the host.
c ← 1 HttpCommand.New 'get' 'dyalog.com'
c.Run
GET / HTTP/1.1
Host: dyalog.com
User-Agent: Dyalog/HttpCommand
Accept: */*
c.RequestOnly←0
c.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 20684]
- Use the
Show
instance method.
c ← HttpCommand.New ''
c.URL ← 'someurl.com/stuff'
c.Command ← 'get'
c.Params ← 'name' 'Drake Mallard'
'header-name' c.AddHeader 'header value'
c.Show
GET /stuff?name=Drake%20Mallard HTTP/1.1
header-name: header value
Host: someurl.com
User-Agent: Dyalog/HttpCommand
Accept: */*
Debug Mode
Setting HttpCommand.Debug←1
will disable HttpCommand
's error checking and cause HttpCommand
to suspend if and where an error occurs.
Setting HttpCommand.Debug←2
will cause HttpCommand
to suspend just before it attempts to create the client connection to the host. This will give you the opportunity to examine the request's state and step through the code.
Note: HttpCommand.Debug
is a shared setting and will affect all instances of HttpCommand
.
Ended: Usage
Reference ↵
Settings ↵
Request-related settings are settings you use to specify attributes of the HTTP request that HttpCommand
will process.
Instance Settings
Command
Description | The case-insensitive HTTP command (method) for the request. Command is not limited to standard HTTP methods like GET, POST, PUT, HEAD, OPTIONS, and DELETE, but can be any string provided that the host has implemented support for it. |
Default | 'GET' |
Example(s) | h.Command←'POST' |
URL
Description | The URL for the request. The general format for URL is:
[scheme://][userinfo@]host[:port][/path][?query] At a minimum the URL must specify the host. |
Default | '' |
Example(s) | h.URL←'dyalog.com' |
Details |
A URL has the general format:[scheme://][userinfo@]host[:port][/path][?query]
So, a URL can be as simple as just a host name like 'dyalog.com' or as complex as 'https://username:password@ducky.com:1234/?id=myid&time=1200'
The only mandatory segment is the host ; HttpCommand will infer or use default information when it builds the HTTP request to be sent.
|
Params
Description | The parameters or payload, if any, for the request. Params can be a set of name/value pairs or a character vector that is properly formatted for the ContentType or Command of the
request. See details for more information. |
Default | '' |
Example(s) | The following examples are
equivalent:h.Params←(('name' 'dyalog') ('age' 39)) ns←⎕NS '' ⋄ ns.(name age)←'dyalog' 39 ⋄ h.Params←ns
|
Details | If Params is not empty, its interpretation is dependent on Command and the content type of the
request. The content type is determined by the ContentType setting or
the presence of a content-type header.If Command is 'GET' or 'HEAD' , the request will generally not have a payload in the message body (and hence no specified content type) and Params will be URLEncoded if necessary and appended to the query string of URL .If Command is neither 'GET' nor 'HEAD' and no content type has been
specified, HttpCommand will attempt to infer the content type as follows:
Params is processed based on the content type and inserted as the payload of the request. If the content type is:
|
Headers
Description | The HTTP headers for the request. Specified as one of:
|
Default | By default, HttpCommand will create the following headers if you have not supplied them yourself:Host: the host specified in URL User-Agent: 'Dyalog/HttpCommand 5.0.1' or whatever the version happens to beAccept: '*/*' If the request content type has been specified, HttpCommand will insert an appropriate content-type header.
If the request has content in the request payload, Conga will automatically supply a content-length header.
|
Example(s) | The following examples are equivalent:h.Headers←'accept' 'text/html' 'content-type' 'test/plain'
h.Headers←('accept' 'text/html')('content-type' 'test/plain')
h.Headers←'accept:text/html',(⎕UCS 13 10),'content-type:text/plain'
h.Headers←('accept:text/html')('content-type:text/plain') |
ContentType
Description | This setting is a convenient shortcut for setting the content-type HTTP header of the request. If you happen set both ContentType and a content-type header, ContentType takes precedence.
|
Default | '' |
Example(s) | h.ContentType←'application/json; charset=UTF-8' |
Details | See Content Types for additional information. |
Auth
Description | This setting is the authentication/authorization string appropriate for the authentication scheme specified in AuthType . Used along with AuthType , Auth is a shortcut for setting the authorization HTTP header for requests that require authentication. If Auth is non-empty, HttpCommand will create an 'authorization' header and and set its value to AuthType,' ',Auth . If you happen set both Auth and an authorization header, Auth takes precedence.You may specify an environment variable whose value is to be used for Auth by enclosing the environment variable name in '%' . This helps avoid the need to hardcode credentials in your code.
|
Default | '' |
Example(s) | h.Auth←'my-secret-token'
h.Auth←h.Base64Encode 'userid:password' ⍝ HTTP Basic Authentication h.Auth←'userid' 'password' ⍝ HTTP Basic Authentication |
Details | For HTTP Basic Authentication, Auth can be set to any of
URL as in 'https://username:password@someurl.com' , HttpCommand will automatically generate a proper 'authorization' header.
|
AuthType
Description | This setting is used in conjunction with Auth and is a character vector indicating the authentication scheme. Three common authentication schemes are:
|
Default | '' |
Example(s) | h.AuthType←'Bearer' |
Details |
If AuthType is not set and Auth is set to either a character vector in the form 'userid:password' or a 2-element vector of character vectors as in ('userid' 'password') HttpCommand will infer the AuthType to be 'Basic' .Note: While authentication schemes are supposed to be case insensitive, some servers are not so forgiving and require the authentication scheme to be appropriately cased. |
UseZip
Description | UseZip controls whether the request payload is zipped. Valid values are:
|
Default | 0 |
Details | The ZipLevel setting controls the level of compression when using gzip or deflate encoding. |
ZipLevel
Description | ZipLevel controls the level of compression when using gzip or deflate encoding. Valid values are 0 through 9 . Higher values use a higher degree of compression but also consume more CPU. |
Default | 1 |
Details | The UseZip setting controls which compression algorithm, if any, is used. |
BaseURL
Description | BaseURL can be used when making multiple requests to similar-named endpoints. Set BaseURL to the common root of the URLs that you will be using and then set URL to the remaining portion of the specific URL. BaseURL will be prepended to URL to form the complete URL for the request. Subsequent calls to other endpoints can be made by setting URL . |
Default | '' |
Example(s) |
|
Details | If URL begins with 'http://' or 'https://' , BaseURL will not be prepended to URL . |
Cookies
Description | Cookies is a vector of namespaces, each containing a representation of an HTTP cookie. It contains cookies sent by the host that may be used in a series of requests to the same host. This setting should be considered read-only. |
Default | '' |
Example(s) | (c ← HttpCommand.New 'get' 'github.com').Run [rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 299959]
≢ c.Cookies 3 ↑c.Cookies.(Name Host ('DD-MMM-YYYY'(1200⌶)Creation)) _gh_sess github.com 05-AUG-2022 _octo github.com 05-AUG-2022 logged_in github.com 05-AUG-2022 |
ChunkSize
Description | A non-zero ChunkSize will make HttpCommand use "chunked" transfer-encoding and send the payload of the request in chunk of ChunkSize bytes. |
Default | 0 meaning do not use "chunked" transfer-encoding |
Details | Using a non-zero ChunkSize will cause HttpCommand to format the payload of the request according to the specification for "chunked" transfer-encoding. This involves breaking the payload into ChunkSize -sized chunks each preceded by the hexadecimal length of the chunk. Note: In the current implementation, the entire, reformatted, payload is sent in a single request to the host. |
Shared Settings
HeaderSubstitution
Description | In the following text, the phrase "environment variable" is taken to mean either an environment variable or a Dyalog configuration setting as both of these are retrieved using the same technique (
You may also use the delimiters in the |
Default | '' |
Example(s) |
For these examples, assume we have an environment variable named "MyVariable" which has a value of '0123456789' .
Now let's specify a delimiter...
The delimiters do not have to be single characters...
Alternatively, you can use the
|
Details | Many web services require an API key. It is generally considered bad practice to hard-code such API keys in your application code. Storing the keys as environment variables allows them to be retrieved more securely. If no environment variable matches the name between the delimeters, no substitution is performed. |
Name/Value Pairs
Params
, for an appropriate content type, and Headers
can be specified as name/value pairs. HttpCommand
gives you some flexibility in how you specify name/value pairs. You may use:
- A vector of depth
2
or¯2
with an even number of elements.
('name' 'dyalog' 'age' 39)
- A vector of 2-element vectors,
HttpCommand
will treat each sub-vector as a name/value pair.
(('name' 'dyalog') ('age' 39))
- A 2-column matrix where each row represents a name/value pair.
2 2⍴'name' 'dyalog' 'age' 39
- A reference to a namespace,
HttpCommand
will treat the variables and their values in the namespace as name/value pairs.
ns←⎕NS '' ⋄ ns.(name age)←'dyalog' 39
Note that the names will be alphabetical in the formatted output.
Operational settings affect how HttpCommand
behaves.
Instance settings
KeepAlive
Description | A Boolean which indicates whether HttpCommand close the client connection after receiving the response from the host.
|
Default | 1 |
Example(s) | h.KeepAlive←0 ⍝ close the connection |
Details | KeepAlive is only applicable when you persist an instance of HttpCommand and has no effect when you use the shortcut methods Get , GetJSON , or Do as these methods destroy the HttpCommand instance they create when they finish execution. HTTP version 1.1 specifies that connections should be kept alive to improve throughput. Nevertheless, a host may close the connection after sending the response or after a period of inactivity from the client (HttpCommand ). If the connection is closed, HttpCommand will open a new connection on a subsequent request. |
MaxPayloadSize
Description | The maximum response payload size that HttpCommand will accept.
|
Default | ¯1 |
Example(s) | h.MaxPayloadSize←100000 ⍝ set a 100,000 byte limit |
Details | If MaxPayloadSize is set to a value ≥0 and the response contains a payload, HttpCommand checks the payload size as follows:
MaxPayloadSize is exceeded, the client connection will be closed. |
MaxRedirections
Description | The maximum number of redirections that HttpCommand will follow.A setting of ¯1 means there is no limit to the number of redirections followed; exposing the possibility of an infinite redirection loop and eventually a WS FULL error. A setting of 0 means no redirections will be followed. |
Default | 10 |
Example(s) | h.MaxRedirections←0 ⍝ do not follow any redirections
|
Details | If the response HTTP status indicates a redirection (3XX) to another URL, HttpCommand will retain information about the current request in the Redirections element of the result namespace and issue a new request to the new URL. HttpCommand will do this up to MaxRedirections times. |
OutFile
Description | OutFile has up to 2 elements:
|
Default | '' 0 |
Example(s) | c ← HttpCommand.New '' c.URL←'https://www.dyalog.com/uploads/files/student_competition/2022_problems_phase2.pdf' c.OutFile←'/tmp/' c.Run [rc: 0 | msg: | HTTP Status: 200 "OK" | 399766 bytes written to c:/tmp/2022_problems_phase2.pdf] c.OutFile←'/tmp/problems.pdf' 1 c.Run [rc: 0 | msg: | HTTP Status: 200 "OK" | 399766 bytes written to c:/tmp/problems.pdf] |
Details | Output to file is subject to MaxPayloadSize . |
RequestOnly
Description | If set to 1, HttpCommand will return the character vector HTTP request that would be sent, instead of actually sending the request. |
Default | 0 |
Example(s) | h.RequestOnly←1 |
Details | This setting is useful for debugging a request that isn't behaving as you expect. Setting optional left argument of shared methods Get , GetJSON , Do , or New to 1 will have the same effect as setting RequestOnly as will the instance method Show . |
Secret
Description | If set to 1, HttpCommand will suppress the display of credentials in the Authorization header, instead replacing them with >>> Secret setting is 1 <<< . This applies when using the Show or Config methods or setting RequestOnly to 1. Secret will not affect the request that is actually sent to the host. |
Default | 1 |
Example(s) |
|
Details | This setting is useful when doing an HttpCommand demonstration as it will avoid inadvertently displaying credentials in the APL session. |
SuppressHeaders
Description | SuppressHeaders is a Boolean setting indicating whether HttpCommand should suppress the generation of its default HTTP headers for the request.
|
Default | 0 which means HttpCommand will generate its default headers |
Example(s) | h.SuppressHeaders←1 |
Details | HttpCommand will only generate headers that you have not specified yourself. HttpCommand generates the following default headers:
SuppressHeaders←1 will suppress ALL HttpCommand -generated headers which means you will need to specify any necessary request headers yourself.
Individual headers can be suppressed by using the SetHeader instance method and assigning the header a value of '' .Note: Conga will always insert a Content-Length header for any request that has a payload.
|
Timeout
Description | The number of seconds that HttpCommand will count down to wait for a response from the host. If Timeout is positive, HttpCommand will exit with a return code of 100 (Timeout) if it has not received the complete response from the host before the countdown reaches 0. If Timeout is negative, HttpCommand will check if Conga has received any data and if so, will reset the countdown to |Timeout . |
Default | 10 |
Example(s) | h.Timeout←30 |
Details | This is the setting to adjust (and not WaitTime ) if your request is timing out. See Timeout and WaitTime for more information on the relationship between the Timeout and WaitTime settings.
|
TranslateData
Description | Set this to 1 to have HttpCommand attempt to convert the response payload for the following content types.
|
Default | 0 |
Example(s) |
c←HttpCommand.New 'get' 'https://api.github.com/users/dyalog'
|
Shared Settings
Shared settings are set in the HttpCommand
class and are used by all instances of HttpCommand
.
Debug
Description | Set Debug to 1 to turn off HttpCommand 's error trapping. In this case if an error occurs, execution of HttpCommand will be suspended. Set Debug to 2 to have HttpCommand stop just before sending the request to the host so that you can examine the request and HttpCommand 's current state. Both of these settings can be useful for debugging. |
Default | 0 |
Example(s) |
c←HttpCommand.New 'get' 'https://api.github.com/users/dyalog' c.OutFile←0 c.Debug←1 c.Run DOMAIN ERROR: Invalid file or directory name HttpCmd[130] outFile←∊1 ⎕NPARTS outFile ∧ c.Debug←0 c.Run [rc: ¯1 | msg: DOMAIN ERROR while trying to initialize output file '0' | HTTP Status: "" | ⍴Data: 0]
|
In general, you will not need to set any of the Conga-related settings since the HttpCommand
's defaults will suffice for almost all requests. For more information on Conga, please refer to the Conga User Guide.
Instance Settings
BufferSize
Description | The maximum number of bytes that HttpCommand will accept for the HTTP status and headers received from the host. |
Default | 200000 |
Example(s) | h.BufferSize←50000 ⍝ set a lower threshold |
Details | By default, when using Conga's HTTP mode, as HttpCommand does, BufferSize applies only to the data received by the HTTPHeader event. The intent is to protect against a maliciously large response from the host. If the data received by the HTTPHeader event exceeds BufferSize , HttpCommand will exit with a return code of 1135. |
WaitTime
Description | The number of milliseconds that Conga will wait (listen) for a response before timing out. |
Default | 5000 |
Example(s) | h.WaitTime←10000 ⍝ wait 10 seconds |
Details | This setting applies only to the time Conga will wait internally for a response. There is generally no reason to modify this setting; if your request is timing out, you should set Timeout setting appropriately. See Timeout and WaitTime for more information on the relationship between the Timeout and WaitTime settings. |
Cert
Description | The certificate specification to be used for secure communications over SSL/TLS. If set, Cert can be either:
|
Default | '' |
Example(s) | h.Init ⍝ initialize the local instance of Conga
h.Cert← 1⊃h.LDRC.X509Cert.ReadCertUrls ⍝ use the first MS certificate store cert
h.Cert← 'path-to-certfile.pem' 'path-to-keyfile.pem' |
Details | In most cases when using HTTPS for secure communications, the anonymous certificate that HttpCommand will create for you will suffice and you need not set Cert . It should only be necessary to assign Cert in those cases where you need to specify a certificate for authentication purposes.Note: Cert is also a positional argument for the shortcut methods (Get , GetJSON , Do , and New ) as well as the HttpCommand constructor. Cert appears after the Headers positional argument. For example:h← HttpCommand.Get 'someurl.com' '' '' ('certfile.pem' 'keyfile.pem') |
PublicCertFile
Description | PublicCertFile is a character vector containing the full path to a public certificate file when using HTTPS for secure communications. PublicCertFile is used in conjunction with PrivateKeyFile |
Default | '' |
Example(s) | h.PublicCertFile←'path-to-certfile.pem' |
Details | The use of Cert and PublicCertFile /PrivateKeyFile are mutually exclusive and you should only one or the other. If both Cert and PublicCertFile /PrivateKeyFile are specified, Cert takes priority. |
PrivateKeyFile
Description | PrivateKeyFile is a character vector containing the full path to a private key file when using HTTPS for secure communications. PrivateKeyFile is used in conjunction with PublicCertFile |
Default | '' |
Example(s) | h.PrivateKeyFile←'path-to-keyfile.pem' |
Details | The use of Cert and PublicCertFile /PrivateKeyFile are mutually exclusive and you should only one or the other. If both Cert and PublicCertFile /PrivateKeyFile are specified, Cert takes priority. |
SSLFlags
Description | SSLFlags is used when using HTTPS for secure communications. It is a part of the certificate checking process and determines whether to connect to a server that does not have a valid certificate. |
Default | 32 which means accept the server certificate without checking it |
Example(s) | h.SSLFlags←8 |
Details | For more information on the interpretation of SSLFlag values, see Conga User Guide Appendix C.Note: SSLFlags is also a positional argument for the shortcut methods (Get , GetJSON , Do , and New ) as well as the HttpCommand constructor. SSLFlags appears after the Cert positional argument. |
Priority
Description | The GnuTLS priority string that specifies the TLS session's handshake algorithms. |
Default | 'NORMAL:!CTYPE-OPENPGP' |
Example(s) | h.Priority←'SECURE128:-VERS-TLS1.0' |
Details | In general, you would use a different value than the default only in rare and very specific circumstances. See GnuTLS Priority Strings" for more information.
Note: Priority is also a positional argument for the shortcut methods (Get , GetJSON , Do , and New ) as well as the HttpCommand constructor. Priority appears after the SSLFlags positional argument. |
Shared Settings
Shared settings are set in the HttpCommand
class and are used by all instances of HttpCommand
.
CongaPath
Description | The path to Conga resources |
Default | '' |
Example(s) | HttpCommand.CongaPath←'/myapp/dlls/' |
Details |
This setting is intended to be used when Conga is not located in the Dyalog installation folder or the current folder, as might be the case when deploying HttpCommand as a part of a runtime application. CongaPath is used for two purposes:
|
CongaRef
Description | A reference to the Conga or DRC namespace or to an initialized instance of the Conga.LIB class. |
Default | '' |
Example(s) | HttpCommand.CongaRef← #.Utils.Conga |
Details | This setting is intended to be used when your application has other components that use Conga. To avoid having multiple copies of Conga, you can set CongaRef to point to an existing copy of the Conga API.See HttpCommand and Conga and/or Integrating HttpCommand for more information. |
LDRC
Description | Once HttpCommand has been initialized by processing a request, LDRC is a reference to the Conga API that HttpCommand is using. |
Default | N/A |
Example(s) | HttpCommand.Get 'dyalog.com' ⍝ run a request HttpCommand.LDRC.Version 3 4 1612 |
Details | LDRC should be treated as a read-only setting. It provides a means to access the Conga API which may be helpful for debugging and informational purposes. |
CongaVersion
Description | Once HttpCommand has been initialized by processing a request, CongaVersion is the version number, in major.minor format, of the Conga API that HttpCommand is using. |
Default | N/A |
Example(s) | HttpCommand.Get 'dyalog.com' ⍝ run a request HttpCommand.CongaVersion 3.4 |
Details | CongaVersion should be treated as a read-only setting. It provides information which may be helpful for debugging and informational purposes. |
Proxy-related settings are settings you use to specify attributes in order to use a proxy server for your request. See Using a Proxy Server for more information on how to use a proxy server with HttpCommand
.
Settings
ProxyURL
Description | The URL for the proxy server which will relay the request. |
Default | '' |
Example(s) | h.ProxyURL←'http://someproxyserver.com' |
Details |
The format for ProxyURL is the same as URL .
|
ProxyHeaders
Description | The HTTP headers, if any, specifically for the proxy server's CONNECT request to the host. |
Default | 0 2⍴⊂''
|
Details | The format for ProxyHeaders is the same as Headers .If you specify proxy authentication either as a part of ProxyURL or by setting ProxyAuth and ProxyAuthType , HttpCommand will create a Proxy-Authorization header.
|
ProxyAuth
Description | This setting is the authentication/authorization string appropriate for the authentication scheme specified in ProxyAuthType . Used along with ProxyAuthType , ProxyAuth is a shortcut for setting the proxy-authorization HTTP header for requests that require proxy authentication. If ProxyAuth is non-empty, HttpCommand will create a 'proxy-authorization' header and and set its value to ProxyAuthType,' ',ProxyAuth . If you happen set both ProxyAuth and a proxy-authorization header, ProxyAuth takes precedence.
|
Default | '' |
Example(s) | h.ProxyAuth←'id' 'password' ⍝ HTTP Basic Authentication
h.ProxyAuth←h.Base64Encode 'id:password' ⍝ HTTP Basic Authentication |
Details | For HTTP Basic Authentication, ProxyAuth can be set to any of
ProxyURL as in 'http://username:password@someproxy.com' , HttpCommand will automatically generate a proper 'proxy-authorization' header.
|
ProxyAuthType
Description | This setting is used in conjunction with ProxyAuth and is a character vector indicating the authentication scheme. Three common authentication schemes are:
|
Default | '' |
Example(s) | h.ProxyAuthType←'Basic' |
Details |
If ProxyAuthType is not set and ProxyAuth is set to either a character vector in the form 'userid:password' or a 2-element vector of character vectors as in ('userid' 'password') HttpCommand will infer the ProxyAuthType to be 'Basic' . |
Ended: Settings
Shared Methods ↵
These "shortcut" methods make it easier to issue HTTP requests or create an instance of HttpCommand
.
Get
- issue an HTTP GET request
Get
is probably HttpCommand
's most-used feature. It issues an HTTP GET request and returns the response from the server. It can be used for many purposes including interacting with web services, downloading files, and returning the contents of web pages.
Syntax | r ←{RequestOnly} HttpCommand.Get args |
args |
Either
|
RequestOnly |
(optional) A Boolean indicating:
|
r |
If RequestOnly is
|
Example(s) | args ← ⎕NS '' args.URL ← 'httpbin.org' args.Params ← ('name' 'Donald')('species' 'duck') HttpCommand.Get args
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 339] HttpCommand.Get 'httpbin.org/get' (('name' 'Donald')('species' 'duck')) [rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 339] 1 HttpCommand.Get args GET /get?name=Donald&species=duck HTTP/1.1 Host: httpbin.org User-Agent: Dyalog-HttpCommand/5.0.2 Accept: */*
|
GetJSON
- issue a request to a JSON-based web service
GetJSON
is used to interact with web services that use JSON for their request and response payloads. It was originally developed as a convenient way to interact with Jarvis, Dyalog's JSON and REST Service framework. Conveniently, it turns out that there are many web services, including GitHub and Twitter, that use JSON as well.
When Command
is something other than GET
or HEAD
, GetJSON
will automatically convert APL Params
into JSON format. For GET
and HEAD
, HttpCommand
will URLEncode Params
in the query string of the URL
. The rationale behind this is that GET
and HEAD
requests should not have content; therefore Params
should be included in the query string of URL
and it doesn't make a lot of sense to include JSON in the query string. If you really need JSON in the query string, you can use ⎕JSON
to convert Params
.
GetJSON
will attempt to convert any JSON response payload into its equivalent APL representation.
Syntax | r ←{RequestOnly} HttpCommand.GetJSON args |
args |
Either |
RequestOnly |
(optional) A Boolean indicating:
|
r |
If RequestOnly is
|
Example(s) | These examples assume you have a Jarvis service running at http://localhost:8080 and a endpoint of #.sum ← {+/⍵} . args ← ⎕NS ''
args.Command ← 'post'
args.URL ← 'localhost:8080/sum'
args.Params ← ⍳1000
⊢r ← HttpCommand.GetJSON args
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: ⍬]
r.Data
500500
Params ← ('per_page' '3')('page' '1')('sort' 'full_name')
URL ← 'https://api.github.com/orgs/dyalog/repos'
⊢r ← HttpCommand.GetJSON 'get' URL Params
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 3]
r.Data.full_name
Dyalog/a3s-Linux Dyalog/APLCourse Dyalog/aplssh
|
Do
- issue a generic HTTP request
Do
is essentially the same as Get
except that you specify the HTTP method (Command
) to use.
Syntax | r ←{RequestOnly} HttpCommand.Do args |
args |
Either
|
RequestOnly |
(optional) A Boolean indicating:
|
r |
If RequestOnly is
|
Example(s) | args ← ⎕NS '' args.(Command URL) ← 'post' 'httpbin.org/post' args.Params ← ('name' 'Donald')('species' 'duck') HttpCommand.Do args
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 465] |
New
- create a new instance of HttpCommand
New
is different than the other shortcut methods in that it returns an instance of HttpCommand
. Get
, GetJSON
, and Do
all create an instance, run it, return the response namespace, and upon exit the instance is destroyed.
New
can be useful for maintaining state information, like HTTP cookies across multiple requests or keeping the connection to the host open so that subsequent requests to the host are processed without the overhead of re-establishing the connection.
After specifying the settings in the instance, run the Run
instance method to execute the request.
Syntax | instance ←{RequestOnly} HttpCommand.New args |
args |
Either:
|
RequestOnly |
(optional) A Boolean indicating when Run is executed:
|
instance |
An instance of HttpCommmand . |
Example(s) | Use a namespace for the request settings: args ← ⎕NS '' args.(Command URL) ← 'post' 'httpbin.org/post' args.Params ← ('name' 'Donald')('species' 'duck') cmd ← HttpCommand.New args
cmd.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 465] Create an instance of HttpCommand and set the settings directly: cmd ← HttpCommand.New '' ⍝ synonym for cmd ← ⎕NEW HttpCommand
cmd.(Command URL) ← 'post' 'httpbin.org/post' cmd.Params ← ('name' 'Donald')('species' 'duck') cmd.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 465] Set RequestOnly, display the request that would be sent, then send it cmd ← 1 HttpCommand.New 'get' 'dyalog.com'
cmd.Run
GET / HTTP/1.1 Host: dyalog.com User-Agent: Dyalog-HttpCommand/5.0.4 Accept: */* cmd.RequestOnly←0 cmd.Run [rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 23127] |
Base64 Encoding
Base64 is a binary-to-text encoding scheme that is used to transmit binary data over channels the only reliably support text content. Among Base64's uses are:
- Embed images or other binary assets in HTML files.
- Encode user credentials for HTTP Basic Authentication
Base64Decode
Decode a Base64-encoded string or single-byte integer vector.
Syntax | out←{cpo} HttpCommand.Base64Decode b64 |
b64 |
A character vector of Base64-encoded data. |
cpo |
(optional) cpo stands for "code points only". It can be any value, its mere existence is all that is necessary. You would use it in the case where you do not want Base64Decode to perform a UTF-8 conversion on the result. In almost all use cases, you can ignore this argument. |
out |
A character vector representing the decoded base-64 right argument. |
Example(s) | HttpCommand.Base64Decode 'RHlhbG9nIOKNuuKNtOKMig==' Dyalog ⍺⍴⌊ |
Base64Encode
Base64 encode a string or integer vector.
Syntax | b64←{cpo} HttpCommand.Base64Encode in |
in |
Either an integer vector with values in the range 0-255 or a character vector to be encoded |
cpo |
(optional) cpo stands for "code points only". If not supplied, Base64Encode will first perform UTF-8 conversion on a character argument. If any value for cpo is supplied, no conversion will be performed. If in is integer, no conversion is performed. The only use case for this argument is when you have already UTF-8 converted the in and you don't want Base64Encode to perform a second conversion. |
b64 |
A character vector representing the base-64 encoding of the right argument. |
Example(s) | HttpCommand.Base64Encode 'Dyalog ⍺⍴⌊' RHlhbG9nIOKNuuKNtOKMig== |
URL Encoding
URLs can only be sent over the Internet using the ASCII character set. However, URLs often contain characters outside the ASCII character set. URL encoding converts strings to a format acceptable for transmission over the Internet. URLEncoding is also used to encode payloads for content-type 'application/x-www-form-urlencoded'
.
UrlDecode
URLDecode a URLEncoded string.
Syntax | out←HttpCommand.UrlDecode in |
in |
A URLEncoded string |
out |
The URLDecoding of in . |
Example(s) | HttpCommand.UrlDecode 'Dyalog%20%E2%8D%BA%E2%8D%B4%E2%8C%8A' Dyalog ⍺⍴⌊ HttpCommand.UrlDecode 'name=Donald%20Duck' name=Donald Duck HttpCommand.UrlDecode 'first=Donald&last=O%27Mallard' first=Donald&last=O'Mallard |
UrlEncode
URLEncode a string or a set of name/value pairs.
Syntax | out←{name} HttpCommand.UrlEncode in |
in |
One of:
|
name |
(optional) The name for the URLEncoded right argument. Applies only in the case where in is a simple character vector. |
out |
The URLEncoding of in . |
Example(s) | HttpCommand.UrlEncode 'Dyalog ⍺⍴⌊' Dyalog%20%E2%8D%BA%E2%8D%B4%E2%8C%8A 'name' HttpCommand.UrlEncode 'Donald Duck' name=Donald%20Duck HttpCommand.UrlEncode ('first' 'Donald') ('last' 'O''Mallard') first=Donald&last=O%27Mallard |
This section describes HttpCommand
shared methods that don't conveniently fit into other categories.
Version
Returns HttpCommand
version information.
Syntax | r←HttpCommand.Version | |
Result | A 3-element vector of:
| |
Example | HttpCommand.Version HttpCommand 5.0.2 2022-08-03 |
Documentation
Returns a link to the documentation for HttpCommand
that you can click on to navigate to this documentation.
Syntax | r←HttpCommand.Documentation | |
Example | HttpCommand.Documentation See https://dyalog.github.io/HttpCommand/ |
Upgrade
Upgrade
checks GitHub for a newer version of HttpCommand
and if one is found it will be ⎕FIX
ed in the workspace.
Upgrade
will not work on Classic interpreters. To manually upgrade HttpCommand
:
- Open a browser to https://www.github.com/Dyalog/HttpCommand/releases/latest
- Click on the
HttpCommand.dyalog
file in the list of assets for the release. This will download the file. - From APL, do
2 ⎕FIX 'filename'
where filename is the full pathname of the downloaded file.
Note: Upgrade
will only update the in-workspace copy of HttpCommand
and will not update the version of HttpCommand
found in the Dyalog installation folder. The installed version of HttpCommand
is upgraded when updates to Dyalog APL are installed.
Syntax | r←HttpCommand.Upgrade |
r |
a 2-element vector of
|
Example | HttpCommand.Upgrade
0 Already using the most current version: HttpCommand 5.0.2 2022-08-03
|
Ended: Shared Methods
The methods documented in this section are instance methods and may be called from an instance of HttpCommand
. In the documentation below, we will use the name instance
to represent an instance of HttpCommand
.
Run
Run
"runs" the HTTP request defined by the instance's settings. Run
is called internally by the shared "shortcut" methods Get
, GetJSON
, and Do
.
Syntax | result←instance.Run | |
result |
result depends on the RequestOnly setting.If RequestOnly=1 , Run will return, if possible, the HTTP request that would be sent if RequestOnly was set to 0 . If HttpCommand cannot form a proper HTTP request, Run will return a result namespace with pertinent information.If RequestOnly=0 , Run will return a result namespace containing the result of attempting to build and send the HTTP request specified by the instance's settings.
| |
Examples | instance←HttpCommand.New '' instance.RequestOnly←1 There isn't sufficient information for HttpCommand to build a proper HTTP request. ⊢result ← instance.Run
[rc: ¯1 | msg: No URL specified | HTTP Status: "" | ⍴Data: 0] instance.URL←'dyalog.com' Now, there's enough information to form a proper HTTP request. ⊢result ← instance.Run GET / HTTP/1.1
instance.RequestOnly←0 ⊢result ← instance.Run [rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 23127]
|
Show
Returns the HTTP request that HttpCommand
would send when Run
is executed and RequestOnly
is 0
. Show
is equivalent to setting RequestOnly
to 1
and running Run
.
Syntax | r←instance.Show | |
Example | instance ← HttpCommand.New 'get' 'dyalog.com' instance.Show GET / HTTP/1.1 Host: dyalog.com User-Agent: Dyalog-HttpCommand/5.0.3 Accept: */*
|
Config
Config
returns the current state of all HttpCommand
settings.
Syntax | r←instance.Config |
r |
A 2-column matrix where[;1] contains the setting names[;2] contains the corresponding setting values |
Example |
instance←HttpCommand.New 'get' 'dyalog.com' instance.Config Auth AuthType BufferSize 200000 Cert Command get CongaPath CongaRef CongaVersion ContentType Cookies Debug 0 Headers KeepAlive 1 LDRC not set MaxPayloadSize ¯1 MaxRedirections 10 OutFile Params Priority NORMAL:!CTYPE-OPENPGP PrivateKeyFile PublicCertFile RequestOnly 0 Secret 1 SSLFlags 32 SuppressHeaders 0 Timeout 10 TranslateData 0 URL dyalog.com WaitTime 5000 |
Init
Init
initializes Conga, Dyalog's TCP/IP utility library. Normally, HttpCommand
will initialize Conga when Run
is first called. Init
is intended to be used when the user wants to "tweak" Conga prior to Run
being executed. It's very unlikely that you'll ever need to use Init
.
Syntax | r←instance.Init |
r |
a 2-element vector of
|
Example | instance←HttpCommand.New '' instance.CongaPath←'/doesnotexist' instance.Init ¯1 CongaPath "c:/doesnotexist/" does not exist
|
Header-related Methods
There are two sets of headers associated with an HTTP request - the request headers and the response headers. The methods described here deal with request headers.
HttpCommand
's request headers are stored in the Headers
setting which is a 2-column matrix of name/value pairs. Header names are case-insensitive; header values are not. While you can manipulate the Headers
array directly, HttpCommand
has three methods to manage Headers
that accommodate the case-insensitive nature of header names.
By default, HttpCommand
will automatically generate several request headers if you haven't specified values for them. See SuppressHeaders
for the list of these headers. To suppress the generation of specific headers, you can set its value to ''
.
You may specify that HttpCommand
should substitute the value of an environment variable in a header name or value by surrounding the name of the environment variable with %
. For example:
1 HttpCommand.Get 'someurl.com' '' ('MyHeader' '%DYALOG%')
GET / HTTP/1.1
MyHeader: C:\Program Files\Dyalog\Dyalog APL-64 19.0 Unicode
Host: someurl.com
User-Agent: Dyalog-HttpCommand/5.5.0
Accept: */*
Accept-Encoding: gzip, deflate
Note: The examples below were run using ]boxing on
.
AddHeader
AddHeader
will add a header if a user-defined header with that name does not already exist. Use SetHeader
to set a header regardless if one with the same name already exists.
Syntax | {hdrs}←name instance.AddHeader value |
value |
the value for the header |
name |
the name for the header |
hdrs |
the updated matrix of user-specified headers |
Example | instance←HttpCommand.New '' 'My-Header' instance.AddHeader 'Drake Mallard' instance.Headers ┌─────────┬─────────────┐ │My-Header│Drake Mallard│ └─────────┴─────────────┘ AddHeader will not replace an existing header with the same case-insensitive name 'my-header' instance.AddHeader 'Daffy Duck' instance.Headers ┌─────────┬─────────────┐ │My-Header│Drake Mallard│ └─────────┴─────────────┘ Setting the value of an HttpCommand -generated header that to '' will suppress that header from being sent in the request. 'accept-encoding' instance.SetHeader '' |
SetHeader
SetHeader
will set a header, replacing one of the same name if it already exists.
Syntax | {hdrs}←name instance.SetHeader value |
value |
the value for the header |
name |
the name for the header |
hdrs |
the updated matrix of user-specified headers |
Example | instance←HttpCommand.New '' ⊢'My-Header' instance.SetHeader 'Drake Mallard' ┌─────────┬─────────────┐ │My-Header│Drake Mallard│ └─────────┴─────────────┘ SetHeader will replace an existing header with the same case-insensitive name ⊢'my-header' instance.SetHeader 'Daffy Duck' ┌─────────┬──────────┐ │My-Header│Daffy Duck│ └─────────┴──────────┘ Setting the value of an HttpCommand -generated header that to '' will suppress that header from being sent in the request. 'accept-encoding' instance.SetHeader '' |
RemoveHeader
RemoveHeader
removes a user-specified header. If the header does not exist, RemoveHeader
has no effect. RemoveHeader
does not affect the HttpCommand
-generated headers.
Syntax | {hdrs}←instance.RemoveHeader name |
name |
the case-insensitive name of the header to remove |
hdrs |
the updated matrix of user-specified headers |
Example | 'My-Header' instance.SetHeader 'Daffy Duck'
'another' instance.SetHeader 'some value'
instance.Headers ┌─────────┬──────────┐ │My-Header│Daffy Duck│ ├─────────┼──────────┤ │another │some value│ └─────────┴──────────┘
instance.RemoveHeader 'my-header' instance.Headers ┌───────┬──────────┐ │another│some value│ └───────┴──────────┘ |
Result Namespace ↵
For the purposes of this document, we will refer to result
as the result namespace returned by Run
when RequestOnly=0
. result
contains information about the request and the response, if any, from the host. Some settings from the request are copied into result
.
rc
The operational return code. This indicates if HttpCommand
was able to form and send an HTTP request and process the response from the host. The sign of rc
indicates:
rc=0
no operational error occurred.rc<0
an operational error occurred.rc>0
a Conga error occurred.
rc
is further described in Messages and Return Codes. To verify that an HTTP request was successful, first check that result.rc=0
and then that result.HttpStatus
is a HTTP status code you would expect from the host.
msg
The operational status message. If rc=0
, msg
will generally be empty (''
). msg
will contain (hopefully) helpful information as to the nature of the error or condition. msg
is further described in Messages and Return Codes.
∇IsOK
IsOK
is a function included in the result namespace that makes it easier to check if the HTTP request was successful by checking both that rc=0
and HttpStatus
is a 200-series value. If the request was successful, IsOK
will return 1
, otherwise it will return 0
.
Syntax | bool ← IsOK | |
Example(s) | result←HttpCommand.Get 'dyalog.com' result.IsOK 1 result←HttpCommand.Get 'blooofo.com' ⍝ domain does not exist result.IsOK 0 |
Elapsed
The number of millseconds that the request took to process.
OutFile
OutFile
is copied from the OutFile
setting so that, if the response payload is written to file, the result namespace has a record of the file name.
BytesWritten
If OutFile
is non-empty, and the HTTP request was successful, BytesWritten
is the number of bytes written to that file named by OutFile
. Otherwise, BytesWritten
is set to ¯1
.
For the purposes of this document, we will refer to result
as the result namespace returned by Run
when RequestOnly=0
. result
contains information about the request and the response, if any, from the host.
Request-related elements in the result namespace are either copied or derived from certain request settings. Not all request settings are included in the result namespace, but they are retained in the HttpCommand
instance.
Command
The case-insensitive HTTP command (method) for the request.
Host
The final host to which the HTTP request was sent. This may be different from the host specified in the URL
setting if the request was redirected.
Path
The final path for the requested resource. This may be different from the resource specified in the URL
setting if the request was redirected.
Port
The port that the request was sent to. If the request was redirected, this may be different from the port specified in the URL
setting or the original default port if no port was specified in URL
.
Secure
A Boolean indicating whether the final request was sent using HTTPS. If the request was redirected, this may be reflect a different secure state from the original request.
URL
The final URL of the HTTP request. If the request was redirected, this may be different from the URL
setting.
For the purposes of this document, we will refer to result
as the result namespace returned by Run
when RequestOnly=0
. result
contains information about the request and the response, if any, from the host. Some settings from the request are copied into result
.
HttpStatus
The integer HTTP response status code returned by the host. Status codes are split into specific ranges:
- 1xx: Informational - Request received, continuing process
- 2xx: Success - The action was successfully received, understood, and accepted
- 3xx: Redirection - Further action must be taken in order to complete the request
- 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
- 5xx: Server Error - The server failed to fulfill an apparently valid request
HttpMessage
A character vector indicating the HTTP message coresponding to the HTTP status code.
HttpVersion
A character vector indicating the HTTP version used by the host.
Data
In most cases Data
will be the response's character vector payload. Data
is not populated if the OutFile
setting is set - the payload is instead written, as received, to file.
The Content-Type
response header will indicate the type of data in the payload and the Content-Encoding
header, if present, will indicate the compression scheme used if the payload is compressed.
If the response payload is compressed using 'deflate' or 'gzip' encoding HttpCommand
will uncompress the payload.
If the Content-Type
header indicates that the UTF-8 character set is used, HttpCommand
will convert the payload to UTF-8.
HttpCommand
can translate certain content types into a format that may be more useful in the APL environment. If the TranslateData is set to 1
, HttpCommand
will attempt to translate application/json
content using ⎕JSON
, and text/xml
and application/xml
using ⎕XML
.
Headers
Headers
is the 2-column matrix of response header name/value pairs.
Note: There are two sets of headers in an HTTP request/response transaction - the request headers that are sent to the host, and the response headers that are sent back from the host.
∇GetHeader
GetHeader
is a utility function included in the result namespace that makes it easier to extract response header values. GetHeader
accommodates the case-insensitive nature of header names. If the header does not exist, GetHeader
returns ''
.
Syntax | value ← {headers} result.GetHeader name | |
name |
A character vector header name, or vector of header names | |
headers |
The optional header array to extract from. By default, GetHeader will use the response's Headers array. You may also pass the Headers element of a redirection (see Redirections ). | |
value |
The header value(s) corresponding to the header names specified in name , or the empty vector '' for header name(s) that don't exist. | |
Example(s) | result.GetHeader 'content-type' text/html; charset=utf-8 ⍝ Note: there is no 'fred' header result.GetHeader 'content-type' 'fred' 'server' ┌────────────────────────┬┬──────────────────────┐ │text/html; charset=utf-8││Apache/2.4.18 (Ubuntu)│ └────────────────────────┴┴──────────────────────┘ |
Cookies
Cookies
is a vector of namespaces, one per cookie set by the host. Cookies
are frequently used to maintain a state between the client (HttpCommand
) and the host. When using an instance of HttpCommand
, the instance will retain a copy of Cookies
and apply appropriate cookies to subsequent requests.
The sample below shows the names and first 50 characters of the values of 3 cookies returned by GitHub.com. The first cookie holds the session ID.
'Name' 'Value'⍪↑(HttpCommand.Get'github.com').Cookies.(Name((50∘⌊∘≢↑⊢)Value))
Name Value
_gh_sess A0ZezbnUgtkiq1lBubH7mrXclGhvhcCFKRUbAb045wGNT2Hlma
_octo GH1.1.809596667.1660313286
logged_in no
PeerCert
If the connection to the host uses HTTPS as its protocol which means it is a secure connection, then PeerCert
contains the X509 certificate of the host.
⊃(HttpCommand.Get 'dyalog.com').PeerCert.Formatted.(Issuer Subject)
┌──────────────────────────┬───────────────┐
│C=US,O=Let's Encrypt,CN=R3│CN=*.dyalog.com│
└──────────────────────────┴───────────────┘
Redirections
Redirections
is a vector of namespaces, one per HTTP redirect response from the host. An HTTP redirect is a special kind of response from the host that directs the client to another location for the resource that's being requested. When a web browser like Google Chrome or Mozilla Firefox receives a redirect response, they automatically reissue the request for the resource at the new location. The new location is specified in the response's Location
header. A redirection can itself be redirected and can even result in an infinite redirection loop. HttpCommand
will also follow the redirections, but it also retains information about each redirection in Redirections
. The MaxRedirections
setting can limit the number of redirections that HttpCommand
will follow.
Each namespace in Redirections
has the following elements:
HttpStatus | The HTTP status for the request. |
HttpMessage | The corresponding HTTP status message for the request. |
HttpVersion | The HTTP version that was used in sending the response. |
Headers | The headers that were sent by the host. There should be a 'Location' header that indicates the redirection location for the requested resource |
URL | The URL that was used and produced this redirection. |
The example below uses httpbin.org/relative_redirect/2
to redirect the request twice.
⊢result ← HttpCommand.Get 'http://httpbin.org/relative_redirect/2'
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 266]
Examining the information in the 2 redirections shows that our original URL
, 'httpbin.org/relative-redirect/2'
, was redirected to /relative-redirect/1
which was subsequently redirected to /get
.
'URL' 'Was redirected to'⍪result.(Redirections.URL,⍪Redirections.Headers GetHeader¨⊂'location')
┌───────────────────────────────┬────────────────────┐
│URL │Was redirected to │
├───────────────────────────────┼────────────────────┤
│httpbin.org/relative-redirect/2│/relative-redirect/1│
├───────────────────────────────┼────────────────────┤
│httpbin.org/relative-redirect/1│/get │
└───────────────────────────────┴────────────────────┘
Ended: Result Namespace
rc
Values
The value of rc
may be interpreted as follows:
Error Type | rc Value |
Description |
---|---|---|
No error | 0 |
HttpCommand was able to format and send the request and receive a response without error. |
Conga error | >0 |
If rc is a positive integer, it is a return code that is signalled by Conga when sending the request and receiving the response. If Conga detects an error at the operating system level, it will return the operating system return code. For instance, 10013 is the Microsoft Windows return code for "port in use". |
Translation Error | ¯2 |
You specified TranslateData←1 and HttpCommand was unable to translate an XML or JSON response payload using ⎕XML or ⎕JSON respectively or you used GetJSON and response content-type header was not 'application/json' . |
Everything else | ¯1 |
This is the generic return code for any error condition that is not signalled by Conga. |
In general if rc=0
then msg
will be empty. There are circumstances where msg
will contain an informational message even if rc=0
. These messages are included below.
In the following message descriptions, items that are enclosed in {} represent the value of that named item. For instance, {BufferSize} represents the value of the BufferSize
setting. In many cases, the message text itself is sufficient to explain the condition and its resolution, but we document them nonetheless for completeness.
Request-related Messages
"Catch All" Messages
Message | Unexpected {ERROR} at {location} |
Description | You should rarely, if ever, see this message. It is returned when an error occurred that wasn't anticipated or otherwise handled. |
Resolution | Try to find a consistently reproduceable example and contact Dyalog support. |
Message | Invalid HttpCommand setting(s): {setting name(s)} |
Description | You passed a namespace argument New , Get , GetJSON , or Do or as a constructor argument to ⎕NEW and that namespace contained named elements that are not valid HttpCommand setting names. |
Resolution | Remove the named elements that are not HttpCommand setting names. |
Message | Stopped for debugging... (Press Ctrl-Enter) |
Description | This message is not returned in the result namespace, but is displayed when you have set Debug←2 and HttpCommand has stopped intentionally just prior to establishing the connection to the host. |
Resolution | Pressing Ctrl-Enter will open the debugger and trace into HttpCommand . Entering →⎕LC+1 |
Non-Conga Setting Messages
These messages report problems with settings that prevent HttpCommand
from creating a proper HTTP request to send to the host.
Message | No URL specified |
Description | You didn't specify a URL setting. |
Resolution | Specify a valid URL . |
Message | URL is not a simple character vector |
Description | The URL setting isn't a simple character vector. |
Resolution | Make sure URL isn't nested or non-character. |
Message | Invalid host/port: {host} |
Description | You specified a URL that has a hostname followed by a colon (':' ) followed by something that does not parse as an integer. For example: 'dyalog.com:ducky' |
Resolution | Correct (or omit) the bad port specification. |
Message | No host specified |
Description | HttpCommand couldn't find a host in the URL setting. |
Resolution | Ensure your URL conforms to the specification. |
Message | Invalid port: {port} |
Description | The port you specified is not in the range 1-63535. |
Resolution | Specify an integer port number in the range 1-65535. |
Message | Invalid protocol: {protocol} |
Description | HttpCommand thinks you've specified a protocol other than 'http://' or 'https:// . |
Resolution | HttpCommand supports only the HTTP and HTTPS protocols. If you have not specified the protocol in your URL setting, HttpCommand will default to use HTTP. HTTPS will be used if you've specified either the default secure port (443) or supplied certificate information. |
Message | Cookies are not character |
Description | Cookies are specified as name/value pairs. All of the names and values need to be character. |
Resolution | Make sure Cookies names and values are character. |
Message | Headers are not character |
Description | Headers may be specified as name/value pairs. All of the names and values need to be character. |
Resolution | Make sure Headers names and values are character. |
Message | Improper header format |
Description | You used a value for Headers that did not conform to one of the formats described in the Headers specification. |
Resolution | Ensure that Headers conforms to the specification |
Message | Output file folder {foldername} does not exist. |
Description | The folder in your {OutFile} setting does not exist. HttpCommand will create the output file, if necessary, in an existing folder but HttpCommand will not create a new folder. |
Resolution | Either create the folder or change the OutFile setting. |
Message | No filename specified in OutFile or URL |
Description | If you do not specify a file name in OutFile , HttpCommand will attempt to use the file name specified in URL . However, if there is also no file name in URL , you will receive this message. |
Resolution | Specify a file name in either OutFile or URL . |
Message | Output file "{OutFile}" is not empty |
Description | You specified the name of an existing, non-empty, file in OutFile but did not specify to overwrite or append to the file. |
Resolution | Either specify a filename of a file that doesn't exist or is empty, or specify that the file is to be overwritten or appended to. |
Conga Setting Messages
The messages in this section are related to the Conga settings in HttpCommand
, not the actual execution of Conga code whose messages are described in "Conga Execution"-Related Messages.
Message | CongaRef {CongaRef} does not point to a valid instance of Conga |
Description | You specified a CongaRef setting that is not the name of, or a reference to, the Conga or the DRC namespace. |
Resolution | Check that CongaRef is actually the name of, or a reference to, the Conga or the DRC namespace. |
Message | {location}.{namespace} does not point to a valid instance of Conga |
Description | HttpCommand searches for the Conga API according to these rules and found a namespace named either Conga or DRC , but that namespace is not a valid Conga namespace. |
Resolution | Either set CongaRef to point to a proper Conga or DRC namespace, or remove/rename the offending namespace. |
Message | CongaPath "{CongaPath}" does not exist |
Description | You specified a CongaPath that could not be found. |
Resolution | Set CongaPath to the name of an existing folder containing the Conga shared libraries, or do not set CongaPath and let HttpCommand use the Dyalog installation folder. |
Message | CongaPath "{CongaPath}" is not a folder |
Description | You specified a CongaPath that exists, but is not a folder. |
Resolution | Set CongaPath to the name of an existing folder containing the Conga shared libraries, or do not set CongaPath and let HttpCommand use the Dyalog installation folder. |
Message | {Conga API} was copied from {path}, but is not valid |
Description | HttpCommand was able to copy either the Conga or the DRC namespace according to the procedure described in Conga Default Behavior, but the namespace was not a valid Conga API. |
Resolution | Ensure that conga workspace from which HttpCommand attempted to copy the Conga API is proper and the same version as the shared libraries. See Integrating HttpCommand . |
Message | Neither Conga nor DRC were successfully copied |
Description | HttpCommand was unable to copy either the Conga or the DRC namespace according to the procedure described in Conga Default Behavior. |
Resolution | The most likely cause is that there is no conga workspace in the paths from which HttpCommand tried to copy. See Integrating HttpCommand . |
Message | Not found PublicCertFile "{PublicCertFile}" Not found PrivateKeyFile "{PrivateKeyFile}" Not found PublicCertFile "{PublicCertFile}" and PrivateKeyFile "{PrivateKeyFile}" |
Description | One or both of the file names you specified for PublicCertFile and PrivateKeyFile does not exist. |
Resolution | Set PublicCertFile and PrivateKeyFile to the names of certificate files that actually exist. |
Message | PublicCertFile is empty PrivateKeyFile is empty |
Description | You have specified one of PublicCertFile or PrivateKeyFile , but not the other. |
Resolution | Be sure to set both PublicCertFile and PrivateKeyFile . |
Message | Invalid certificate parameter |
Description | You specified a value for Cert that is not a valid instance of Conga's X509 class. |
Resolution | Make sure that Cert is a valid instance of the |
Message | Unable to decode PublicCertFile "{PublicCertFile}" as certificate |
Description | An error occurred when Conga attempted to use X509Cert.ReadCertFromFile with the value you specified for PublicCertFile . |
Resolution | Make sure PublicCertFile contains a valid certificate. See the Conga User Guide for more information. |
Conga Execution Messages
The messages in this section are returned when Conga returns a non-zero return code, or an unexpected Conga event occurs. If there is a non-zero return code from Conga, it is returned in rc
.
HttpCommand
uses Conga's "HTTP" mode, where Conga will parse the response from the host. Some of the messages occur when the host sends an ill-formed response and Conga cannot parse it as HTTP. The ill-formed data is returned in the Data
element of HttpCommand
's result namespace.
Message | Could not initialize Conga due to... |
Description | Conga could not be initialized for one of many reasons. The remainder of the message should give some indication as to what the problem was. Examples of problems include:
|
Resolution | The resolution will depend on the circumstances described in the message. The Conga User Guide and/or the Integrating HttpCommand section could be helpful here. |
Message | Conga client creation failed... |
Description | This will occur if Conga is not able to create a client connection to the host. The remainder of the message will indicate the specific Conga error message. |
Resolution | The resolution will depend on the circumstances described in the message. See the Conga User Guide. |
Message | Conga could not parse the HTTP response |
Description | The response from the host is not a properly formatted HTTP message. |
Resolution | Inspect the data returned by the host in the Data element of the result. |
Message | Response payload not completely received |
Description | This occurs when HttpCommand was able to receive and parse the HTTP headers from the host but, during the receipt of the response payload, an error occurred. |
Resolution | Attempt the request again. If the error persists, examine the headers and payload data, if any, returned by the host. |
Message | Conga error processing your request: {Conga return code} |
Description | Conga encountered some error that wasn't otherwise diagnosed or trapped. |
Resolution | See the Conga User Guide for guidance. |
Message | Socket closed by server |
Description | During processing of the request, the server unexpectedly closed the connection to HttpCommand . |
Resolution | Check that your request is proper for the host. See the Troubleshooting guide. |
Message | Unhandled Conga event type: {Conga event} |
Description | This should never occur, but for the sake of paranoia, we coded for the possibility of a Conga event that we didn't anticipate. |
Resolution | Try to find a consistently reproduceable example and contact Dyalog support. |
Message | Conga wait error: {Conga return code} |
Description | An error occurred while Conga was waiting for a response from the host. |
Resolution | Re-attempt the request. Examine any data or headers that may have been received for clues. |
Message | Could not set DecodeBuffers on Conga client "{Conga client name}": {Conga return code} |
Description | This is another error that should never occur. |
Resolution | Try to find a consistently reproduceable example and contact Dyalog support. |
Message | Conga failed to parse the response HTTP header |
Description | Conga received an HTTPHeader event but was unable to parse the received data as HTTP headers. |
Resolution | The unparseable data is returned in the Data element of the result namespace and may provide insight as to the problem. |
Message | Conga failed to parse the response HTTP chunk |
Description | Conga received an HTTPChunk event but was unable to parse the received data as an HTTP chunk. |
Resolution | The unparseable data is returned in the Data element of the result namespace and may provide insight as to the problem. |
Message | Conga failed to parse the response HTTP trailer |
Description | Conga received an HTTPTrailer event but was unable to parse the received data as an HTTP trailer. |
Resolution | The unparseable data is returned in the Data element of the result namespace and may provide insight as to the problem. |
Message | Conga error while attempting to send request: {Conga return code} |
Description | Conga was able to establish a connection to the host, but encountered an error when attempting to send the HTTP request. |
Resolution | Examine the request being sent as described in the Troubleshooting guide. The Conga User Guide may also be helpful. |
Message | Unable to set EventMode on Conga root |
Description | This is another message that should never occur. |
Resolution | Try to find a consistently reproduceable example and contact Dyalog support. |
Operational Messages
Message | {ERROR} while trying to initialize output file "{OutFile}" |
Description | You specified an OutFile setting and an error occured while trying to initialize the file. |
Resolution | {ERROR} should provide information that will help determine the resolution. |
Message | Response header size exceeds BufferSize {BufferSize} |
Description | The size of the response's HTTPHeader message exceeded the value set for BufferSize. |
Resolution | BufferSize is intended to help counteract maliciously large message headers. If the response headers are expected to be very large, increase the value of BufferSize . |
Message | Payload length exceeds MaxPayloadSize |
Description | The content-length header in the response had a value that exceeded the MaxPayload setting. |
Resolution | MaxPayloadSize is intended to help counteract maliciously large messages. If the response payload is expected to be very large, increase the value of MaxPayloadSize |
Message | Request timed out before server responded |
Description | The host did not respond within the number of seconds specified in the Timeout setting. |
Resolution | If you expect the host to be slow in responding, increase the magnitude of the Timeout setting. |
Message | Redirection detected, but no "location" header supplied. |
Description | The host responded with a 3XX HTTP status (redirection), but the response did not contain a location header indicating where to redirect the request. |
Resolution | This is a server-side problem. |
Message | Too many redirections ({MaxRedirections}) |
Description | The host sent more 3XX HTTP status responses (redirections) than MaxRedirections specified. |
Resolution | MaxRedirections is intended to prevent redirection loops or too many redirection hops. If the redirections are legitimate, increase the value of MaxRedirections . |
Message | TRANSLATION ERROR occurred during response payload conversion (Data was not converted) |
Description | This will occur if the response payload contains an invalid UTF-8 sequence or if you are using a Classic interpreter and the response payload contains characters not found in ⎕AVU . Data will contain the response payload as an unconverted vector of single-byte integers. |
Resolution | If you're using a Classic interpreter, consider using a Unicode interpreter. Otherwise try to identify the offending characters/sequences and take appropriate action to remove or amend them. |
Message | Could not translate XML payload |
Description | If you specify TranslateData←1 and the response content-type header contains 'text/xml' or 'application/xml' , HttpCommand will attempt to use ⎕XML to translate the payload. If ⎕XML fails, this message is returned and rc is set to ¯2 . |
Resolution | This is probably due to the response payload containing incorrectly formatted XML. The untranslated payload is returned in Data . |
Message | Could not translate JSON payload |
Description | If you specify TranslateData←1 or use the GetJSON shared method and the response content-type header contains 'application/json' , HttpCommand will attempt to use ⎕JSON to translate the payload. If ⎕JSON fails, this message is returned and rc is set to ¯2 . |
Resolution | This is probably due to the response payload containing incorrectly formatted JSON. The untranslated payload is returned in Data . |
Message | Response content-type is not application/json |
Description | You used GetJSON and the response content-type header is not 'application/json' . rc is set to ¯2 and Data contains the response payload. |
Resolution | GetJSON expects the response content-type to be 'application/json' . If the host is expected to return some other content-type, consider using a method other than GetJSON . |
Informational Messages
These messages are issued to inform you that, while there was no actual error,
Message |
|
Description | |
Resolution |
Message | Connection properties changed, connection reset |
Description | Unless otherwise specified, an instance of HttpCommand will attempt to keep the connection for the last request open. If any of the connection properties change on a subsequent request, the old connection closed and a new connection is established. |
Resolution | No resolution necessary. |
Message | Unhandled content-encoding: {content-encoding} |
Description | This message occurs if the response's content-encoding header is something other than 'gzip' or 'deflate' .It is intended to inform you that HttpCommand did not automatically decode the payload. |
Resolution | Your application will need to decode the payload. |
Other Messages
These messages are not found in the msg
element of result namespace, but are issued when using other features of HttpCommand
.
Message | Could not ⎕FIX file: {ERROR}{: Message} |
Description | The Fix method was not able to ⎕FIX the file content returned as the response payload. |
Resolution | Ensure that the requested file contains ⎕FIX -able contents. |
Message | Could not ⎕FIX new HttpCommand: {ERROR}{: Message} |
Description | The Upgrade method was not able to ⎕FIX a newer HttpCommand . |
Resolution | See Upgrade . If the problem persists, contact Dyalog support. |
Message | Upgraded to {new-version} from {old-version} |
Description | The Upgrade method was able to ⎕FIX a newer version of HttpCommand . |
Resolution | See Upgrade . |
Message | Already using the most current version {version} |
Description | The Upgrade method did not find a newer version of HttpCommand . |
Resolution | See Upgrade . |
Ended: Reference
Advanced Topics ↵
If your HTTP request has a payload and you do not specify the content type, HttpCommand
will attempt to determine whether to use a content type of 'application/json'
or 'application/x-www-form-urlencoded'
.
This may be fine for interactively tinkering in the APL session. But when running HttpCommand
under program control you should explicitly specify the content type for the payload by either setting ContentType
or adding a content-type
header.
The exception to this is when using GetJSON
which is specifically intended to interact with JSON-based web services and will use a default content type of application/json
.
Special Treatment of Content Type application/json
If you specify a content type of 'application/json'
, HttpCommand
will automatically convert a non-JSON Params
setting to JSON. In the rare case where Params
is an APL character vector that happens to represent valid JSON, you should convert it yourself using 1 ⎕JSON
.
Special Treatment of Content Type multipart/form-data
Content type multipart/form-data
is commonly used to transfer files to a server or to send multiple types of content in the request payload. If you specify a content type of 'multipart/form-data'
:
Params
must be a namespace with named elements.- Each element in
Params
consists of the data for the element optionally followed by a content type for the element. - To send a file, prefix the file name with either:
@
to upload the file's content and its name<
to upload just the file's content
- If you do not specify a content type for the file,
HttpCommand
will use a content type of'text/plain'
if the extension of the file is .txt, otherwise it will use a content type of'application/octet-stream'
.
In the example below:
- Extra newlines have been removed for compactness.
- The file
/tmp/foo.txt
containsHello World
. - We create 4 parts to be sent with the request:
- a simple string
- a named file - both the content and file name will be sent
- an unnamed file - only the content will be sent
- a JSON array (with content type 'application/json')
h←HttpCommand.New 'post' 'someurl.com'
p←⎕NS '' ⍝ create a namespace
p.string←'/tmp/foo.txt' ⍝ just a value
p.namedfile←'@/tmp/foo.txt' ⍝ @ = include the file name
p.unnamedfile←'</tmp/foo.txt' ⍝ < = do not include the file name
p.json←'[1,2,3]' 'application/json' ⍝ value and content type
h.Params←p ⍝ assign the request Params
h.ContentType←'multipart/form-data' ⍝
h.Show
POST / HTTP/1.1
Host: someurl.com
User-Agent: Dyalog-HttpCommand/5.6.0
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
Content-Length: 631
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
Content-Disposition: form-data; name="json"
Content-Type: application/json
[1,2,3]
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
Content-Disposition: form-data; name="namedfile"; filename="foo.txt"
Content-Type: text/plain
Hello World
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
Content-Disposition: form-data; name="string"
/tmp/foo.txt
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
Content-Disposition: form-data; name="unnamedfile"
Content-Type: text/plain
Hello World
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd--
HttpCommand
uses Conga, Dyalog's TCP/IP utility library, for communications. HttpCommand
requires Conga version 3.0 or later. Conga consists of two elements:
- Two shared library files whose names begin with "conga" and are found in the Dyalog installation folder. The names of the files varies based on the platform they are running on and the specific version of Conga; for instance
conga34_64.dll
andconga34ssl64.dll
are the shared library files for Conga version 3.4 for the 64-bit version of Dyalog for Windows. - An APL-based API to communicate with the shared libraries. There are two versions of the API both of which are available in the
conga
workspace.- A namespace named
Conga
which was introduced with Conga version 3.0 and implements behavior that makes it easier to run multiple Conga-based utilities in the same workspace.Conga
is the recommended API version to use. - A namespace named
DRC
which is retained for backward-compatibility with applications which use earlier versions of Conga.DRC
should only be used in an application where backward compatibility is necessary.
- A namespace named
The Conga API looks for a matching version of the shared libraries; as such version of the API and the shared libraries must be the same. For more information on Conga please refer to the Conga User Guide.
Default Behavior
When first run, HttpCommand
will attempt find or copy the Conga API and then initialize it. HttpCommand
will attempt to use the Conga
version of the API in preference to the DRC
version. In general, all of this is transparent to the user.
- Look in the current workspace for the Conga API:
- First look in the namespace where
HttpCommand
resides for a namespace named eitherConga
orDRC
, in that order. - Failing that, look in the root namespace
#
for a namespace named eitherConga
orDRC
, in that order.
- First look in the namespace where
- If neither version of the API is found in the current workspace,
HttpCommand
will attempt to copy the API (firstConga
thenDRC
) from theconga
workspace. The API is copied into theHttpCommand
class which means there will be no additional footprint in workspace.HttpCommand
will attempt to copy the API as follows:- If the
DYALOG
environment variable exists, use its folder. Otherwise use the folder from the command line used to start Dyalog. - If that fails, then attempt to copy from the "current" folder as determined by
⊃1 ⎕NPARTS ''
- If the
- If the API was found or successfully copied,
HttpCommand
will initialize Conga as follows:- If the
Conga
version of the API is used,HttpCommand
will initialize it with a root name of'HttpCommand'
. - If the
DRC
version of the API is used,HttpCommand
will simply initialize it. AsDRC
does not support multiple roots, care should be taken if other Conga-using utilities also reside in the workspace.
- If the
- If the API was successfully initialized, a reference to the API root can be found in
HttpCommand.LDRC
.
Overriding Default Locations
There are two methods to tell HttpCommand
's default behavior, both of which involve setting a shared public field in the HttpCommand
class.
- If you have the
Conga
namespace in your workspace in other than default locations theHttpCommand
will search,HttpCommand.CongaRef
can be used to specify its location.CongaRef
can be an actual reference to the namespace or a character array representing the location. For instance:
HttpCommand.CongaRef←#.Utils.Conga
or
HttpCommand.CongaRef←'#.Utils.Conga'
This can be useful when integratingHttpCommand
into an application that also uses Conga. HttpCommand.CongaPath
can be used to specify the path to the shared library files and optionally the conga workspace. This can be useful when bundlingHttpCommand
in a distributed application. For instance:
HttpCommand.CongaPath←(⊃1 ⎕NPARTS ''),'/conga/'
would tellHttpCommand
to find the shared libraries in the/conga/
subfolder of the current folder. See IntegratingHttpCommand
for more information.
Using Other Versions of Conga
If you need to use a version of Conga other than the one in the Dyalog installation folder, there are two ways to accomplish this:
- Put the shared libraries and the
conga
workspace in a folder and setCongaPath
to point to that folder. - Put the
Conga
namespace in your workspace (pointingCongaRef
to it if necesssary) and the shared libraries in a folder setCongaPath
to point to that folder.
Timeout and WaitTime
The operational setting Timeout should not be confused with the Conga setting WaitTime . Internally, after sending the request to the host, HttpCommand
sits in a Conga Wait loop, listening for a response. WaitTime
is the number of milliseconds that Conga will wait before timing out. When this happens, HttpCommand
checks if the request itself has timed out based on the setting of Timeout
. If it has, then HttpCommand
will stop with a return code of 100 indicating the timeout. If the request has not timed out, then HttpCommand
will perform another
iteration of the Conga Wait loop.
It is generally unnecessary to adjust the WaitTime
setting. If your request is timing out, increase the Timeout
setting.
Note that Timeout
is in seconds and WaitTime
is in milliseconds.
HTTPS
In the HTTP world, secure communications is accomplished by using the HTTPS protocol which uses Transport Layer Security (TLS) or Secure Sockets Layer (SSL) to encrypt communications. Both the client (HttpCommand
) and the server use certificates for secure communications. The certificates serve a couple of purposes:
- They provide bi-directional encryption of the data sent across the link.
- They can help provide authentication of the client and/or the server.
HttpCommand
Behavior
HttpCommand
attempts to figure out if the connection is going to use HTTPS and what port to use based on:
- The protocol, if any, that you specify in
URL
. - The port, if any, that you specify in
URL
. - Whether you have provided certificate information for the request.
HttpCommand
will use HTTPS if
- You provide certificate information by using the
Cert
orPublicCertFile
andPrivateKeyFile
settings. - You specify
'https'
as the protocol. - You don't specify a protocol, but do specify a port in
URL
of 443.
HttpCommand
will use port 443 if you do not specify a port in URL
and HttpCommand
has otherwise determined from the above criteria that the connection should use HTTPS.
Encrypted Communications
In most cases, the use of certificates is hidden when using the HTTPS protocol because HttpCommand
will automatically generate an "anonymous" certificate. This is sufficient to provide secure, encrypted, communications.
Authentication
Certificates can provide information about the identity of what is at the other end of the communications link.
Server Identity
When HttpCommand
uses HTTPS, the PeerCert
element of the result namespace contains the server's certificate. This can be used to validate the server is what you think it is. Most certificates will have a "chain" of parent certificates that show who issued the peer's certificate and any intermediate certificates. If the final certificate in the chain is issued by a Trusted Root Certificate Authority the domain listed in the certificate has undergone validation by an entity that you can trust.
Dyalog.com provides us with an example of a certificate chain:
⊢ r ← HttpCommand.Get 'https://dyalog.com'
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 23127]
r.PeerCert ⍝ Dyalog.com's certificate
#.HttpCommand.[X509Cert]
r.PeerCert.Chain
#.HttpCommand.[X509Cert] #.HttpCommand.[X509Cert] #.HttpCommand.[X509Cert]
⍪⊃r.PeerCert.Chain.Formatted.(Subject,' from ',Issuer)
CN=*.dyalog.com from C=US,O=Let's Encrypt,CN=R3
C=US,O=Let's Encrypt,CN=R3 from C=US,O=Internet Security Research Group,CN=ISRG Root X1
C=US,O=Internet Security Research Group,CN=ISRG Root X1 from O=Digital Signature Trust Co.,CN=DST Root CA X3
This shows that the certificate for '*.dyalog.com'
was issued by Let's Encrypt whose certificate was issued by Internet Security Research Group whose certificate was issued by Digital Signature Trust Co and Digital Signature Trust Co is a Trusted Root Certificate Authority.
The good news is that in most cases you'll never need to look at the certificate chain, but it is available in the rare event that you need to verify the server you're connecting to.
Client Identity
If the service you connect to uses client certificate authentication, you will need to use a certificate when sending your HTTP request. Generally this certificate will be issued by the service provider. A certificate consists of two parts - a public certificate file and a private key file. HttpCommand
allows you to specify the certificate in two ways:
- provide the file names for the public certificate file and private key file in the
PublicCertFile
andPrivateKeyFile
settings respectively. - specify the
Cert
setting as either:- An instance of Conga's
X509Cert
class - a 2-element vector of the names of the public certificate and private key files
- An instance of Conga's
Other HTTPS Settings
HttpCommand
has two more settings SSLFlags
and Priority
. The default values for these settings will suffice in almost all cases. If you need to use something other than the default, refer to the Conga User Guide.
Further Reading
See the Conga User Guide Chapter 5 for more information on Conga's secure communications and X509Cert
.
A proxy server is a server that acts as an intermediary between HttpCommand
(which makes requests for resources) and the host server that provides those resources. Proxy servers can be used for a number of purposes including load balancing, privacy, and security.
To use a proxy server with HttpCommand
:
- Set
URL
to the address of the host server. Be sure to include the proper scheme (eitherhttp://
orhttps://
). - Set any other settings, for example
Headers
,Params
,Auth
/AuthType
, etc., required for the host server. - Set
ProxyURL
to the address of the proxy server. - If the proxy server requires headers of its own, specify them in
ProxyHeaders
. - If the proxy server itself requires authentication to connect to the host server, specify
ProxyAuth
andProxyAuthType
as appropriate.
See Proxy-related Settings for more information on proxy settings.
Examples
The examples here were developed using a Squid proxy server running in a Docker container on a machine in the author's home network. Squid is a popular proxy server available as free software released under the GNU General Public License.
This particular Squid server is configured to serve only HTTPS requests, such that even though the connection to the proxy server is initialized using HTTP, the connection to the host server is "upgraded" to use HTTPS. HttpCommand
takes care of upgrading the connection.
First, create a new instance of HttpCommand
and, in this case, specify the Command
as 'get'
and the URL
as 'dyalog.com'
. Note that we did not specify a scheme in URL
.
h←HttpCommand.New 'get' 'dyalog.com'
Now specify the URL for the proxy server. In this case, it's the IP address of the machine on the author's network and the default Squid port of 3128. Then run the request.
h.ProxyURL←'192.168.1.123:3128' ⍝ set the proxy server address
⊢r←h.Run
[rc: 0 | msg: Proxy CONNECT response failed | HTTP Status: 403 "Forbidden" | ⍴Data: 3372]
The request failed when the proxy server tried to connect to dyalog.com. Notice that there is some Data
in the response; it turns out that Squid returns some HTML when something fails. We can examine it using HTMLRenderer.
'hr' ⎕WC 'HTMLRenderer' ('HTML' r.Data)
What went wrong? We didn't specify the scheme for dyalog.com. Let's try again...
h.URL←'https://dyalog.com'
h.Run
[rc: 0 | msg: | HTTP Status: 200 "OK" | ⍴Data: 23043]
With the proper scheme specified, the request succeeds.
Considerations
Two aspects that need to be considered when integrating HttpCommand
into your application.
- Are there other components in your application that also use Conga?
- How will your application be deployed?
Use of Conga
If your application has other components that also use Conga, it's advisable that each component have its own Conga "root" created by Conga.Init
. This requires the Conga
namespace from the conga
workspace. The recommended setup is:
- Copy the
Conga
namespace into your workspace. For this example, we will assume you've copiedConga
into the root (#
) namespace. - Explicitly point
HttpCommand
at thisConga
namespace by settingHttpCommand.CongaRef←#.Conga
(or wherever you've copiedConga
). - All other Conga-using components should be similarly pointed at this
Conga
namespace.
When HttpCommand
is initialized it will create a root named 'HttpCommand'
when Conga.Init
is called. Your other components will create their own Conga roots when they also call Conga.Init
. This will ensure that the Conga shared libraries are loaded only once.
Deployment
In addition to the presence of other Conga-using components in your application, you need to consider how your application is deployed.
Dyalog Installation Folder is Available
If the Dyalog installation folder is available, and there are no other components that use Conga, you can use HttpCommand
without any additional configuration. HttpCommand
will copy the Conga
namespace from the conga
workspace in the Dyalog installation and find the shared libraries in the Dyalog APL installation folder.
Dyalog Installation Folder is Not Available
If the Dyalog installation folder is not available, for instance in the case of a runtime application, or a bound or stand-alone executable, then you will need to have a copy of the Conga
namespace in your workspace and either put the Conga shared libraries in the same folder as your executuable or set CongaPath
to the location of the shared libraries.
Ended: Advanced Topics
About ↵
MIT License
Copyright (c) 2021 Dyalog
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Version 5.8
- Added configuration setting
ChunkSize
to enable sending request payloads using "chunked" transfer-encoding.
Version 5.7
- Added shared setting HeaderSubstitution to control if and how environment variables are injected into header names and/or values.
Version 5.6
- Added support for content type "multipart/form-data". See Content Types.
Version 5.5
- Added configuration setting
Secret
which will suppress the display of credentials in the authorization header. This is primarily so that one can demo using authenticated requests without having their credentials displayed in the session. - Added ability for HTTP header names and values to reference environment variables by enclosing the environment variable name in % (e.g.
%MyPassword%
). This provides additional security by reducing the need to store sensitive or variable information inline. This is particularly useful when settingAuth
.
Version 5.4
- Added function
IsOK
to result namespace.
Version 5.3
- Added
BaseURL
to make it easier to issue multiple requests to a common host. - Request header functions return shy result of new Headers array
- Better error trapping for invalidly formatted headers
Version 5.2
Version 5.1
- Added proxy server support. See Proxy-related Settings and Using a Proxy Server.
-
Changed how
HttpCommand
attempts to determine payload Content-Type if the user has not specified it.
Prior behavior was to always treat it asx-www-form-urlencoded
.
Now,HttpCommand
will use a Content-Type ofapplication/json;charset=utf-8
if the payload either:- is simple and looks like JSON
- is a set of name/value pairs
To avoid having
HttpCommand
"guess" improperly, setContent-Type
explicitly. -
If
Auth
is either a vector in form'userid:password'
or a 2-element vector('userid' 'password')
andAuthType
is either unspecified or'basic'
,HttpCommand
will properlyBase64Encode
the credentials for HTTP Basic authentication.
Version 5.0
- The major version bump from 4 to 5 was due to:
- swapping the meaning for the
Timeout
andWaitTime
settings. PreviouslyTimeout
was used to indicate how long Conga'sWait
function would wait for a response andWaitTime
was how longHttpCommand
would wait for a complete response before timing out. - return codes and messages were normalized
- swapping the meaning for the
- Added new
Auth
andAuthType
settings to more easily support token-based authentication. - Removed half-implemented support for streaming
- Added
GetHeader
function to result namespace - More complete setting checking
- Better handling of relative redirections
- New documentation