Skip to content

Commit d07c691

Browse files
authored
Resolves #444 - Support regex replacement of URL (#445)
1 parent 4946cda commit d07c691

File tree

3 files changed

+87
-41
lines changed

3 files changed

+87
-41
lines changed

README.md

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
# Elastic Path Composable Commerce Command Line Interface
22

3-
43
## Overview
5-
This project is designed as a tool for power users to interact with the [Elastic Path Composable Commerce API](https://documentation.elasticpath.com/commerce-cloud/docs/api/) via the command line and the project is designed to fill three distinct niches:
4+
5+
This project is designed as a tool for power users to interact with the [Elastic Path Composable Commerce API](https://documentation.elasticpath.com/commerce-cloud/docs/api/) via the command line and the project is designed to fill three distinct
6+
niches:
7+
68
1. Provide a fast way for users familiar with the API to interact with it.
79
2. Provide a simpler way to do scripting with the API (i.e., instead of using curl and creating JSON in the shell)
810
3. Provide a reusable set of scripts for creating data sets with [Runbooks](docs/runbook-development.md).
911

10-
This tool is not meant for new users unfamiliar with the API, new users are highly encouraged to use the [Elastic Path Composable Commerce Postman Collection](https://elasticpath.dev/docs/commerce-cloud/api-overview/test-with-postman-collection) instead of this tool.
12+
This tool is not meant for new users unfamiliar with the API, new users are highly encouraged to use the [Elastic Path Composable Commerce Postman Collection](https://elasticpath.dev/docs/commerce-cloud/api-overview/test-with-postman-collection)
13+
instead of this tool.
1114

1215
Additionally, this tool is not necessarily meant to be a new command line equivalent of Commerce Manager, it should just feel at all times like you are interacting with a JSON based REST API.
1316

@@ -26,6 +29,7 @@ It is highly recommended that new users check out the [Tutorial](docs/tutorial.m
2629
The following is a summary of the main commands, in general you can type `epcc help` to get an updated list and see all commands as well as flags.
2730

2831
#### CRUD Commands
32+
2933
| Command | Description |
3034
|-------------------------------------------------------------|---------------------------------------------------------------------------|
3135
| `epcc get <RESOURCE> [ID] ... [QUERY_PARAM_KEY] [VAL] ...` | Retrieves either a list of objects, or an particular object from the API. |
@@ -43,7 +47,8 @@ The following is a summary of the main commands, in general you can type `epcc h
4347
| `epcc login implicit` | Login to the API using an Implicit Token |
4448
| `epcc login status` | Determine the current state of the login |
4549

46-
#### Debugging Commands
50+
#### Debugging Commands
51+
4752
| Command | Description |
4853
|----------------------------------------------------|------------------------------------------------------------------------------|
4954
| `epcc docs <RESOURCE>` | Open the API docs for a resource in your browser |
@@ -66,21 +71,21 @@ The following is a summary of the main commands, in general you can type `epcc h
6671
1. `--execution-timeout` will control how long the `epcc` process can run before timing out.
6772
2. `--rate-limit` will control the number of requests per second to EPCC.
6873
3. `--max-concurrency` will control the maximum number of concurrent commands that can run simultaneously.
69-
* This differs from the rate limit in that if a request takes 2 seconds, a rate limit of 3 will allow 6 requests in flight at a time, whereas `--max-concurrency` would limit you to 3. A higher value will slow down initial start time.
74+
* This differs from the rate limit in that if a request takes 2 seconds, a rate limit of 3 will allow 6 requests in flight at a time, whereas `--max-concurrency` would limit you to 3. A higher value will slow down initial start time.
7075

7176
#### Headers
7277

7378
Headers can be set in one of three ways, depending on what is most convenient
7479

7580
1. Via the `-H` argument.
76-
* This header will be one time only.
81+
* This header will be one time only.
7782
2. Via the `EPCC_CLI_HTTP_HEADER_0` environment variable.
78-
* This header will be always be set.
83+
* This header will be always be set.
7984
3. Via the `epcc header set`
80-
* These headers will be set in the current profile and will stay until unset. You can see what headers are set with `epcc headers status`
81-
* Headers set this way support aliases.
82-
* You can also additionally group headers into groups with `--group` and then clear all headers with `epcc headers clear <GROUP>`
83-
85+
* These headers will be set in the current profile and will stay until unset. You can see what headers are set with `epcc headers status`
86+
* Headers set this way support aliases.
87+
* You can also additionally group headers into groups with `--group` and then clear all headers with `epcc headers clear <GROUP>`
88+
8489
### Configuration
8590

8691
#### Via Prompts
@@ -91,16 +96,18 @@ Run the `epcc configure` and it will prompt you for the required settings, when
9196

9297
The following environment variables can be set up to control which environment and store to use with the EPCC CLI.
9398

94-
| Environment Variable | Description |
95-
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
96-
| EPCC_API_BASE_URL | This is the API base URL which can be retrieved via CM. |
97-
| EPCC_BETA_API_FEATURES | This variable allows you to set [Beta Headers](https://documentation.elasticpath.com/commerce-cloud/docs/api/basics/api-contract.html#beta-apis) for all API calls. |
98-
| EPCC_CLI_HTTP_HEADER_**N** | Setting any environment variable like this (where N is a number) will cause it's value to be parsed and added to all HTTP headers (e.g., `EPCC_CLI_HTTP_HEADER_0=Cache-Control: no-cache` will add `Cache-Control: no-cache` as a header). FYI, the surprising syntax is due to different encoding rules. You can also specify headers using `-H` or `epcc headers` |
99-
| EPCC_CLI_SUPPRESS_NO_AUTH_MESSAGES | This will supress warning messages about not being authenticated or logged out |
100-
| EPCC_CLIENT_ID | This is the Client ID which can be retrieved via CM. |
101-
| EPCC_CLIENT_SECRET | This is the Client Secret which can be retrieved via CM. |
102-
| EPCC_PROFILE | A profile name that allows for an independent session and isolation (e.g., distinct histories) |
103-
| EPCC_RUNBOOK_DIRECTORY | A directory that will be scanned for runbook, a runbook ends with `.epcc.yml` |
99+
| Environment Variable | Description |
100+
|-------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
101+
| EPCC_API_BASE_URL | This is the API base URL which can be retrieved via CM. |
102+
| EPCC_BETA_API_FEATURES | This variable allows you to set [Beta Headers](https://documentation.elasticpath.com/commerce-cloud/docs/api/basics/api-contract.html#beta-apis) for all API calls. |
103+
| EPCC_CLI_HTTP_HEADER_**N** | Setting any environment variable like this (where N is a number) will cause it's value to be parsed and added to all HTTP headers (e.g., `EPCC_CLI_HTTP_HEADER_0=Cache-Control: no-cache` will add `Cache-Control: no-cache` as a header). FYI, the surprising syntax is due to different encoding rules. You can also specify headers using `-H` or `epcc headers`. |
104+
| EPCC_CLI_SUPPRESS_NO_AUTH_MESSAGES | This will supress warning messages about not being authenticated or logged out |
105+
| EPCC_CLI_URL_MATCH_REGEXP_**N** | Setting this value causes the _path_ section of a URL to be matched and replaced with a corresponding value from the `EPCC_CLI_URL_MATCH_SUBSTITION_**N**` header, if not set the empty string is used. |
106+
| EPCC_CLI_URL_MATCH_SUBSTITION_**N** | The replacement string to use when a match is found. Capture groups and back references are supported (see [ReplaceAllString](https://pkg.go.dev/regexp#Regexp.ReplaceAllString)). |
107+
| EPCC_CLIENT_ID | This is the Client ID which can be retrieved via CM. |
108+
| EPCC_CLIENT_SECRET | This is the Client Secret which can be retrieved via CM. |
109+
| EPCC_PROFILE | A profile name that allows for an independent session and isolation (e.g., distinct histories). |
110+
| EPCC_RUNBOOK_DIRECTORY | A directory that will be scanned for runbook, a runbook ends with `.epcc.yml`. |
104111

105112
It is recommended to set EPCC_API_BASE_URL, EPCC_CLIENT_ID, and EPCC_CLIENT_SECRET to be able to interact with most things in the CLI.
106113

@@ -123,7 +130,9 @@ You will need to start a new shell for this setup to take effect
123130

124131
#### Bash
125132

126-
You will need to have the [bash-completion](https://github.com/scop/bash-completion) (e.g., [Ubuntu](https://packages.ubuntu.com/search?keywords=bash-completion), [Arch](https://archlinux.org/packages/extra/any/bash-completion/), [Gentoo](https://packages.gentoo.org/packages/app-shells/bash-completion)) package installed, and restart your bash session.
133+
You will need to have the [bash-completion](https://github.com/scop/bash-completion) (
134+
e.g., [Ubuntu](https://packages.ubuntu.com/search?keywords=bash-completion), [Arch](https://archlinux.org/packages/extra/any/bash-completion/), [Gentoo](https://packages.gentoo.org/packages/app-shells/bash-completion)) package installed, and restart
135+
your bash session.
127136

128137
To load completions for each session, execute once:
129138

@@ -157,7 +166,6 @@ To load completions for each session, execute once:
157166

158167
`epcc completion fish > ~/.config/fish/completions/epcc.fish`
159168

160-
161169
## Tips
162170

163171
### JQ Output
@@ -207,6 +215,7 @@ this is based on [GoJQ which has a number of differences](https://github.com/itc
207215
The `--retry-while-jq` argument can be used to wait for certain conditions to happen (e.g., a catalog publication, or an eventual consistency condition).
208216

209217
For example:
218+
210219
```bash
211220
epcc get pcm-catalog-release --retry-while-jq '.data.meta.release_status != "PUBLISHED"' name=Ranges_Catalog last_release
212221
```
@@ -219,6 +228,7 @@ this is based on [GoJQ which has a number of differences](https://github.com/itc
219228
```bash
220229
epcc runbooks run misc get-store-info
221230
```
231+
222232
## Development Tips
223233

224234
### Fast rebuilds

external/httpclient/httpclient.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"net/http/httputil"
1919
"net/url"
2020
"os"
21+
"regexp"
2122
"runtime"
2223
"sort"
2324
"strings"
@@ -29,6 +30,12 @@ var RawHeaders []string
2930

3031
const EnvNameHttpPrefix = "EPCC_CLI_HTTP_HEADER_"
3132

33+
const EnvUrlMatch = "EPCC_CLI_URL_MATCH_REGEXP_(\\d+)"
34+
35+
const EnvUrlMatchPrefix = "EPCC_CLI_URL_MATCH_SUBSTITUTION_"
36+
37+
var urlSubstitions = map[*regexp.Regexp]string{}
38+
3239
var httpHeaders = map[string]string{}
3340

3441
var DontLog2xxs = false
@@ -43,6 +50,9 @@ var stats = struct {
4350

4451
func init() {
4552
stats.respCodes = make(map[int]int)
53+
54+
urlMatchRegexp := regexp.MustCompile(EnvUrlMatch)
55+
4656
for _, env := range os.Environ() {
4757
splitEnv := strings.SplitN(env, "=", 2)
4858

@@ -58,6 +68,18 @@ func init() {
5868
httpHeaders[headersSplit[0]] = headersSplit[1]
5969
}
6070
}
71+
72+
if groups := urlMatchRegexp.FindStringSubmatch(envName); groups != nil {
73+
if groups != nil {
74+
r, err := regexp.Compile(envValue)
75+
76+
if err != nil {
77+
log.Warnf("Environment variable %s has a malformed regex and substition cannot be performed, %v", env, err)
78+
} else {
79+
urlSubstitions[r] = os.Getenv(EnvUrlMatchPrefix + groups[1])
80+
}
81+
}
82+
}
6183
}
6284
}
6385
}
@@ -181,7 +203,21 @@ func doRequestInternal(ctx context.Context, method string, contentType string, p
181203
log.Fatalf("Error when parsing default host, this is a bug, %s", config.DefaultUrl)
182204
}
183205
}
206+
207+
origPath := path
208+
209+
for r, substitution := range urlSubstitions {
210+
if r.MatchString(path) {
211+
path = r.ReplaceAllString(path, substitution)
212+
}
213+
}
214+
215+
if origPath != path {
216+
log.Tracef("URL Replacement transformed %s to %s", origPath, path)
217+
}
218+
184219
reqURL.Path = path
220+
185221
reqURL.RawQuery = query
186222

187223
var bodyBuf []byte

0 commit comments

Comments
 (0)