diff --git a/docs/release-notes.md b/docs/release-notes.md index 2f12b06..c944da0 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,3 +1,5 @@ +## Version 5.7 +* Added shared setting [HeaderSubstitution](./request-settings.md#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](./userguide.md#content-types). ## Version 5.5 diff --git a/docs/request-settings.md b/docs/request-settings.md index 51f5977..e2797aa 100644 --- a/docs/request-settings.md +++ b/docs/request-settings.md @@ -1,5 +1,5 @@ Request-related settings are settings you use to specify attributes of the HTTP request that `HttpCommand` will process. -## Settings +## Instance Settings ### `Command` @@ -220,6 +220,57 @@ If AuthType is not set and Auth is set to either a cha logged_in github.com 05-AUG-2022
Description
+## 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 (2 ⎕NQ '.' 'GetEnvironment').

HeaderSubstitution provides a shorthand technique to inject environment variable values into the request's HTTP header names and values. If HeaderSubstitution is '' (the default), no substitution is done. When HeaderSubstitution has a non-empty value, it denotes the beginning and ending delimiteres between which you may use the name of an enviroment variable. If HeaderSubstitution is a single character, that character is used as both the beginning and ending delimiter.

+

You may also use the delimiters in the Auth setting as Auth is used to format the HTTP Authorization header.

+
Default''
Example(s) +For these examples, assume we have an environment variable named "MyVariable" which has a value of '0123456789'.
      HttpCommand.HeaderSubstitution←'' ⍝ no substitutions done
+      h←HttpCommand.New 'get' 'someurl.com'
+      'name' h.SetHeader '%MyVariable%'
+      h.Show
+      GET / HTTP/1.1
+name: %MyVariable%
+Host: someurl.com
+User-Agent: Dyalog-HttpCommand/5.7.0
+Accept: */*
+Accept-Encoding: gzip, deflate
+

Now let's specify a delimiter...

+
      HttpCommand.HeaderSubstitution←'%' ⍝ specify a delimiter
+      h.Show
+GET / HTTP/1.1
+name: 0123456789
+Host: someurl.com
+User-Agent: Dyalog-HttpCommand/5.7.0
+Accept: */*
+Accept-Encoding: gzip, deflate
+
+

The delimiters do not have to be single characters...

+
      HttpCommand.HeaderSubstitution←'env:[' ']' 
+      'name' h.SetHeader 'env:[MyVariable]'
+      h.Show
+GET / HTTP/1.1
+name: 0123456789
+Host: someurl.com
+User-Agent: Dyalog-HttpCommand/5.7.0
+Accept: */*
+Accept-Encoding: gzip, deflate
+

Alternatively, you can use the GetEnv method to retrieve environment variables and/or Dyalog configuration settings.

+
      'name' h.SetHeader GetEnv 'MyAPIKey' 
+
+
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: diff --git a/source/HttpCommand.dyalog b/source/HttpCommand.dyalog index fecffc7..8ffa0de 100644 --- a/source/HttpCommand.dyalog +++ b/source/HttpCommand.dyalog @@ -7,7 +7,7 @@ ∇ r←Version ⍝ Return the current version :Access public shared - r←'HttpCommand' '5.6.0' '2024-03-17' + r←'HttpCommand' '5.7.0' '2024-05-17' ∇ ⍝ Request-related fields @@ -20,6 +20,8 @@ :field public Auth←'' ⍝ authentication string :field public AuthType←'' ⍝ authentication type :field public BaseURL←'' ⍝ base URL to use when making multiple requests to the same host + :field public shared HeaderSubstitution←'' ⍝ delimiters to indicate environment/configuration settings be substituted in headers, set to '' to disable + ⍝ Proxy-related fields - only used if connecting through a proxy server :field public ProxyURL←'' ⍝ address of the proxy server @@ -53,7 +55,6 @@ :field public UseZip←0 ⍝ zip request payload (0-no, 1-use gzip, 2-use deflate) :field public ZipLevel←1 ⍝ default compression level (0-9) :field public shared Debug←0 ⍝ set to 1 to disable trapping, 2 to stop just before creating client - :field public readonly shared ValidFormUrlEncodedChars←'&=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~*+~%' :field Client←'' ⍝ Conga client ID @@ -1355,9 +1356,14 @@ r←Headers ∇ - ∇ hdrs←environment hdrs + ∇ hdrs←environment hdrs;beg;end;escape;hits;regex ⍝ substitute any header names or values that begin with '$env:' with the named environment variable - hdrs←(⍴hdrs)⍴'%[[:alpha:]].*?%'⎕R{GetEnv 1↓¯1↓⍵.Match}⊢,hdrs + :If ~0∊⍴HeaderSubstitution + (beg end)←2⍴HeaderSubstitution + escape←'.^$*+?()[]{\|-'∘{m←∊(1+⍺∊⍨t←⌽⍵)↑¨1 ⋄ t←m\t ⋄ t[⍸~m]←'\' ⋄ ⌽t} ⍝ chars that need escaping in regex + regex←(escape beg),'[[:alpha:]].*?',escape end + hdrs←(⍴hdrs)⍴regex ⎕R{0∊⍴e←GetEnv(≢beg)↓(-≢end)↓⍵.Match:⍵.Match ⋄ e}⊢,hdrs + :EndIf ∇ ∇ hdrs←privatize hdrs