-
Notifications
You must be signed in to change notification settings - Fork 4
fix(routing): added WithViewers to overwrite default handler's viewers #26
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
Conversation
Reviewer's Guide by SourceryThis pull request introduces the ability to overwrite the default handler's viewers using the Sequence diagram for viewer rendering processsequenceDiagram
participant C as Client
participant A as App
participant V as Viewers
participant B as BufferPool
C->>A: HTTP Request with Accept header
A->>V: Select viewer based on Accept
V->>B: Get buffer from pool
V->>V: Encode data (JSON/XML)
V->>C: Write response with content type
V->>B: Return buffer to pool
Class diagram showing viewer and app structure changesclassDiagram
class App {
-sync.RWMutex mu
-http.ServeMux mux
-[]Middleware middlewares
-map[string]Viewer viewers
-map[string]*Routing routes
-[]Viewer handlerViewers
-[]ViewEngine engines
+New(opts ...Option)
+HandleFile(name string, v *FileViewer)
+HandlePage(pattern string, viewName string, v Viewer)
}
class RoutingOptions {
-map[string]any metadata
-[]Viewer viewers
}
class Viewer {
<<interface>>
+MimeType() *MimeType
+Render(w http.ResponseWriter, r *http.Request, data any) error
}
class XmlViewer {
+MimeType() *MimeType
+Render(w http.ResponseWriter, r *http.Request, data any) error
}
Viewer <|.. XmlViewer
App --> "*" Viewer : has
RoutingOptions --> "*" Viewer : has
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #26 +/- ##
==========================================
+ Coverage 89.98% 90.15% +0.17%
==========================================
Files 32 34 +2
Lines 1198 1219 +21
==========================================
+ Hits 1078 1099 +21
Misses 83 83
Partials 37 37
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cnlangzi - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟡 General issues: 3 issues found
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
if !c.writtenStatus { | ||
c.rw.WriteHeader(http.StatusOK) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Removing default status code could cause malformed HTTP responses
The default 200 OK status code was previously set if no status was written. Now viewers must handle this, which could lead to responses without status codes if viewers don't set them explicitly.
@@ -23,6 +23,15 @@ | |||
// | |||
// It sets the Content-Type header to "application/json". | |||
func (*JsonViewer) Render(w http.ResponseWriter, r *http.Request, data any) error { // skipcq: RVV-B0012 | |||
buf := BufPool.Get() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): Consider setting Content-Length header since response is now buffered
Now that the response is buffered, you could set the Content-Length header using buf.Len() before writing to the response writer. This helps clients better handle the response.
Suggested implementation:
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Content-Length", strconv.Itoa(buf.Len()))
_, err = buf.WriteTo(w)
You'll need to add the following import if not already present:
- "strconv"
// Render renders the given data as xml to the http.ResponseWriter. | ||
// | ||
// It sets the Content-Type header to "text/xml; charset=utf-8". | ||
func (*XmlViewer) Render(w http.ResponseWriter, r *http.Request, data any) error { // skipcq: RVV-B0012 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): Add Content-Length header to XML viewer
Similar to the JSON viewer, setting Content-Length header would improve performance since the response is already buffered.
Suggested implementation:
err := xml.NewEncoder(buf).Encode(data)
if err != nil {
return err
}
w.Header().Add("Content-Type", "text/xml; charset=utf-8")
w.Header().Add("Content-Length", strconv.Itoa(buf.Len()))
Make sure the following import is present at the top of the file:
import "strconv"
@@ -198,7 +198,7 @@ func (app *App) HandleFile(name string, v *FileViewer) { | |||
return | |||
} | |||
|
|||
ro.viewer = v | |||
ro.viewers = []Viewer{v} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider simplifying viewer initialization and handling in RoutingOptions.
The shift to array-based viewers has introduced unnecessary complexity. While maintaining multi-viewer support, we can simplify the implementation:
- Simplify viewer initialization and handling in
RoutingOptions
:
type RoutingOptions struct {
viewers []Viewer
}
// Constructor function for cleaner initialization
func NewRoutingOptions(viewers ...Viewer) *RoutingOptions {
return &RoutingOptions{viewers: viewers}
}
- Simplify the
createHandler
function:
func (app *App) createHandler(pattern string, hf HandleFunc, opts []RoutingOption, c chain) {
ro := NewRoutingOptions(app.handlerViewers...)
for _, o := range opts {
o(ro)
}
r := &Routing{
Options: ro,
Pattern: pattern,
Handle: hf,
chain: c,
}
if existing, ok := app.routes[pattern]; ok {
// Merge viewers if updating existing route
r.Viewers = append(r.Viewers, existing.Viewers...)
}
app.routes[pattern] = r
// ... rest of the function
}
This approach:
- Eliminates redundant viewer append operations
- Makes initialization more explicit
- Maintains multi-viewer capability while simplifying the common case
- Reduces nesting and conditional complexity
Here's the code health analysis summary for commits Analysis Summary
|
Changed
app.WithViewer
toapp.WithHandlerViewers
to accept multiple default viewersFixed
Added
WithViewers
in RoutingOption to overwrite default handler's viewersXmlViewer
Tests
Tasks to complete before merging PR:
make unit-test
to check for any regressions 📋make lint
to check for any issuesSummary by Sourcery
Add support for XML viewer.
New Features:
Tests: