Skip to content

Conversation

cnlangzi
Copy link
Member

@cnlangzi cnlangzi commented Jan 19, 2025

Changed

  • changed app.WithViewer to app.WithHandlerViewers to accept multiple default viewers

Fixed

Added

  • added WithViewers in RoutingOption to overwrite default handler's viewers
  • added XmlViewer

Tests

Tasks to complete before merging PR:

  • Ensure unit tests are passing. If not run make unit-test to check for any regressions 📋
  • Ensure lint tests are passing. if not run make lint to check for any issues
  • Ensure codecov/patch is passing for changes.

Summary by Sourcery

Add support for XML viewer.

New Features:

  • Introduce an XML viewer that allows routes to return responses in XML format.

Tests:

  • Add tests for the XML viewer.

Copy link

sourcery-ai bot commented Jan 19, 2025

Reviewer's Guide by Sourcery

This pull request introduces the ability to overwrite the default handler's viewers using the WithViewers option. It also adds a new XmlViewer to support XML responses.

Sequence diagram for viewer rendering process

sequenceDiagram
    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
Loading

Class diagram showing viewer and app structure changes

classDiagram
    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
Loading

File-Level Changes

Change Details Files
Renamed app.WithViewer to app.WithHandlerViewers to allow multiple default viewers.
  • Renamed app.WithViewer to app.WithHandlerViewers.
  • Updated the New function to use handlerViewers instead of viewer.
  • Updated the createHandler function to use handlerViewers instead of viewer.
  • Updated the app_test.go to use WithHandlerViewers instead of WithViewer.
app.go
option.go
app_test.go
Added WithViewers in RoutingOption to overwrite default handler's viewers.
  • Added viewers field in RoutingOptions.
  • Added WithViewer function to set the viewers in RoutingOptions.
  • Updated HandleFile and HandlePage to use viewers instead of viewer.
  • Updated createHandler to append the viewers to the route.
  • Added a test case to verify the functionality of WithViewer.
app.go
routing_option.go
routing_option_test.go
Added XmlViewer to support XML responses.
  • Added XmlViewer struct and its methods.
  • Added a test case to verify the functionality of XmlViewer.
viewer.go
viewer_xml.go
routing_option_test.go
Refactored JsonViewer and HtmlViewer to use a buffer pool.
  • Added BufPool to viewer.go.
  • Updated JsonViewer and HtmlViewer to use BufPool.
viewer.go
viewer_json.go
viewer_html.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

codecov bot commented Jan 19, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.15%. Comparing base (6dc74f4) to head (9589679).
Report is 1 commits behind head on main.

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              
Flag Coverage Δ
Unit-Tests 90.15% <100.00%> (+0.17%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@sourcery-ai sourcery-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.

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

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines -86 to -87
if !c.writtenStatus {
c.rw.WriteHeader(http.StatusOK)
Copy link

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()
Copy link

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

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}
Copy link

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:

  1. 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}
}
  1. 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

Copy link

deepsource-io bot commented Jan 19, 2025

Here's the code health analysis summary for commits 6dc74f4..9589679. View details on DeepSource ↗.

Analysis Summary

AnalyzerStatusSummaryLink
DeepSource Go LogoGo✅ SuccessView Check ↗

💡 If you’re a repository administrator, you can configure the quality gates from the settings.

@cnlangzi cnlangzi merged commit cc6c72b into main Jan 19, 2025
7 checks passed
@cnlangzi cnlangzi deleted the fix/routing branch January 19, 2025 15:28
@cnlangzi cnlangzi changed the title fix(routing): added WithViewers to overwrite default hanlder's viewers fix(routing): added WithViewers to overwrite default handler's viewers Jan 19, 2025
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