Summary
Three UI list handlers follow an identical pattern: define a filter struct, parse from query params, call handleList(), and enrich data. The filter structs differ only in which categories are valid, but the parsing and enrichment logic is duplicated.
Current Pattern (repeated 3x)
// ui_iocs.go
type iocFilter struct { Category, Search, Status, SortBy, SortOrder, Page, PageSize string }
func parseIOCFilter(r *http.Request) iocFilter { ... }
func (h *UIHandlers) HandleListIOCs(w, r) { filter := parseIOCFilter(r); handleList(...); enrichIOCData(...) }
// ui_sources.go — IDENTICAL STRUCT
type sourceFilter struct { Category, Search, Status, SortBy, SortOrder, Page, PageSize string }
func parseSourceFilter(r *http.Request) sourceFilter { ... }
// ui_sites.go — IDENTICAL STRUCT
type siteFilter struct { Category, Search, Status, SortBy, SortOrder, Page, PageSize string }
func parseSiteFilter(r *http.Request) siteFilter { ... }
Proposed Solution
Define a common filter interface and generic parser:
// ui_base.go
// BaseFilter holds common filter fields shared across list pages.
type BaseFilter struct {
Search string
Status string
SortBy string
SortOrder string
Page string
PageSize string
}
// FilterParser parses common fields from query params.
func ParseBaseFilter(r *http.Request) BaseFilter {
return BaseFilter{
Search: r.URL.Query().Get("search"),
Status: r.URL.Query().Get("status"),
SortBy: r.URL.Query().Get("sort_by"),
SortOrder: r.URL.Query().Get("sort_order"),
Page: r.URL.Query().Get("page"),
PageSize: r.URL.Query().Get("page_size"),
}
}
// CategoryFilter adds category filtering on top of BaseFilter.
type CategoryFilter struct {
BaseFilter
Category string
ValidCategories []string
}
Each handler then only defines its category-specific logic:
func (h *UIHandlers) HandleListIOCs(w, r) {
base := ParseBaseFilter(r)
filter := CategoryFilter{
BaseFilter: base,
Category: r.URL.Query().Get("category"),
ValidCategories: []string{"domain", "hash", "url", ...},
}
// ... handleList with filter ...
}
Impact
- Lines saved: ~50 per file (~150 total across 3 files)
- Risk: Medium — filter parsing is tested, need to verify equivalence
- Benefit: Single source of truth for filter parsing, easier to add new filter fields
Summary
Three UI list handlers follow an identical pattern: define a filter struct, parse from query params, call
handleList(), and enrich data. The filter structs differ only in which categories are valid, but the parsing and enrichment logic is duplicated.Current Pattern (repeated 3x)
Proposed Solution
Define a common filter interface and generic parser:
Each handler then only defines its category-specific logic:
Impact