Skip to content

refactor: move to traefik paerser for label parsing#197

Merged
steveiliop56 merged 4 commits intomainfrom
refactor/paerser
Jun 15, 2025
Merged

refactor: move to traefik paerser for label parsing#197
steveiliop56 merged 4 commits intomainfrom
refactor/paerser

Conversation

@steveiliop56
Copy link
Copy Markdown
Member

@steveiliop56 steveiliop56 commented Jun 15, 2025

Summary by CodeRabbit

  • Chores

    • Updated base Docker images for frontend and development environments to newer versions.
    • Added a new backend dependency to improve label parsing.
  • Refactor

    • Replaced the previous label structure with a more flexible and structured format for handling authentication and OAuth labels.
    • Improved error handling and parsing of container labels.
    • Centralized and streamlined header parsing for HTTP responses.
  • Tests

    • Updated and renamed tests to reflect changes in label parsing logic.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 15, 2025

Warning

Rate limit exceeded

@steveiliop56 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 39 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between aeb93da and 6157f75.

📒 Files selected for processing (2)
  • internal/docker/docker.go (4 hunks)
  • internal/utils/utils.go (2 hunks)

Walkthrough

This update refactors the handling and structure of Docker container labels in the codebase. It introduces new structured types for labels, replaces manual label parsing with a declarative decoding approach, updates related function signatures, improves error handling, and updates Dockerfile base images. Associated tests and constants are adjusted or removed to align with the new label structure.

Changes

Files/Groups Change Summary
Dockerfile, frontend/Dockerfile.dev Updated Bun base image versions for frontend and development Dockerfiles.
go.mod Added new indirect dependency: github.com/traefik/paerser v0.2.2.
internal/types/config.go Added new OAuthLabels and Labels struct types for structured label handling.
internal/types/types.go, internal/constants/... Removed TinyauthLabels struct and TinyauthLabels constant slice.
internal/auth/auth.go Updated method signatures and label field accesses to use new Labels struct.
internal/docker/docker.go Changed GetLabels method to use new Labels struct, updated error handling and label extraction logic.
internal/utils/utils.go Removed manual label parsing function; added ParseHeaders and new GetLabels using parser.Decode.
internal/handlers/handlers.go Changed header handling to use ParseHeaders for setting response headers.
internal/utils/utils_test.go Updated and renamed test to match new label structure and function signatures.

Sequence Diagram(s)

sequenceDiagram
    participant Docker as Docker Engine
    participant App as Application
    participant Utils as utils.GetLabels
    participant Parser as parser.Decode

    App->>Docker: Get container labels
    Docker-->>App: Return label map
    App->>Utils: GetLabels(label map)
    Utils->>Parser: Decode(label map, Labels struct)
    Parser-->>Utils: Labels struct or error
    Utils-->>App: Labels struct or error
Loading

Poem

A hop, a skip, a label anew,
Structs and headers, now clear in view.
Old constants gone, new types arise,
Parsing with care, no more disguise.
From Docker to code, the flow is neat—
This bunny’s work is now complete!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@steveiliop56 steveiliop56 added this to the v3.5.0 milestone Jun 15, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (9)
frontend/Dockerfile.dev (1)

1-1: Consider pinning the image by digest for reproducible builds.

Bumping to oven/bun:1.2.16-alpine is fine, but using a digest (@sha256:<hash>) guarantees the exact layer set and guards against unexpected retags.

Dockerfile (1)

2-2: Same reproducibility concern as Dockerfile.dev.

Pin the Bun builder stage to a digest so CI / local builds always run with the exact same bits.

-FROM oven/bun:1.2.16-alpine AS frontend-builder
+FROM oven/bun:1.2.16-alpine@sha256:<expected-hash> AS frontend-builder
internal/handlers/handlers.go (1)

240-244: Duplicate logic – extract into a helper to avoid divergence.

The block is identical to lines 117-121. Factor it into a small helper (e.g. setExtraHeaders(c *gin.Context, hdrs []string)) to keep behaviour in sync and shrink this very large handler.

internal/types/config.go (1)

96-108: Add explicit struct tags to future-proof label decoding.

github.com/traefik/paerser relies on struct tags (label:"...") or field names to map keys. Relying on bare field names assumes label keys will always match the Go identifier case-insensitively (e.g. Headers). Explicit tags make the mapping obvious and resilient to renames:

