Skip to content

Add OCO_API_CUSTOM_HEADERS #467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 3, 2025
Merged

Conversation

EmilienMottet
Copy link
Contributor

@EmilienMottet EmilienMottet commented Apr 29, 2025

Description

This pull request implements the feature described in #466 by adding support for custom HTTP headers in API requests via the new OCO_API_CUSTOM_HEADERS configuration option.

Main changes

  • Introduces the OCO_API_CUSTOM_HEADERS environment/config variable.
  • Allows users to set custom HTTP headers (as a JSON object) for all API requests, supporting use cases like custom authentication, corporate proxy headers, and API gateway requirements.

Example usage

oco config set OCO_API_CUSTOM_HEADERS='{"Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ="}'
oco config set OCO_API_CUSTOM_HEADERS='{"X-API-Version": "2", "X-Custom-Header": "value"}'

Additional context

Close #466

Add OCO_API_CUSTOM_HEADERS variable to README, config enum,
and env parsing to allow JSON string of custom headers.
Validate that custom headers are valid JSON in config validator.
Extend AiEngineConfig with customHeaders and pass headers to
OllamaEngine and OpenAiEngine clients when creating requests.
Parse custom headers in utils/engine and warn on invalid format.
Add unit tests to ensure OCO_API_CUSTOM_HEADERS is handled
correctly and merged from env over global config.

This enables users to send additional headers such as
Authorization or tracing headers with LLM API calls.
Copy link
Owner

@di-sukharev di-sukharev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asked for few changes, thank you for contributing! <3

} else {
this.client = new OpenAI({ apiKey: config.apiKey, baseURL: config.baseURL });
// Configuration options for the OpenAI client
const clientOptions: any = {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove comments and any

apiKey: config.apiKey
};

// Add baseURL if present
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comment please

clientOptions.baseURL = config.baseURL;
}

// Add custom headers if present
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comment please

if (config.customHeaders) {
try {
let headers = config.customHeaders;
// If the headers are a string, try to parse them as JSON
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comment please

let customHeaders = {};
if (config.OCO_API_CUSTOM_HEADERS) {
try {
// If it's already an object, no need to parse it
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you move this code to a function with a good semantic name please

if (typeof config.OCO_API_CUSTOM_HEADERS === 'object' && !Array.isArray(config.OCO_API_CUSTOM_HEADERS)) {
customHeaders = config.OCO_API_CUSTOM_HEADERS;
} else {
// Try to parse as JSON
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comment please

@di-sukharev
Copy link
Owner

also please pull latest master and look for failing tests @EmilienMottet, thank you!

Use OpenAI.ClientOptions for stronger typing and clarity
Extract custom headers parsing into parseCustomHeaders util
Simplify getEngine by delegating header parsing to helper
Improve maintainability and reduce code duplication

if (config.customHeaders) {
try {
let headers = config.customHeaders;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could parseCustomHeaders be used here too?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@di-sukharev
Copy link
Owner

added one more comment to reuse the parseCustomHeaders function on one more place and please look into the tests that fail

@di-sukharev
Copy link
Owner

added one more comment to reuse the parseCustomHeaders function on one more place and please look into the tests that fail

@EmilienMottet

@EmilienMottet
Copy link
Contributor Author

Hi @di-sukharev thanks for your review, I make change now :)

- export parseCustomHeaders from src/utils/engine.ts
- use parseCustomHeaders in OpenAiEngine for config.customHeaders
- remove try/catch and inline JSON.parse logic
- update config test to expect headers as object and drop JSON.parse

Centralize header parsing for reuse and simplify engine code
Update tests to match new header format for clarity
@EmilienMottet
Copy link
Contributor Author

Thank you for your review @di-sukharev , tell me if you want more change :)

@EmilienMottet EmilienMottet requested a review from di-sukharev May 3, 2025 08:52
@di-sukharev di-sukharev merged commit f6de2dc into di-sukharev:master May 3, 2025
4 checks passed
});

expect(config).not.toEqual(null);
expect(config.OCO_API_CUSTOM_HEADERS).toEqual({"Authorization": "Bearer token123", "X-Custom-Header": "test-value"});

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "Bearer token123" is used as
authorization header
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Add support for custom HTTP headers in API requests
2 participants