conductor-oss / conductor-oss/conductor-cli
Conductor CLI sends duplicate Accept and Content-Type headers across multiple commands
- Dominant language
- Go
- Stars
- 11
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Description
## Description
The Conductor CLI generates HTTP requests containing duplicate `Accept` and `Content-Type` headers across multiple commands.
This is not specific to `workflow create`. The issue appears to be in the shared HTTP request construction used by the CLI / Conductor Go SDK.
Observed headers:
```http
Accept: application/json
Accept: application/json
Content-Type: application/json
Content-Type: application/json
```
Expected:
```http
Accept: application/json
Content-Type: application/json
```
The problem can be reproduced locally using a raw TCP listener, without requiring a Conductor server.
## Affected commands
The behavior is observed across commands including:
```bash
conductor workflow create dummy_set_1.json
```
Create a new workflow definition from JSON.
```bash
conductor workflow update dummy_set_0.json
```
Update an existing workflow definition from JSON.
```bash
conductor workflow start --workflow dummy_set_1
```
Start a workflow.
```bash
conductor workflow rerun
```
Rerun an existing workflow.
```bash
conductor task create
```
Create a task definition.
```bash
conductor task update
```
Update a task definition.
```bash
conductor task update-execution \
--workflow-id \
--task-ref-name \
--status COMPLETED \
--output '{"result":"ok"}'
```
Update a task execution.
Since these commands use different API endpoints but exhibit the same behavior, the issue appears to be in the common HTTP client/request layer rather than in an individual command implementation.
## Steps to reproduce
Start a local TCP listener:
```bash
nc -l 8080
```
Configure the CLI:
```bash
export CONDUCTOR_SERVER_URL=http://localhost:8080/api
```
Run any command that sends an HTTP request with a JSON body, for example:
```bash
conductor workflow create dummy_set_1.json
```
The raw request captured by `nc` contains:
```http
POST /api/metadata/workflow?overwrite=true HTTP/1.1
Host: localhost:8080
User-Agent: Go-http-client/1.1
Content-Length: 898
Accept: application/json
Accept: application/json
Accept-Encoding: gzip
Content-Type: application/json
Content-Type: application/json
```
The important part is:
```http
Accept: application/json
Accept: application/json
Content-Type: application/json
Content-Type: application/json
```
The same duplicate-header behavior can be checked against the other CLI commands listed above.
## Expected behavior
Each HTTP request should contain only one `Accept` header and one `Content-Type` header:
```http
Accept: application/json
Content-Type: application/json
```
## Actual behavior
The CLI sends duplicate values:
```http
Accept: application/json
Accept: application/json
Content-Type: application/json
Content-Type: application/json
```
## Why this appears to be a shared HTTP client issue
The affected commands call different workflow/task APIs, but all go through the shared Conductor Go SDK HTTP request implementation.
The SDK request path sets request-specific headers such as:
```go
headers["Content-Type"] = cType
headers["Accept"] = "application/json"
```
The default HTTP settings also contain:
```go
Headers: map[string]string{
"Content-Type": "application/json",
"Accept": "application/json",
"Accept-Encoding": "gzip",
},
```
When the request is prepared, request-specific headers are first installed using:
```go
for h, v := range headerParams {
headers.Set(h, v)
}
```
The default HTTP headers are then appended using:
```go
for header, value := range h.httpSettings.Headers {
localVarRequest.Header.Add(header, value)
}
```
This appears to result in the same logical header being inserted twice.
Conceptually:
```text
Request-specific headers
|
+-- Accept: application/json
+-- Content-Type: application/json
|
v
Default HttpSettings headers
|
+-- Accept: application/json
+-- Content-Type: application/json
|
v
Header.Add(...)
|
v
Final HTTP request
Accept: application/json
Accept: application/json
Content-Type: application/json
Content-Type: application/json
```
Because this code is shared, any CLI operation passing through the same request path can potentially emit duplicate headers.
## Impact
This affects multiple Conductor CLI operations, not just workflow registration.
Examples include:
```text
Workflow metadata APIs
- workflow create
- workflow update
Workflow execution APIs
- workflow start
- workflow rerun
Task metadata APIs
- task create
- task update
Task execution APIs
- task update-execution
```
HTTP servers, gateways, proxies, or libraries that strictly process singleton HTTP headers may reject or normalize the duplicate values.
For example, two `Content-Type` fields may become:
```http
Content-Type: application/json,application/json
```
which is not a valid MIME type for parsers expecting a single media type.
## Local proof
The duplicate headers are present before the request reaches any Conductor server.
This can be demonstrated with:
```text
Conductor CLI
|
v
nc -l 8080
```
and observing:
```http
Accept: application/json
Accept: application/json
Content-Type: application/json
Content-Type: application/json
```
Therefore this is reproducible purely from the client-side HTTP request emitted by the CLI.
## Possible fix
The shared HTTP request implementation should avoid appending a header when the same header is already present.
For example, instead of:
```go
for header, value := range h.httpSettings.Headers {
localVarRequest.Header.Add(header, value)
}
```
one option would be:
```go
for header, value := range h.httpSettings.Headers {
if localVarRequest.Header.Get(header) == "" {
localVarRequest.Header.Set(header, value)
}
}
```
Another option, if configured HTTP settings should override request defaults, would be:
```go
for header, value := range h.httpSettings.Headers {
localVarRequest.Header.Set(header, value)
}
```
Alternatively, `Accept` and `Content-Type` could be removed from the global default headers if they are already set in the request-specific execution path.
The desired behavior should ensure these headers appear once:
```http
Accept: application/json
Content-Type: application/json
```
## Summary
The issue appears to be generic across the Conductor CLI:
```text
CLI command
|
v
Conductor Go SDK
|
+-- request-specific headers
| Accept: application/json
| Content-Type: application/json
|
+-- default HttpSettings headers
| Accept: application/json
| Content-Type: application/json
|
+-- Header.Add(...)
|
v
Duplicate headers emitted
```
The issue is reproducible locally with `nc` and affects multiple workflow and task commands.
Could the shared HTTP request construction be updated so singleton headers such as `Accept` and `Content-Type` are emitted only once?
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the shared Conductor Go SDK HTTP request construction described in the issue, comparing request-specific headers with HttpSettings.Headers and Header.Add. Reproduce the behavior with nc and a JSON-body command such as workflow create; done when affected requests contain one Accept and one Content-Type header.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100