-type OAuthLabels struct {
-    Whitelist string
-    Groups    string
+type OAuthLabels struct {
+    Whitelist string `label:"oauth.whitelist"`
+    Groups    string `label:"oauth.groups"`
 }
 
-type Labels struct {
-    Users   string
-    Allowed string
-    Headers []string
-    OAuth   OAuthLabels
+type Labels struct {
+    Users   string      `label:"users"`
+    Allowed string      `label:"allowed"`
+    Headers []string    `label:"headers"`
+    OAuth   OAuthLabels `label:"oauth"`
 }

Tag names are illustrative—adjust to your actual label keys.

internal/utils/utils.go (1)

201-207: Hard-coding every key defeats the purpose of declarative decoding

Passing both "tinyauth" and every concrete key to parser.Decode makes maintenance harder – any new sub-key will require touching this list in multiple places.

If you just want to allow anything under tinyauth.*, provide only the root prefix:

-	err := parser.Decode(labels, &labelsParsed,
-		"tinyauth", "tinyauth.users", "tinyauth.allowed",
-		"tinyauth.headers", "tinyauth.oauth")
+	err := parser.Decode(labels, &labelsParsed, "tinyauth")

This keeps the decoder future-proof.

internal/docker/docker.go (1)

114-121: Duplicate log + error propagation

The error from utils.GetLabels is already logged inside that function.
Logging it again here adds noise without extra signal.

Either drop the local log line or change the inner function to not log.

internal/utils/utils_test.go (1)

282-316: Slice order in tests can introduce flakiness

reflect.DeepEqual on slices is order-sensitive.
parser.Decode iterates over a map, so "tinyauth.headers"[]string order is not guaranteed across Go versions.

Prefer a set/element comparison:

-	if !reflect.DeepEqual(expected, result) {
+	if !cmp.Equal(expected, result, cmpopts.SortSlices(func(a, b string) bool { return a < b })) {
 		t.Fatalf("Expected %v, got %v", expected, result)
 	}

(uses github.com/google/go-cmp/cmp)

Prevents sporadic CI failures.

internal/auth/auth.go (2)

267-278: Minor readability: early-return instead of nested if

-	if context.OAuth {
-		log.Debug().Msg("Checking OAuth whitelist")
-		return utils.CheckWhitelist(labels.OAuth.Whitelist, context.Email)
-	}
-
-	// Check users
-	log.Debug().Msg("Checking users")
-
-	return utils.CheckWhitelist(labels.Users, context.Username)
+	if context.OAuth {
+		log.Debug().Msg("Checking OAuth whitelist")
+		return utils.CheckWhitelist(labels.OAuth.Whitelist, context.Email)
+	}
+	// User/password path
+	return utils.CheckWhitelist(labels.Users, context.Username)

Same logic, flatter structure.


310-336: Compiling regex for every request is unnecessary overhead

AuthEnabled recompiles labels.Allowed on each call.
Caching the compiled pattern when labels are first parsed avoids per-request CPU and GC churn.

Consider adding a *regexp.Regexp field to types.Labels or storing it in a small in-memory cache keyed by the pattern string.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb296f and 282cabf.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (11)
  • Dockerfile (1 hunks)
  • frontend/Dockerfile.dev (1 hunks)
  • go.mod (1 hunks)
  • internal/auth/auth.go (4 hunks)
  • internal/constants/constants.go (0 hunks)
  • internal/docker/docker.go (4 hunks)
  • internal/handlers/handlers.go (2 hunks)
  • internal/types/config.go (1 hunks)
  • internal/types/types.go (0 hunks)
  • internal/utils/utils.go (2 hunks)
  • internal/utils/utils_test.go (1 hunks)
💤 Files with no reviewable changes (2)
  • internal/constants/constants.go
  • internal/types/types.go
🧰 Additional context used
🧬 Code Graph Analysis (4)
internal/handlers/handlers.go (1)
internal/utils/utils.go (1)
  • ParseHeaders (178-194)
internal/auth/auth.go (3)
internal/types/types.go (1)
  • UserContext (36-46)
internal/types/config.go (1)
  • Labels (103-108)
internal/utils/utils.go (1)
  • CheckWhitelist (288-324)
internal/docker/docker.go (2)
internal/utils/utils.go (1)
  • GetLabels (197-212)
internal/types/config.go (1)
  • Labels (103-108)
internal/utils/utils.go (1)
internal/types/config.go (1)
  • Labels (103-108)
🔇 Additional comments (1)
go.mod (1)

27-27: Mark the paerser dependency as direct (not indirect).

The codebase now imports github.com/traefik/paerser/parser, so paerser is a first-class dependency. go mod tidy will automatically drop the // indirect suffix, but checking it in as direct avoids noisy diffs later.

-github.com/traefik/paerser v0.2.2 // indirect
+github.com/traefik/paerser v0.2.2

Run go mod tidy before merging to ensure the module graph is consistent.

Comment thread internal/handlers/handlers.go
Comment thread internal/utils/utils.go
Comment thread internal/docker/docker.go
Comment thread internal/docker/docker.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
internal/utils/utils.go (1)

183-190: ⚠️ Potential issue

Still splits on every “=” and keeps stray whitespace – bug resurfaced

Previous review already pointed this out: strings.Split(header, "=") breaks as soon as a header value contains an = (e.g. X-Auth=a=b) and you also keep leading / trailing spaces in both key and value. The implementation hasn’t been updated, so the parser still discards valid headers silently.

-		headerSplit := strings.Split(header, "=")
+		headerSplit := strings.SplitN(header, "=", 2)
 		if len(headerSplit) != 2 {
 			log.Warn().Str("header", header).Msg("Invalid header format, skipping")
 			continue
 		}
-		headerMap[headerSplit[0]] = SanitizeHeader(headerSplit[1])
+		key := strings.TrimSpace(headerSplit[0])
+		val := strings.TrimSpace(headerSplit[1])
+		headerMap[key] = SanitizeHeader(val)

This single change fixes both the “extra =” and “space pollution” issues without impacting the happy path.

🧹 Nitpick comments (1)
internal/utils/utils.go (1)

201-208: parser.Decode call can be simplified

You already scope decoding to the tinyauth prefix, so listing every sub-path (tinyauth.users, tinyauth.allowed, …) is redundant and brittle when new fields are added. A simpler, future-proof call:

err := parser.Decode(labels, &labelsParsed, "tinyauth")

Less to maintain, same result.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 282cabf and aeb93da.

📒 Files selected for processing (1)
  • internal/utils/utils.go (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
internal/utils/utils.go (1)
internal/types/config.go (1)
  • Labels (103-108)

@steveiliop56 steveiliop56 merged commit 3397e2a into main Jun 15, 2025
6 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Dec 30, 2025
@Rycochet Rycochet deleted the refactor/paerser branch April 1, 2026 16:08
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.

1 participant