Data Fetcher
The DataFetcher
provides a high-level interface for fetching CWE data from the API and converting it to local data structures. It builds upon the APIClient
to offer more convenient methods for common operations.
DataFetcher
type DataFetcher struct {
client *APIClient // Underlying API client
}
The DataFetcher wraps an APIClient and provides methods that return *CWE
instances instead of raw API response structures.
Constructors
NewDataFetcher
func NewDataFetcher() *DataFetcher
Creates a new data fetcher with a default API client.
Example:
fetcher := cwe.NewDataFetcher()
NewDataFetcherWithClient
func NewDataFetcherWithClient(client *APIClient) *DataFetcher
Creates a new data fetcher with a custom API client.
Parameters:
client
- Custom API client instance
Example:
// Create custom client
customClient := cwe.NewAPIClientWithOptions(
"https://custom-api.example.com/api/v1",
60 * time.Second,
)
// Create fetcher with custom client
fetcher := cwe.NewDataFetcherWithClient(customClient)
Basic Fetching Methods
FetchWeakness
func (f *DataFetcher) FetchWeakness(id string) (*CWE, error)
Fetches a weakness by ID and converts it to a CWE structure.
Parameters:
id
- CWE ID (with or without "CWE-" prefix)
Returns:
*CWE
- CWE instance with populated dataerror
- Error if fetching or conversion fails
Example:
// Create a data fetcher instance
fetcher := cwe.NewDataFetcher()
// Fetch a specific weakness by ID
// The ID can be specified with or without the "CWE-" prefix
cwe, err := fetcher.FetchWeakness("79")
if err != nil {
log.Fatalf("Failed to fetch weakness: %v", err)
}
// Print the fetched CWE information
fmt.Printf("Fetched: %s - %s\n", cwe.ID, cwe.Name)
fmt.Printf("Description: %s\n", cwe.Description)
fmt.Printf("Severity: %s\n", cwe.Severity)
FetchCategory
func (f *DataFetcher) FetchCategory(id string) (*CWE, error)
Fetches a category by ID and converts it to a CWE structure.
Parameters:
id
- Category ID
Returns:
*CWE
- CWE instance representing the categoryerror
- Error if fetching or conversion fails
FetchView
func (f *DataFetcher) FetchView(id string) (*CWE, error)
Fetches a view by ID and converts it to a CWE structure.
Parameters:
id
- View ID
Returns:
*CWE
- CWE instance representing the viewerror
- Error if fetching or conversion fails
Batch Operations
FetchMultiple
func (f *DataFetcher) FetchMultiple(ids []string) (*Registry, error)
Fetches multiple CWEs and returns them in a Registry.
Parameters:
ids
- Slice of CWE IDs to fetch
Returns:
*Registry
- Registry containing all fetched CWEserror
- Error if any fetch operation fails
Example:
// Prepare a slice of CWE IDs to fetch
ids := []string{"79", "89", "287"}
// Fetch multiple CWEs in a single operation
// This returns a Registry containing all the fetched CWEs
registry, err := fetcher.FetchMultiple(ids)
if err != nil {
log.Fatalf("Failed to fetch multiple CWEs: %v", err)
}
// Print information about the fetched CWEs
fmt.Printf("Fetched %d CWEs\n", len(registry.Entries))
for id, cwe := range registry.Entries {
fmt.Printf(" %s: %s\n", id, cwe.Name)
}
Tree Building Methods
BuildCWETreeWithView
func (f *DataFetcher) BuildCWETreeWithView(viewID string) (*Registry, error)
Builds a complete CWE tree starting from a specific view.
Parameters:
viewID
- View ID to use as the root
Returns:
*Registry
- Registry containing the complete treeerror
- Error if tree building fails
Example:
// Build a complete CWE tree starting from the Research View (CWE-1000)
// This operation fetches the view and recursively builds its entire hierarchy
registry, err := fetcher.BuildCWETreeWithView("1000")
if err != nil {
log.Fatalf("Failed to build tree: %v", err)
}
// Print information about the built tree
fmt.Printf("Built tree with %d nodes\n", len(registry.Entries))
// Access the root node
if registry.Root != nil {
fmt.Printf("Root node: %s - %s\n", registry.Root.ID, registry.Root.Name)
}
FetchCWEByIDWithRelations
func (f *DataFetcher) FetchCWEByIDWithRelations(id string, viewID string) (*CWE, error)
Fetches a CWE and populates its relationships (children) recursively.
Parameters:
id
- CWE ID to fetchviewID
- View context for relationships
Returns:
*CWE
- CWE with populated childrenerror
- Error if fetching fails
Example:
// Fetch a specific CWE and populate its children relationships
// The viewID parameter provides context for determining relationships
cwe, err := fetcher.FetchCWEByIDWithRelations("74", "1000")
if err != nil {
log.Fatalf("Failed to fetch with relations: %v", err)
}
// Print information about the CWE and its children
fmt.Printf("CWE %s has %d children\n", cwe.ID, len(cwe.Children))
for _, child := range cwe.Children {
fmt.Printf(" Child: %s - %s\n", child.ID, child.Name)
}
PopulateChildrenRecursive
func (f *DataFetcher) PopulateChildrenRecursive(cwe *CWE, viewID string) error
Recursively populates children for an existing CWE instance.
Parameters:
cwe
- CWE instance to populateviewID
- View context for relationships
Returns:
error
- Error if population fails
Version Information
GetCurrentVersion
func (f *DataFetcher) GetCurrentVersion() (string, error)
Gets the current CWE version string.
Returns:
string
- Version string (e.g., "4.12")error
- Error if version retrieval fails
Example:
version, err := fetcher.GetCurrentVersion()
if err != nil {
log.Fatalf("Failed to get version: %v", err)
}
fmt.Printf("Current CWE version: %s\n", version)
Usage Examples
Basic Fetching
fetcher := cwe.NewDataFetcher()
// Fetch individual items
xss, err := fetcher.FetchWeakness("79")
if err != nil {
log.Fatal(err)
}
injection, err := fetcher.FetchCategory("74")
if err != nil {
log.Fatal(err)
}
researchView, err := fetcher.FetchView("1000")
if err != nil {
log.Fatal(err)
}
fmt.Printf("XSS: %s\n", xss.Name)
fmt.Printf("Injection: %s\n", injection.Name)
fmt.Printf("Research View: %s\n", researchView.Name)
Building Complete Trees
fetcher := cwe.NewDataFetcher()
// Build complete tree from research view
fmt.Println("Building CWE tree (this may take a while)...")
registry, err := fetcher.BuildCWETreeWithView("1000")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Tree built with %d nodes\n", len(registry.Entries))
// Find root and traverse
if root := registry.Root; root != nil {
fmt.Printf("Root: %s - %s\n", root.ID, root.Name)
fmt.Printf("Root has %d direct children\n", len(root.Children))
// Print first level children
for _, child := range root.Children {
fmt.Printf(" - %s: %s\n", child.ID, child.Name)
}
}
Batch Processing
fetcher := cwe.NewDataFetcher()
// Define CWEs of interest
topCWEs := []string{
"79", // XSS
"89", // SQL Injection
"287", // Authentication
"22", // Path Traversal
"78", // OS Command Injection
}
// Fetch all at once
registry, err := fetcher.FetchMultiple(topCWEs)
if err != nil {
log.Fatal(err)
}
// Process results
fmt.Printf("Top %d CWEs:\n", len(registry.Entries))
for _, id := range topCWEs {
if cwe, exists := registry.GetByID("CWE-" + id); exists {
fmt.Printf(" CWE-%s: %s\n", id, cwe.Name)
if cwe.Severity != "" {
fmt.Printf(" Severity: %s\n", cwe.Severity)
}
}
}
Working with Relationships
fetcher := cwe.NewDataFetcher()
// Fetch injection category with all children
injection, err := fetcher.FetchCWEByIDWithRelations("74", "1000")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Injection (%s) hierarchy:\n", injection.ID)
printTree(injection, 0)
func printTree(cwe *cwe.CWE, depth int) {
indent := strings.Repeat(" ", depth)
fmt.Printf("%s- %s: %s\n", indent, cwe.ID, cwe.Name)
for _, child := range cwe.Children {
printTree(child, depth+1)
}
}
Performance Considerations
- Rate Limiting: Inherits rate limiting from underlying APIClient
- Tree Building: Large trees can take significant time due to recursive API calls
- Memory Usage: Complete trees may consume substantial memory
- Error Handling: Failed child fetches are logged but don't stop the process
Error Handling
The DataFetcher provides detailed error information:
cwe, err := fetcher.FetchWeakness("invalid-id")
if err != nil {
switch {
case strings.Contains(err.Error(), "not found"):
fmt.Println("CWE does not exist")
case strings.Contains(err.Error(), "parse"):
fmt.Println("Failed to parse CWE ID")
case strings.Contains(err.Error(), "convert"):
fmt.Println("Failed to convert API response")
default:
fmt.Printf("Unknown error: %v\n", err)
}
}