Skip to content

Commit d9adefb

Browse files
committed
--http-probe-cmd-upload http probe flag for uploads and the related --http-probe-cmd-file data format enhancements as well as api spec request data generation enhancements
Signed-off-by: Kyle Quest <[email protected]>
1 parent 3b4705a commit d9adefb

File tree

14 files changed

+807
-107
lines changed

14 files changed

+807
-107
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,9 @@ In the interactive CLI prompt mode you must specify the target image using the `
430430
- `--poststart-compose-svc` - placeholder for now
431431
- `--http-probe` - Enables/disables HTTP probing (ENABLED by default; you have to disable the probe if you don't need it by setting the flag to `false`: `--http-probe=false`)
432432
- `--http-probe-off` - Alternative way to disable HTTP probing
433-
- `--http-probe-cmd` - Additional HTTP probe command [can use this flag multiple times]
433+
- `--http-probe-cmd` - User defined HTTP probe(s) as `[[[[\"crawl\":]PROTO:]METHOD:]PATH]` [can use this flag multiple times]
434434
- `--http-probe-cmd-file` - File with user defined HTTP probe commands
435+
- `--http-probe-cmd-upload` - User defined HTTP probe(s) to submit form data as `[[[[[PROTO:]FORM_FILE_NAME:]FORM_FIELD_NAME:]FILE_OR_GENERATE_TYPE:]PATH]` [can use this flag multiple times
435436
- `--http-probe-start-wait` - Number of seconds to wait before starting HTTP probing
436437
- `--http-probe-retry-count` - Number of retries for each HTTP probe (default value: 5)
437438
- `--http-probe-retry-wait` - Number of seconds to wait before retrying HTTP probe (doubles when target is not ready; default value: 8)
@@ -958,12 +959,14 @@ To configure Docker Desktop to create the default Unix socket open its UI and go
958959

959960
## HTTP PROBE COMMANDS
960961

961-
If the HTTP probe is enabled (note: it is enabled by default) it will default to running `GET /` with HTTP and then HTTPS on every exposed port. You can add additional commands using the `--http-probe-cmd` and `--http-probe-cmd-file` options.
962+
If the HTTP probe is enabled (note: it is enabled by default) it will default to running `GET /` with HTTP and then HTTPS on every exposed port. You can add additional commands using the `--http-probe-cmd`, `--http-probe-cmd-upload` and `--http-probe-cmd-file` options.
962963

963964
If you want to disable HTTP probing set the `--http-probe` flag to false (e.g., `--http-probe=false`). You can also use the `--http-probe-off` flag to do the same (simply use the flag without any parameters).
964965

965966
The `--http-probe-cmd` option is good when you want to specify a small number of simple commands where you select some or all of these HTTP command options: crawling (defaults to false), protocol, method (defaults to GET), resource (path and query string).
966967

968+
The `--http-probe-cmd-upload` option is good when you want to upload a file. The file upload is done using a multipart form data request (the most common way to upload files). The flag value has the following format: `[[[[[PROTO:]FORM_FILE_NAME:]FORM_FIELD_NAME:]FILE_OR_GENERATE_TYPE:]PATH]`. The most basic flag value is a `PATH` (e.g., `--http-probe-cmd-upload /uploadpath`). When no file to upload or data generate instruction is provided a simple text file is generated. The `FILE_OR_GENERATE_TYPE` section can either point to a local file path for the file to upload or it can be one of the data generate instructions: `generate.text`, `generate.text.json`, `generate.image`, `generate.image.png`, `generate.image.jpeg`, `generate.image.gif`. You can specify a custom form field name to use for the request using the `FORM_FIELD_NAME` section (defaults to `file`). You can also specify the file name for the upload using the `FORM_FILE_NAME` section (defaults to `file.data` or the base path of the file name when `FILE_OR_GENERATE_TYPE` points to a local file). The `PROTO` section is used to scope the request to a specific protocol (`http`, `https`, etc). Note that you can also specify an upload command using a JSON record provided with the `--http-probe-cmd-file` flag (see below).
969+
967970
If you only want to use custom HTTP probe command and you don't want the default `GET /` command added to the command list you explicitly provided you'll need to set `--http-probe` to false when you specify your custom HTTP probe command. Note that this inconsistency will be addressed in the future releases to make it less confusing.
968971

969972
Possible field combinations:
@@ -992,9 +995,14 @@ Available HTTP command options:
992995
* `headers` - array of strings with column delimited key/value pairs (e.g., "Content-Type: application/json")
993996
* `body` - request body as a string
994997
* `body_file` - request body loaded from the provided file
998+
* `body_generate` - auto-generate request body using one of the instructions: `generate.text`, `generate.text.json`, `generate.image`, `generate.image.png`, `generate.image.jpeg`, `generate.image.gif`
999+
* `body_is_form` - request body is a multipart form (request data from `body`, `body_file` or `body_generate` will be form encoded)
1000+
* `form_field_name` - form field name to use (for form submissions)
1001+
* `form_file_name` - form file name to use (for form submissions)
9951002
* `username` - username to use for basic auth
9961003
* `password` - password to use for basic auth
9971004
* `crawl` - boolean to indicate if you want to crawl the target (to visit all referenced resources)
1005+
* `fastcgi` - Fast CGI config params (todo: document sub-fields, see code for details)
9981006

9991007
Here's a probe command file example:
10001008

pkg/app/master/command/build/prompt.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ var CommandFlagSuggestions = &command.FlagSuggestions{
5050
{Text: command.FullFlagName(command.FlagHTTPProbeOff), Description: command.FlagHTTPProbeOffUsage},
5151
{Text: command.FullFlagName(command.FlagHTTPProbe), Description: command.FlagHTTPProbeUsage},
5252
{Text: command.FullFlagName(command.FlagHTTPProbeCmd), Description: command.FlagHTTPProbeCmdUsage},
53+
{Text: command.FullFlagName(command.FlagHTTPProbeCmdUpload), Description: command.FlagHTTPProbeCmdUploadUsage},
5354
{Text: command.FullFlagName(command.FlagHTTPProbeCmdFile), Description: command.FlagHTTPProbeCmdFileUsage},
5455
{Text: command.FullFlagName(command.FlagHTTPProbeStartWait), Description: command.FlagHTTPProbeStartWaitUsage},
5556
{Text: command.FullFlagName(command.FlagHTTPProbeRetryCount), Description: command.FlagHTTPProbeRetryCountUsage},

pkg/app/master/command/cliflags.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ const (
111111
FlagHTTPProbeOff = "http-probe-off" //alternative way to disable http probing
112112
FlagHTTPProbeCmd = "http-probe-cmd"
113113
FlagHTTPProbeCmdFile = "http-probe-cmd-file"
114+
FlagHTTPProbeCmdUpload = "http-probe-cmd-upload"
114115
FlagHTTPProbeStartWait = "http-probe-start-wait"
115116
FlagHTTPProbeRetryCount = "http-probe-retry-count"
116117
FlagHTTPProbeRetryWait = "http-probe-retry-wait"
@@ -223,6 +224,7 @@ const (
223224
FlagHTTPProbeUsage = "Enable or disable HTTP probing"
224225
FlagHTTPProbeOffUsage = "Alternative way to disable HTTP probing"
225226
FlagHTTPProbeCmdUsage = "User defined HTTP probe(s) as [[[[\"crawl\":]PROTO:]METHOD:]PATH]"
227+
FlagHTTPProbeCmdUploadUsage = "User defined HTTP probe(s) to submit form data as [[[[[PROTO:]FORM_FILE_NAME:]FORM_FIELD_NAME:]FILE_OR_GENERATE_TYPE:]PATH]"
226228
FlagHTTPProbeCmdFileUsage = "File with user defined HTTP probes"
227229
FlagHTTPProbeStartWaitUsage = "Number of seconds to wait before starting HTTP probing"
228230
FlagHTTPProbeRetryCountUsage = "Number of retries for each HTTP probe"
@@ -610,6 +612,12 @@ var CommonFlags = map[string]cli.Flag{
610612
Usage: FlagHTTPProbeCmdUsage,
611613
EnvVars: []string{"DSLIM_HTTP_PROBE_CMD"},
612614
},
615+
FlagHTTPProbeCmdUpload: &cli.StringSliceFlag{
616+
Name: FlagHTTPProbeCmdUpload,
617+
Value: cli.NewStringSlice(),
618+
Usage: FlagHTTPProbeCmdUploadUsage,
619+
EnvVars: []string{"DSLIM_HTTP_PROBE_CMD_UPLOAD"},
620+
},
613621
FlagHTTPProbeCmdFile: &cli.StringFlag{
614622
Name: FlagHTTPProbeCmdFile,
615623
Value: "",
@@ -946,6 +954,7 @@ func HTTPProbeFlags() []cli.Flag {
946954
func HTTPProbeFlagsBasic() []cli.Flag {
947955
return []cli.Flag{
948956
Cflag(FlagHTTPProbeCmd),
957+
Cflag(FlagHTTPProbeCmdUpload),
949958
Cflag(FlagHTTPProbeCmdFile),
950959
Cflag(FlagHTTPProbeStartWait),
951960
Cflag(FlagHTTPProbeRetryCount),

pkg/app/master/command/clifvgetter.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ func GetHTTPProbes(ctx *cli.Context) ([]config.HTTPProbeCmd, error) {
158158
return nil, err
159159
}
160160

161+
httpProbeCmdUploads, err := ParseHTTPProbeUploads(ctx.StringSlice(FlagHTTPProbeCmdUpload))
162+
if err != nil {
163+
return nil, err
164+
}
165+
166+
if httpProbeCmdUploads != nil {
167+
httpProbeCmds = append(httpProbeCmds, httpProbeCmdUploads...)
168+
}
169+
161170
moreHTTPProbeCmds, err := ParseHTTPProbesFile(ctx.String(FlagHTTPProbeCmdFile))
162171
if err != nil {
163172
return nil, err

pkg/app/master/command/clifvparser.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,133 @@ func ParseHTTPProbes(values []string) ([]config.HTTPProbeCmd, error) {
647647
return probes, nil
648648
}
649649

650+
func ParseHTTPProbeUploads(values []string) ([]config.HTTPProbeCmd, error) {
651+
// FORMAT:
652+
// [[[[[PROTO:]FORM_FILE_NAME:]FORM_FIELD_NAME:]FILE_OR_GENERATE_TYPE:]PATH]
653+
probes := []config.HTTPProbeCmd{}
654+
655+
method := "POST"
656+
for _, raw := range values {
657+
parts := strings.Split(raw, ":")
658+
659+
proto := "http"
660+
resource := "/"
661+
var formFieldName string //use the default from the form processor
662+
var formFileName string //use the default from the form processor
663+
var bodyFile string
664+
var bodyGenerate string
665+
666+
switch len(parts) {
667+
case 1:
668+
// parts[0] - PATH
669+
if parts[0] == "" || !isResource(parts[0]) {
670+
return nil, fmt.Errorf("invalid HTTP probe command resource: %+v", raw)
671+
}
672+
673+
resource = parts[0]
674+
case 2:
675+
// parts[0] - FILE_OR_GENERATE_TYPE
676+
// parts[1] - PATH
677+
if parts[0] != "" {
678+
if strings.HasPrefix(parts[0], "generate.") {
679+
bodyGenerate = parts[0]
680+
} else {
681+
bodyFile = parts[0]
682+
}
683+
}
684+
685+
if parts[1] == "" || !isResource(parts[1]) {
686+
return nil, fmt.Errorf("invalid HTTP probe command resource: %+v", raw)
687+
}
688+
689+
resource = parts[1]
690+
case 3:
691+
// parts[0] - FORM_FIELD_NAME
692+
// parts[1] - FILE_OR_GENERATE_TYPE
693+
// parts[2] - PATH
694+
formFieldName = parts[0]
695+
696+
if parts[1] != "" {
697+
if strings.HasPrefix(parts[1], "generate.") {
698+
bodyGenerate = parts[1]
699+
} else {
700+
bodyFile = parts[1]
701+
}
702+
}
703+
704+
if parts[2] == "" || !isResource(parts[2]) {
705+
return nil, fmt.Errorf("invalid HTTP probe command resource: %+v", raw)
706+
}
707+
708+
resource = parts[2]
709+
case 4:
710+
// parts[0] - FORM_FILE_NAME
711+
// parts[1] - FORM_FIELD_NAME
712+
// parts[2] - FILE_OR_GENERATE_TYPE
713+
// parts[3] - PATH
714+
formFileName = parts[0]
715+
formFieldName = parts[1]
716+
717+
if parts[2] != "" {
718+
if strings.HasPrefix(parts[2], "generate.") {
719+
bodyGenerate = parts[2]
720+
} else {
721+
bodyFile = parts[2]
722+
}
723+
}
724+
725+
if parts[3] == "" || !isResource(parts[3]) {
726+
return nil, fmt.Errorf("invalid HTTP probe command resource: %+v", raw)
727+
}
728+
729+
resource = parts[3]
730+
case 5:
731+
// parts[0] - PROTO
732+
// parts[1] - FORM_FILE_NAME
733+
// parts[2] - FORM_FIELD_NAME
734+
// parts[3] - FILE_OR_GENERATE_TYPE
735+
// parts[4] - PATH
736+
if parts[0] != "" && !isMethod(parts[0]) {
737+
return nil, fmt.Errorf("invalid HTTP probe command method: %+v", raw)
738+
}
739+
740+
formFileName = parts[1]
741+
formFieldName = parts[2]
742+
743+
if parts[3] != "" {
744+
if strings.HasPrefix(parts[3], "generate.") {
745+
bodyGenerate = parts[3]
746+
} else {
747+
bodyFile = parts[3]
748+
}
749+
}
750+
751+
if parts[4] == "" || !isResource(parts[4]) {
752+
return nil, fmt.Errorf("invalid HTTP probe command resource: %+v", raw)
753+
}
754+
755+
resource = parts[4]
756+
default:
757+
return nil, fmt.Errorf("invalid HTTP probe upload command: %s", raw)
758+
}
759+
760+
cmd := config.HTTPProbeCmd{
761+
BodyIsForm: true,
762+
Protocol: proto,
763+
Method: method,
764+
Resource: resource,
765+
BodyFile: bodyFile,
766+
BodyGenerate: bodyGenerate,
767+
FormFieldName: formFieldName,
768+
FormFileName: formFileName,
769+
}
770+
771+
probes = append(probes, cmd)
772+
}
773+
774+
return probes, nil
775+
}
776+
650777
func ParseHTTPProbesFile(filePath string) ([]config.HTTPProbeCmd, error) {
651778
probes := []config.HTTPProbeCmd{}
652779

pkg/app/master/command/profile/prompt.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ var CommandFlagSuggestions = &command.FlagSuggestions{
2525
{Text: command.FullFlagName(command.FlagHTTPProbeOff), Description: command.FlagHTTPProbeOffUsage},
2626
{Text: command.FullFlagName(command.FlagHTTPProbe), Description: command.FlagHTTPProbeUsage},
2727
{Text: command.FullFlagName(command.FlagHTTPProbeCmd), Description: command.FlagHTTPProbeCmdUsage},
28+
{Text: command.FullFlagName(command.FlagHTTPProbeCmdUpload), Description: command.FlagHTTPProbeCmdUploadUsage},
2829
{Text: command.FullFlagName(command.FlagHTTPProbeCmdFile), Description: command.FlagHTTPProbeCmdFileUsage},
2930
{Text: command.FullFlagName(command.FlagHTTPProbeStartWait), Description: command.FlagHTTPProbeStartWaitUsage},
3031
{Text: command.FullFlagName(command.FlagHTTPProbeRetryCount), Description: command.FlagHTTPProbeRetryCountUsage},

pkg/app/master/config/config.go

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -135,75 +135,6 @@ type VolumeMount struct {
135135
Options string
136136
}
137137

138-
const (
139-
ProtoHTTP = "http"
140-
ProtoHTTPS = "https"
141-
ProtoHTTP2 = "http2"
142-
ProtoHTTP2C = "http2c"
143-
ProtoWS = "ws"
144-
ProtoWSS = "wss"
145-
)
146-
147-
func IsProto(value string) bool {
148-
switch strings.ToLower(value) {
149-
case ProtoHTTP,
150-
ProtoHTTPS,
151-
ProtoHTTP2,
152-
ProtoHTTP2C,
153-
ProtoWS,
154-
ProtoWSS:
155-
return true
156-
default:
157-
return false
158-
}
159-
}
160-
161-
// HTTPProbeCmd provides the HTTP probe parameters
162-
type HTTPProbeCmd struct {
163-
Method string `json:"method"`
164-
Resource string `json:"resource"`
165-
Port int `json:"port"`
166-
Protocol string `json:"protocol"`
167-
Headers []string `json:"headers"`
168-
Body string `json:"body"`
169-
BodyFile string `json:"body_file"`
170-
Username string `json:"username"`
171-
Password string `json:"password"`
172-
Crawl bool `json:"crawl"`
173-
174-
FastCGI *FastCGIProbeWrapperConfig `json:"fastcgi,omitempty"`
175-
}
176-
177-
// FastCGI permits fine-grained configuration of the fastcgi RoundTripper.
178-
type FastCGIProbeWrapperConfig struct {
179-
// Root is the fastcgi root directory.
180-
// Defaults to the root directory of the container.
181-
Root string `json:"root,omitempty"`
182-
183-
// The path in the URL will be split into two, with the first piece ending
184-
// with the value of SplitPath. The first piece will be assumed as the
185-
// actual resource (CGI script) name, and the second piece will be set to
186-
// PATH_INFO for the CGI script to use.
187-
SplitPath []string `json:"split_path,omitempty"`
188-
189-
// Extra environment variables.
190-
EnvVars map[string]string `json:"env,omitempty"`
191-
192-
// The duration used to set a deadline when connecting to an upstream.
193-
DialTimeout time.Duration `json:"dial_timeout,omitempty"`
194-
195-
// The duration used to set a deadline when reading from the FastCGI server.
196-
ReadTimeout time.Duration `json:"read_timeout,omitempty"`
197-
198-
// The duration used to set a deadline when sending to the FastCGI server.
199-
WriteTimeout time.Duration `json:"write_timeout,omitempty"`
200-
}
201-
202-
// HTTPProbeCmds is a list of HTTPProbeCmd instances
203-
type HTTPProbeCmds struct {
204-
Commands []HTTPProbeCmd `json:"commands"`
205-
}
206-
207138
// DockerClient provides Docker client parameters
208139
type DockerClient struct {
209140
UseTLS bool
@@ -232,30 +163,6 @@ type ContinueAfter struct {
232163
ContinueChan <-chan struct{}
233164
}
234165

235-
type HTTPProbeOptions struct {
236-
Do bool
237-
Full bool
238-
ExitOnFailure bool
239-
240-
Cmds []HTTPProbeCmd
241-
Ports []uint16
242-
243-
StartWait int
244-
RetryCount int
245-
RetryWait int
246-
247-
CrawlMaxDepth int
248-
CrawlMaxPageCount int
249-
CrawlConcurrency int
250-
CrawlConcurrencyMax int
251-
252-
APISpecs []string
253-
APISpecFiles []string
254-
255-
ProxyEndpoint string
256-
ProxyPort int
257-
}
258-
259166
type AppNodejsInspectOptions struct {
260167
IncludePackages []string
261168
NextOpts NodejsWebFrameworkInspectOptions

0 commit comments

Comments
 (0)