Skip to content
This repository was archived by the owner on Dec 18, 2025. It is now read-only.

Enabled ability for users to specify customer headers - for example x-forwarded-for#681

Merged
pingu2k4 merged 2 commits into
devfrom
feature/allos-custom-headers
Mar 6, 2025
Merged

Enabled ability for users to specify customer headers - for example x-forwarded-for#681
pingu2k4 merged 2 commits into
devfrom
feature/allos-custom-headers

Conversation

@pingu2k4
Copy link
Copy Markdown
Contributor

@pingu2k4 pingu2k4 commented Mar 6, 2025

Changes

  • Enabled ability for users to specify customer headers - for example x-forwarded-for

Issue

Categorise the PR

  • feature
  • bug
  • docs
  • security
  • meta
  • patch
  • minor
  • major

Description by Korbit AI

What change is being made?

Enable users to specify custom headers, such as x-forwarded-for, in requests by implementing AppwriteRequestContext and AppwriteHeaderScope for managing headers, and updating the header handlers in the client and server projects to incorporate these custom headers.

Why are these changes being made?

These changes allow for greater flexibility in request handling by permitting users to add and manage custom headers dynamically, which is essential for supporting scenarios like forwarding header information in HTTP requests. This design provides an easy-to-use, encapsulated way to manage headers within a defined scope, allowing for easy integration into existing workflows.

Is this description stale? Ask me to generate a new description by commenting /korbit-generate-pr-description

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 6, 2025

Code Coverage

Package Line Rate Branch Rate Complexity Health
PinguApps.Appwrite.Client 98% 97% 153
PinguApps.Appwrite.Server 98% 94% 161
PinguApps.Appwrite.Shared 99% 99% 1439
Summary 99% (3880 / 3934) 98% (753 / 767) 1753

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 6, 2025

Test Results

3 727 tests  ±0   3 727 ✅ ±0   55s ⏱️ ±0s
    3 suites ±0       0 💤 ±0 
    3 files   ±0       0 ❌ ±0 

Results for commit 9738fe4. ± Comparison against base commit 2aec8c9.

