Skip to content

refactor(server): extract common HTTP transport configuration options #253

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 1 commit into from
May 8, 2025

Conversation

rwjblue-glean
Copy link
Collaborator

@rwjblue-glean rwjblue-glean commented May 7, 2025

Create a common interface and pattern for HTTP transport configuration to enable code sharing between SSEServer and the upcoming StreamableHTTPServer.

  • Add new httpTransportConfigurable interface for shared configuration
  • Refactor SSEServer to implement the shared interface
  • Convert With* option functions to work with both server types
  • Add stub for StreamableHTTPServer to demonstrate implementation pattern
  • Deprecate WithSSEContextFunc in favor of WithHTTPContextFunc

This change preserves backward compatibility while allowing the reuse of
configuration code across different HTTP server implementations (e.g. #228).

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a flexible configuration system for HTTP servers, supporting both current and future server types.
    • Added new options for customizing base paths, keep-alive behavior, and HTTP context handling.
  • Refactor

    • Updated the way server options are applied, using a new interface-based approach for improved extensibility and clarity.
    • Deprecated and removed several older configuration functions in favor of the new system.
    • Refactored SSE server option functions to use typed option wrappers and internal setter methods.
    • Changed SSE server context function type and updated constructors to apply options via the new interface.
  • Documentation

    • Updated comments and option descriptions to reflect the new configuration approach.

Copy link
Contributor

coderabbitai bot commented May 7, 2025

Warning

Rate limit exceeded

@robert-jackson-glean has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 32 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 d16a773 and 29f87db.

📒 Files selected for processing (2)
  • server/http_transport_options.go (1 hunks)
  • server/sse.go (5 hunks)

Walkthrough

A new interface-based system for configuring HTTP transport options for servers is introduced, primarily affecting SSEServer and a stub StreamableHTTPServer. The code refactors option functions into typed interfaces and internal setters, consolidating and replacing previous exported option functions with a flexible, extensible approach for server configuration.

Changes

Files/Group Change Summary
server/http_transport_options.go Introduces new interfaces (HTTPServerOption, SSEOption, StreamableHTTPOption, CommonHTTPServerOption), functional wrappers, and setter methods for HTTP transport configuration. Adds new option functions for base path, keep-alive, context customization, and base URL validation. Adds stub StreamableHTTPServer type.
server/sse.go Refactors SSEServer configuration to use new option interfaces and internal setters. Removes previously exported option functions including dynamic base path and keep-alive options, updates constructor logic to apply typed options, changes contextFunc field type, marks WithSSEContextFunc as deprecated, and preserves deprecated WithBasePath as wrapper.

Possibly related PRs

Suggested reviewers

  • steve-calvert-glean
✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

Copy link
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: 2

🧹 Nitpick comments (4)
server/sse_test.go (2)

718-725: Use canonical interface{} syntax to keep go fmt clean

The slice type is written with a space – []interface {} – whereas Go’s canonical formatting is []interface{}.
Running go fmt will rewrite this anyway, but it’s better to commit formatted code to avoid needless churn in future diffs.

-		rands := []interface {}{
+		rands := []interface{}{

728-733: Minor formatting nit for consistency

Same trailing space issue as above:

-			var options []interface {}
+			var options []interface{}
server/sse.go (1)

200-208: Unknown option types are silently discarded – surface misconfiguration early

NewSSEServer ignores any value that is neither SSEOption nor HTTPTransportOption.
A typo in option wiring will therefore compile but have no effect, making the bug hard to spot.

Consider returning an error (or at least log.Printf) when an unknown option is encountered:

 		default:
-			// Optionally: log or panic for unknown option type
+			log.Printf("sse: unrecognised option of type %T ignored", opt)
server/http_transport_options.go (1)

106-110: Overwriting an existing custom http.Server without warning

If the user supplies two WithHTTPServer options, the latter silently overwrites the first.
Either prevent double assignment or warn the caller to avoid hard-to-trace behaviour.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9d6b793 and c6a3162.

📒 Files selected for processing (3)
  • server/http_transport_options.go (1 hunks)
  • server/sse.go (4 hunks)
  • server/sse_test.go (2 hunks)
🔇 Additional comments (1)
server/sse.go (1)

109-112: setBasePath("") now normalises to “/” – verify this doesn’t break existing callers

normalizeURLPath("") yields /, so calling WithStaticBasePath("") (or leaving the base path unset but later invoking this setter internally) changes the previous default of an empty string to /.
Down-stream helpers such as CompleteSsePath will therefore produce //sse/sse.
If any code relied on basePath=="" to detect “not configured”, this behaviour change could be breaking.

Double-check call-sites (including external consumers) or guard against empty input:

-func (s *SSEServer) setBasePath(basePath string) {
-	s.basePath = normalizeURLPath(basePath)
+func (s *SSEServer) setBasePath(basePath string) {
+	if basePath == "" {
+		s.basePath = ""
+		return
+	}
+	s.basePath = normalizeURLPath(basePath)
 }

Copy link
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: 2

♻️ Duplicate comments (2)
server/http_transport_options.go (1)

143-168: ⚠️ Potential issue

Fix the silent error handling in WithBaseURL

The WithBaseURL function silently ignores invalid URLs by returning early when validation fails. This can lead to subtle bugs where misconfigured URLs go unnoticed until runtime.

Consider either returning an error from the option factory or logging the failure:

func WithBaseURL(baseURL string) CommonHTTPServerOption {
	return commonOption{
		apply: func(c httpTransportConfigurable) {
			if s, ok := c.(*SSEServer); ok {
				if baseURL != "" {
					u, err := url.Parse(baseURL)
					if err != nil {
-						return
+						log.Printf("http transport: invalid baseURL %q: %v", baseURL, err)
+						return
					}
					if u.Scheme != "http" && u.Scheme != "https" {
-						return
+						log.Printf("http transport: invalid scheme in baseURL %q: must be http or https", baseURL)
+						return
					}
					if u.Host == "" || strings.HasPrefix(u.Host, ":") {
-						return
+						log.Printf("http transport: invalid host in baseURL %q", baseURL)
+						return
					}
					if len(u.Query()) > 0 {
-						return
+						log.Printf("http transport: baseURL %q contains query parameters, which is not supported", baseURL)
+						return
					}
				}
				s.baseURL = strings.TrimSuffix(baseURL, "/")
			}
		},
	}
}

Alternatively, consider refactoring HTTPTransportOption to return an error:

// HTTPTransportOption is a function that configures an httpTransportConfigurable.
type HTTPTransportOption func(httpTransportConfigurable) error
server/sse.go (1)

223-225: ⚠️ Potential issue

Remove invalid //go:deprecated pragma

The //go:deprecated line is an invalid Go compiler directive that will cause a build error.

Go only accepts specific //go: directives, and deprecated is not one of them. Use the conventional comment format instead:

// WithSSEContextFunc sets a function that will be called to customise the context
// to the server using the incoming request.
//
// Deprecated: Use WithContextFunc instead. This will be removed in a future version.
-//go:deprecated
🧹 Nitpick comments (1)
server/sse.go (1)

697-705: Consider moving StreamableHTTPServer to http_transport_options.go

The StreamableHTTPServer implementation appears in both files. To maintain the single responsibility principle, consider defining it only in http_transport_options.go and importing it in server/sse.go.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c6a3162 and 389ad2c.

📒 Files selected for processing (2)
  • server/http_transport_options.go (1 hunks)
  • server/sse.go (6 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
server/http_transport_options.go (1)
server/sse.go (6)
  • HTTPServerOption (23-25)
  • SSEServer (131-148)
  • StreamableHTTPServer (698-698)
  • SSEOption (28-31)
  • StreamableHTTPOption (34-37)
  • CommonHTTPServerOption (40-43)
server/sse.go (2)
server/http_transport_options.go (7)
  • HTTPServerOption (30-32)
  • StreamableHTTPServer (74-74)
  • SSEOption (35-38)
  • StreamableHTTPOption (41-44)
  • HTTPContextFunc (14-14)
  • DynamicBasePathFunc (99-99)
  • WithHTTPContextFunc (135-141)
mcp/types.go (1)
  • Request (103-116)
🪛 GitHub Check: test
server/http_transport_options.go

[failure] 30-30:
other declaration of HTTPServerOption


[failure] 35-35:
other declaration of SSEOption


[failure] 41-41:
other declaration of StreamableHTTPOption


[failure] 47-47:
other declaration of CommonHTTPServerOption


[failure] 53-53:
other declaration of sseOption

server/sse.go

[failure] 23-23:
HTTPServerOption redeclared in this block


[failure] 28-28:
SSEOption redeclared in this block


[failure] 34-34:
StreamableHTTPOption redeclared in this block


[failure] 40-40:
CommonHTTPServerOption redeclared in this block


[failure] 46-46:
sseOption redeclared in this block

🪛 GitHub Actions: go
server/sse.go

[error] 23-23: HTTPServerOption redeclared in this block

🔇 Additional comments (3)
server/sse.go (3)

227-229: Good use of composition in WithSSEContextFunc

The implementation elegantly delegates to WithHTTPContextFunc which ensures that both the old and new options behave consistently, providing good backward compatibility.


150-182: Well-structured implementation of httpTransportConfigurable

The SSEServer correctly implements the httpTransportConfigurable interface with clear, focused setter methods. This approach makes the code more modular and easy to maintain.


244-246: Clean option application in NewSSEServer

The refactored approach using opt.applyToSSE(s) is cleaner and more type-safe than the previous implementation. It ensures that only compatible options can be applied to the SSEServer.

@rwjblue-glean rwjblue-glean force-pushed the rwjblue/push-qprrotsqwysw branch from 389ad2c to 37497a4 Compare May 7, 2025 16:00
Comment on lines 73 to 85
// TODO: Implement StreamableHTTPServer in the future
type StreamableHTTPServer struct{}

// Add stub methods to satisfy httpTransportConfigurable

func (s *StreamableHTTPServer) setBasePath(string) {}
func (s *StreamableHTTPServer) setDynamicBasePath(DynamicBasePathFunc) {}
func (s *StreamableHTTPServer) setKeepAliveInterval(time.Duration) {}
func (s *StreamableHTTPServer) setKeepAlive(bool) {}
func (s *StreamableHTTPServer) setContextFunc(HTTPContextFunc) {}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These are just stubs, to make it clearer what to do in #228

Copy link
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: 2

♻️ Duplicate comments (1)
server/http_transport_options.go (1)

143-168: WithBaseURL silently ignores invalid URLs – return an error or panic

At the moment, any validation failure leads to an early return, leaving baseURL unchanged but without signaling the problem. A mis-typed scheme or host would therefore go unnoticed until runtime when URLs are composed.

Expose the failure to the caller, for example by returning a second error value from the option factory or by logging:

func WithBaseURL(baseURL string) CommonHTTPServerOption {
	return commonOption{
		apply: func(c httpTransportConfigurable) {
			if s, ok := c.(*SSEServer); ok {
				if baseURL != "" {
					u, err := url.Parse(baseURL)
-					if err != nil {
-						return
-					}
+					if err != nil {
+						log.Printf("server: invalid baseURL %q: %v", baseURL, err)
+						return
+					}
					if u.Scheme != "http" && u.Scheme != "https" {
+						log.Printf("server: invalid scheme in baseURL %q: %v", baseURL, u.Scheme)
						return
					}
					// Other validation checks...
🧹 Nitpick comments (1)
server/http_transport_options.go (1)

170-180: Consider documenting implications of custom HTTP server

The WithHTTPServer option allows setting a custom HTTP server, but the documentation doesn't explain how this interacts with other configuration options. Some options might be ineffective when using a custom server.

Enhance the documentation:

// WithHTTPServer sets the HTTP server instance for the transport.
// This is useful for advanced scenarios where you want to provide your own http.Server.
+// Note: When using a custom server, some configuration options might not be applied
+// automatically, such as TLS settings or timeouts. It's the caller's responsibility
+// to ensure the custom server is properly configured.
func WithHTTPServer(srv *http.Server) CommonHTTPServerOption {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 389ad2c and 37497a4.

📒 Files selected for processing (2)
  • server/http_transport_options.go (1 hunks)
  • server/sse.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/sse.go
🧰 Additional context used
🪛 golangci-lint (1.64.8)
server/http_transport_options.go

59-59: type streamableHTTPOption is unused

(unused)


61-61: func streamableHTTPOption.isHTTPServerOption is unused

(unused)


62-62: func streamableHTTPOption.applyToStreamableHTTP is unused

(unused)

🔇 Additional comments (4)
server/http_transport_options.go (4)

16-23: Well-designed internal interface for common HTTP transport settings

The httpTransportConfigurable interface provides a clean abstraction for shared HTTP transport configuration across different server types. This approach follows good design principles by defining a common contract for configuration methods.


29-50: Good interface hierarchy design for server options

The option interface hierarchy is well-structured, with appropriate specialization through interface embedding. This design enables type-safe options that can be applied to specific server types or shared across multiple server types.


52-72: Clean implementation of the functional options pattern

The option wrappers (sseOption, streamableHTTPOption, and commonOption) provide a clean implementation of the functional options pattern. The use of method implementations to satisfy the interfaces creates a flexible and extensible system.

🧰 Tools
🪛 golangci-lint (1.64.8)

59-59: type streamableHTTPOption is unused

(unused)


61-61: func streamableHTTPOption.isHTTPServerOption is unused

(unused)


62-62: func streamableHTTPOption.applyToStreamableHTTP is unused

(unused)


112-141: Well-implemented configuration options

The keep-alive and HTTP context function options are well-implemented, following a consistent pattern and providing appropriate setter functions for each configurable aspect.

@rwjblue-glean rwjblue-glean force-pushed the rwjblue/push-qprrotsqwysw branch 3 times, most recently from 31bcb79 to d16a773 Compare May 7, 2025 16:26
Copy link
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: 1

♻️ Duplicate comments (1)
server/http_transport_options.go (1)

148-173: WithBaseURL silently ignores invalid URLs – consider better error handling

The WithBaseURL function silently returns when validation fails, which could lead to unexpected behavior. This was noted in a previous review comment, and you mentioned you'd address it in a future PR.

As a reminder for your future PR, consider either:

  1. Returning an error from the option function
  2. Logging a warning about the invalid URL
  3. Panicking with a clear message (if this is a programmer error)

This would make it easier to diagnose configuration issues.

🧹 Nitpick comments (1)
server/http_transport_options.go (1)

53-72: Consider adding compiler checks for streamableHTTPOption

The streamableHTTPOption type and its methods are flagged as unused by the static analyzer. Since they're part of your interface design but not currently used, consider adding a compile-time check similar to what you did for StreamableHTTPServer.

+ // Ensure the option types implement the correct interfaces
+ var _ SSEOption = sseOption(nil)
+ var _ StreamableHTTPOption = streamableHTTPOption(nil)
+ var _ CommonHTTPServerOption = commonOption{}
🧰 Tools
🪛 golangci-lint (1.64.8)

60-60: type streamableHTTPOption is unused

(unused)


62-62: func streamableHTTPOption.isHTTPServerOption is unused

(unused)


63-63: func streamableHTTPOption.applyToStreamableHTTP is unused

(unused)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a0b2158 and d16a773.

📒 Files selected for processing (2)
  • server/http_transport_options.go (1 hunks)
  • server/sse.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/sse.go
🧰 Additional context used
🪛 golangci-lint (1.64.8)
server/http_transport_options.go

60-60: type streamableHTTPOption is unused

(unused)


62-62: func streamableHTTPOption.isHTTPServerOption is unused

(unused)


63-63: func streamableHTTPOption.applyToStreamableHTTP is unused

(unused)

🔇 Additional comments (5)
server/http_transport_options.go (5)

11-15: Good documentation and type definition for HTTPContextFunc

The HTTPContextFunc type is well-defined with clear documentation explaining its purpose and usage. This establishes a solid foundation for context manipulation across different HTTP server implementations.


16-24: Well-designed interface for HTTP transport configuration

The httpTransportConfigurable interface provides a clean abstraction for shared HTTP transport configuration, enabling code reuse across different server types. The set of methods covers essential configuration aspects like base paths, keep-alive settings, and HTTP server customization.


29-51: Good interface hierarchy for server configuration options

The option interfaces establish a logical hierarchy that enables both server-specific options and common options. This design supports the PR's goal of sharing configuration between server types while preserving type safety.


74-87: Good approach for the StreamableHTTPServer stub implementation

The StreamableHTTPServer stub with empty method implementations and compile-time interface check (var _ httpTransportConfigurable = (*StreamableHTTPServer)(nil)) is a clean way to ensure interface compliance while indicating future implementation. This satisfies the PR's goal of demonstrating the implementation pattern.


89-97: Well-designed option functions with good documentation

The option functions follow a consistent pattern and have clear documentation explaining their purpose and usage. They correctly use the commonOption wrapper to provide common functionality for different server types.

Also applies to: 106-115, 117-125, 127-135, 137-146, 175-183

@rwjblue-glean rwjblue-glean force-pushed the rwjblue/push-qprrotsqwysw branch from d16a773 to f7ef338 Compare May 7, 2025 16:43
Create a common interface and pattern for HTTP transport configuration to
enable code sharing between SSEServer and the upcoming StreamableHTTPServer.

- Add new httpTransportConfigurable interface for shared configuration
- Refactor SSEServer to implement the shared interface
- Convert With* option functions to work with both server types
- Add stub for StreamableHTTPServer to demonstrate implementation pattern
- Deprecate WithSSEContextFunc in favor of WithHTTPContextFunc

This change preserves backward compatibility while allowing the reuse of
configuration code across different HTTP server implementations.
@rwjblue-glean rwjblue-glean force-pushed the rwjblue/push-qprrotsqwysw branch from f7ef338 to 29f87db Compare May 7, 2025 16:45
@ezynda3 ezynda3 merged commit dd1e1e8 into mark3labs:main May 8, 2025
2 checks passed
@rwjblue-glean rwjblue-glean deleted the rwjblue/push-qprrotsqwysw branch May 8, 2025 12:11
tendant pushed a commit to tendant/mcp-go that referenced this pull request May 8, 2025
…mark3labs#253)

Create a common interface and pattern for HTTP transport configuration to
enable code sharing between SSEServer and the upcoming StreamableHTTPServer.

- Add new httpTransportConfigurable interface for shared configuration
- Refactor SSEServer to implement the shared interface
- Convert With* option functions to work with both server types
- Add stub for StreamableHTTPServer to demonstrate implementation pattern
- Deprecate WithSSEContextFunc in favor of WithHTTPContextFunc

This change preserves backward compatibility while allowing the reuse of
configuration code across different HTTP server implementations.
@pottekkat pottekkat mentioned this pull request May 13, 2025
adlternative pushed a commit to adlternative/mcp-go that referenced this pull request May 20, 2025
…mark3labs#253)

Create a common interface and pattern for HTTP transport configuration to
enable code sharing between SSEServer and the upcoming StreamableHTTPServer.

- Add new httpTransportConfigurable interface for shared configuration
- Refactor SSEServer to implement the shared interface
- Convert With* option functions to work with both server types
- Add stub for StreamableHTTPServer to demonstrate implementation pattern
- Deprecate WithSSEContextFunc in favor of WithHTTPContextFunc

This change preserves backward compatibility while allowing the reuse of
configuration code across different HTTP server implementations.
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.

2 participants