This pull request removes 339 and adds 339 tests. Note that renamed tests count towards both.
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ CreateUserJwt_ShouldReturnSuccess_WhenApiCallSucceeds(request: CreateUserJwtRequest { Duration = 1800, SessionId = "67c45cb5001c7f9e2b5f", UserId = "67c45cb5001c75f043f9", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ CreateUserJwt_ShouldReturnSuccess_WhenApiCallSucceeds(request: CreateUserJwtRequest { Duration = null, SessionId = null, UserId = "67c45cb5001c5ce1cb7c", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserLogs_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserLogsRequest { Queries = null, UserId = "67c45cb5001c79c4cfa5", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserLogs_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserLogsRequest { Queries = null, UserId = "67c45cb5001c7a661b4e", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserTargets_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserTargetsRequest { Queries = null, UserId = "67c45cb5001c73e1a9bd", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserTargets_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserTargetsRequest { Queries = null, UserId = "67c45cb5001c7b48cac6", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ UpdateUserLabels_ShouldReturnSuccess_WhenApiCallSucceeds(request: UpdateUserLabelsRequest { Labels = ["label1", "label2"], UserId = "67c45cb5001c745e7c83", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ UpdateUserLabels_ShouldReturnSuccess_WhenApiCallSucceeds(request: UpdateUserLabelsRequest { Labels = ["label3", "label4"], UserId = "67c45cb5001c70d16fd9", ValidationContext = None })
PinguApps.Appwrite.Shared.Tests.Requests.Account.CreatePushTargetRequestTests ‑ IsValid_WithInvalidData_ReturnsFalse(request: CreatePushTargetRequest { Identifier = "", ProviderId = "provider123", TargetId = "67c45cb4003acc39535e", ValidationContext = None })
PinguApps.Appwrite.Shared.Tests.Requests.Account.CreatePushTargetRequestTests ‑ IsValid_WithInvalidData_ReturnsFalse(request: CreatePushTargetRequest { Identifier = null, ProviderId = "provider123", TargetId = "67c45cb4003ac00f8517", ValidationContext = None })
…
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ CreateUserJwt_ShouldReturnSuccess_WhenApiCallSucceeds(request: CreateUserJwtRequest { Duration = 1800, SessionId = "67c9d2160001ac36ab93", UserId = "67c9d2160001a2e1c001", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ CreateUserJwt_ShouldReturnSuccess_WhenApiCallSucceeds(request: CreateUserJwtRequest { Duration = null, SessionId = null, UserId = "67c9d21600018ec89ef4", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserLogs_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserLogsRequest { Queries = null, UserId = "67c9d2160001a66e428c", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserLogs_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserLogsRequest { Queries = null, UserId = "67c9d2160001aa283618", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserTargets_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserTargetsRequest { Queries = null, UserId = "67c9d2160001a526d086", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ ListUserTargets_ShouldReturnSuccess_WhenApiCallSucceeds(request: ListUserTargetsRequest { Queries = null, UserId = "67c9d2160001aaa4e4e6", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ UpdateUserLabels_ShouldReturnSuccess_WhenApiCallSucceeds(request: UpdateUserLabelsRequest { Labels = ["label1", "label2"], UserId = "67c9d2160001a7457b71", ValidationContext = None })
PinguApps.Appwrite.Server.Tests.Clients.Users.UsersClientTests ‑ UpdateUserLabels_ShouldReturnSuccess_WhenApiCallSucceeds(request: UpdateUserLabelsRequest { Labels = ["label3", "label4"], UserId = "67c9d2160001a5b4a191", ValidationContext = None })
PinguApps.Appwrite.Shared.Tests.Requests.Account.CreatePushTargetRequestTests ‑ IsValid_WithInvalidData_ReturnsFalse(request: CreatePushTargetRequest { Identifier = "", ProviderId = "provider123", TargetId = "67c9d2150009c3042829", ValidationContext = None })
PinguApps.Appwrite.Shared.Tests.Requests.Account.CreatePushTargetRequestTests ‑ IsValid_WithInvalidData_ReturnsFalse(request: CreatePushTargetRequest { Identifier = null, ProviderId = "provider123", TargetId = "67c9d2150009c50fb6da", ValidationContext = None })
…

@pingu2k4 pingu2k4 merged commit 690074d into dev Mar 6, 2025
Copy link
Copy Markdown

@korbit-ai korbit-ai Bot left a comment

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Fix Detected
Error Handling Missing null check in header key access ▹ view
Functionality Unsealed Dispose Method ▹ view
Functionality Unsafe Header Value Validation ▹ view
Readability Unclear tuple field names ▹ view
Readability Overly verbose variable declarations ▹ view
Files scanned
File Path Reviewed
src/PinguApps.Appwrite.Shared/Constants.cs
src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs
src/PinguApps.Appwrite.Server/Handlers/HeaderHandler.cs
src/PinguApps.Appwrite.Shared/AppwriteRequestContext.cs
src/PinguApps.Appwrite.Shared/AppwriteHeaderScope.cs

Explore our documentation to understand the languages and file types we support and the files we ignore.

Need a new review? Comment /korbit-review on this PR and I'll review your latest changes.

Korbit Guide: Usage and Customization

Interacting with Korbit

  • You can manually ask Korbit to review your PR using the /korbit-review command in a comment at the root of your PR.
  • You can ask Korbit to generate a new PR description using the /korbit-generate-pr-description command in any comment on your PR.
  • Too many Korbit comments? I can resolve all my comment threads if you use the /korbit-resolve command in any comment on your PR.
  • On any given comment that Korbit raises on your pull request, you can have a discussion with Korbit by replying to the comment.
  • Help train Korbit to improve your reviews by giving a 👍 or 👎 on the comments Korbit posts.

Customizing Korbit

  • Check out our docs on how you can make Korbit work best for you and your team.
  • Customize Korbit for your organization through the Korbit Console.

Current Korbit Configuration

General Settings
Setting Value
Review Schedule Automatic excluding drafts
Max Issue Count 10
Automatic PR Descriptions
Issue Categories
Category Enabled
Documentation
Logging
Error Handling
Readability
Design
Performance
Security
Functionality

Feedback and Support

Note

Korbit Pro is free for open source projects 🎉

Looking to add Korbit to your team? Get started with a free 2 week trial here

/// </summary>
public static void AddHeader(string key, string value)
{
CurrentHeaders[key] = value;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing null check in header key access category Error Handling

Tell me more
What is the issue?

The AddHeader method does not handle the case where key is null, which could throw a NullReferenceException when used as a dictionary key.

Why this matters

Dictionary operations with null keys will throw exceptions at runtime, potentially causing application crashes in production.

Suggested change ∙ Feature Preview

Add null check and throw ArgumentNullException for better error handling:

public static void AddHeader(string key, string value)
{
    if (key == null)
    {
        throw new ArgumentNullException(nameof(key));
    }
    CurrentHeaders[key] = value;
}

Report a problem with this comment

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +44 to +56
public void Dispose()
{
foreach (var entry in _originalState)
{
var key = entry.Key;
var (hadValue, oldValue) = entry.Value;

if (hadValue)
AppwriteRequestContext.AddHeader(key, oldValue);
else
AppwriteRequestContext.CurrentHeaders.Remove(key);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unsealed Dispose Method category Functionality

Tell me more
What is the issue?

The Dispose method is not marked as sealed, which could lead to incorrect header restoration if a derived class overrides Dispose without calling base.Dispose().

Why this matters

If a derived class improperly overrides Dispose, the original header values won't be restored, potentially causing request header state corruption in subsequent operations.

Suggested change ∙ Feature Preview

Mark the Dispose method as sealed to prevent inheritance issues:

public sealed override void Dispose()
{
    foreach (var entry in _originalState)
    {
        var key = entry.Key;
        var (hadValue, oldValue) = entry.Value;

        if (hadValue)
            AppwriteRequestContext.AddHeader(key, oldValue);
        else
            AppwriteRequestContext.CurrentHeaders.Remove(key);
    }
}

Report a problem with this comment

💬 Looking for more details? Reply to this comment to chat with Korbit.


foreach (var header in AppwriteRequestContext.CurrentHeaders)
{
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unsafe Header Value Validation category Functionality

Tell me more
What is the issue?

Using TryAddWithoutValidation could allow invalid or malformed header values to be added to the request, potentially causing issues with the HTTP request.

Why this matters

Invalid header values could cause the request to fail or be rejected by the server, leading to runtime errors that would be difficult to diagnose.

Suggested change ∙ Feature Preview

Use proper header validation and handle failures:

foreach (var header in AppwriteRequestContext.CurrentHeaders)
{
    if (!_protectedHeaders.Contains(header.Key, StringComparer.OrdinalIgnoreCase))
    {
        try
        {
            request.Headers.Add(header.Key, header.Value);
        }
        catch (InvalidOperationException ex)
        {
            // Log the error or handle invalid headers appropriately
            // Could throw a custom exception or skip the invalid header
        }
    }
}

Report a problem with this comment

💬 Looking for more details? Reply to this comment to chat with Korbit.


public class AppwriteHeaderScope : IDisposable
{
private readonly Dictionary<string, (bool hadValue, string oldValue)> _originalState = [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unclear tuple field names category Readability

Tell me more
What is the issue?

The tuple field names 'hadValue' and 'oldValue' create indirect naming that makes the code harder to follow. More descriptive names would better convey their purpose.

Why this matters

Using more semantic names would make it immediately clear what these values represent in the context of header state management.

Suggested change ∙ Feature Preview
private readonly Dictionary<string, (bool headerExists, string previousValue)> _originalState = [];

Report a problem with this comment

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +44 to +49
public void Dispose()
{
foreach (var entry in _originalState)
{
var key = entry.Key;
var (hadValue, oldValue) = entry.Value;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overly verbose variable declarations category Readability

Tell me more
What is the issue?

The deconstruction of the dictionary entry creates unnecessary variable assignments that add visual noise.

Why this matters

Multiple intermediate variables make the code more verbose without adding clarity. The logic can be simplified while maintaining readability.

Suggested change ∙ Feature Preview
public void Dispose()
{
    foreach (var (headerName, (headerExists, previousValue)) in _originalState)
    {
        if (headerExists)
            AppwriteRequestContext.AddHeader(headerName, previousValue);
        else
            AppwriteRequestContext.CurrentHeaders.Remove(headerName);
    }
}

Report a problem with this comment

💬 Looking for more details? Reply to this comment to chat with Korbit.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant