Skip to content

JSLEEKR/routecheck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go License Tests CI-Friendly

routecheck

Static analysis for API routes. Parse route definitions across multiple web frameworks, detect conflicts, shadowed routes, duplicate registrations, parameter name conflicts, and missing methods. Single binary, zero runtime dependencies, CI-friendly.

Why This Exists

Every non-trivial web application accumulates route definitions over time. As projects grow, subtle bugs creep in:

  • Shadowed routes: GET /users/:id registered before GET /users/admin means /users/admin is unreachable in many frameworks
  • Duplicate registrations: The same method+path registered twice, often in different files, causing silent overwrites
  • Parameter conflicts: /users/:id and /users/:userId at the same position with different names
  • Missing CRUD methods: A resource has GET, POST, PUT but no DELETE — intentional or forgotten?

These issues are caught at runtime (if at all), often in production. routecheck catches them at build time by statically analyzing your source files — no server startup required.

Supported Frameworks

Framework Language Param Style Auto-Detection
Express JavaScript/TypeScript :id require('express') / import express
Gin Go :id, *path github.com/gin-gonic/gin
FastAPI Python {id}, {id:int} from fastapi import
Chi Go {id}, {id:[0-9]+} github.com/go-chi/chi
Echo Go :id, *path github.com/labstack/echo

All parameter styles are normalized to {param} internally for consistent conflict detection.

Installation

From Source

go install github.com/JSLEEKR/routecheck/cmd/routecheck@latest

Binary Download

Download the latest release from GitHub Releases.

Build from Source

git clone https://github.com/JSLEEKR/routecheck.git
cd routecheck
go build -o routecheck ./cmd/routecheck

Quick Start

# Scan current directory recursively
routecheck .

# Scan specific files
routecheck src/routes.js server/main.go

# Scan with glob patterns
routecheck "src/**/*.js"

# Force a specific framework parser
routecheck --framework express src/

# JSON output for CI integration
routecheck --format json src/ > report.json

# List all discovered routes
routecheck --list src/

# Strict mode: treat warnings as errors
routecheck --strict src/

Usage

routecheck [flags] [paths...]

Flags:
  -f, --format string      Output format: text, json (default "text")
  --framework string        Force framework parser: express, gin, fastapi, chi, echo
  --ext string              Comma-separated file extensions to scan (e.g., .go,.js)
  -r, --recursive           Recursively scan directories (default true)
  -l, --list                List all discovered routes
  --strict                  Treat warnings as errors (exit code 1)
  -v, --version             Show version

Exit Codes:
  0  Clean — no errors found
  1  Conflicts — errors (or warnings in strict mode) detected
  2  Parse error — invalid flags or file access problems

Issue Types

Error Severity

duplicate — Same method + pattern registered multiple times

[ERROR] Duplicate route: GET /users registered 2 times
    -> GET /users (routes.js:5)
    -> GET /users (routes.js:15)

shadowed — A route is unreachable because an earlier parameterized route matches first

[ERROR] Route GET /users/admin (line 15) is shadowed by GET /users/{id} (line 5)
    -> GET /users/{id} (routes.js:5)
    -> GET /users/admin (routes.js:15)

Warning Severity

conflict — Two routes could match the same request

[WARN] Potential conflict: GET /users/{id} vs GET /users/{userId}
    -> GET /users/{id} (routes.js:5)
    -> GET /users/{userId} (api.js:10)

param_conflict — Different parameter names at the same path position

[WARN] Parameter name conflict at position 1: {id} vs {userId}
    -> GET /users/{id}/posts (routes.js:5)
    -> GET /users/{userId}/posts (api.js:10)

Info Severity

missing_method — A resource pattern has most CRUD methods but is missing one

[INFO] Pattern /users has 3 methods but missing DELETE — intentional?

Output Formats

Text (Default)

Human-readable output with severity icons and route locations:

routecheck: scanned 12 routes
------------------------------------------------------------

ERRORS (2):
  [ERROR] Duplicate route: GET /health registered 2 times
    -> GET /health (main.go:8)
    -> GET /health (main.go:25)
  [ERROR] Route GET /users/admin (line 20) is shadowed by GET /users/{id} (line 10)
    -> GET /users/{id} (main.go:10)
    -> GET /users/admin (main.go:20)

WARNINGS (1):
  [WARN] Potential conflict: GET /users/{id} vs GET /users/{userId}
    -> GET /users/{id} (main.go:10)
    -> GET /users/{userId} (main.go:22)
------------------------------------------------------------
Summary: 2 errors, 1 warnings, 0 info

JSON

Machine-readable output for CI integration:

{
  "version": "1.0.0",
  "total_routes": 12,
  "issues": [
    {
      "type": "duplicate",
      "severity": "error",
      "message": "Duplicate route: GET /health registered 2 times",
      "routes": [
        {
          "method": "GET",
          "pattern": "/health",
          "file": "main.go",
          "line": 8,
          "framework": "gin"
        },
        {
          "method": "GET",
          "pattern": "/health",
          "file": "main.go",
          "line": 25,
          "framework": "gin"
        }
      ]
    }
  ],
  "summary": {
    "errors": 2,
    "warnings": 1,
    "info": 0
  },
  "routes_by_method": {
    "GET": 8,
    "POST": 2,
    "PUT": 1,
    "DELETE": 1
  },
  "routes_by_framework": {
    "gin": 12
  }
}

CI Integration

GitHub Actions

name: Route Check
on: [push, pull_request]

jobs:
  routecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.26'
      - run: go install github.com/JSLEEKR/routecheck/cmd/routecheck@latest
      - run: routecheck --strict --format json src/ > routecheck-report.json
      - name: Check for issues
        run: routecheck --strict src/

GitLab CI

routecheck:
  stage: lint
  image: golang:1.26
  script:
    - go install github.com/JSLEEKR/routecheck/cmd/routecheck@latest
    - routecheck --strict .

Pre-commit Hook

#!/bin/sh
# .git/hooks/pre-commit
routecheck --strict src/
if [ $? -ne 0 ]; then
    echo "Route conflicts detected! Fix before committing."
    exit 1
fi

Framework Detection

routecheck auto-detects frameworks by analyzing file content:

Framework Detection Signals
Express require('express'), import express, express(), express.Router()
Gin "github.com/gin-gonic/gin", gin.Default(), gin.New()
FastAPI from fastapi, FastAPI(), APIRouter(
Chi "github.com/go-chi/chi", chi.NewRouter()
Echo "github.com/labstack/echo", echo.New()

File extensions determine which detectors run:

  • .go — Gin, Chi, Echo
  • .js, .ts, .mjs, .cjs — Express
  • .py — FastAPI

Use --framework to override auto-detection when scanning files without obvious framework indicators.

Route Groups and Prefixes

routecheck understands route grouping and prefix composition:

Gin Groups

api := r.Group("/api")
v1 := api.Group("/v1")
v1.GET("/users", listUsers) // detected as /api/v1/users

Echo Groups

api := e.Group("/api")
v1 := api.Group("/v1")
v1.GET("/users", listUsers) // detected as /api/v1/users

FastAPI Router Prefixes

router = APIRouter(prefix="/items")
app.include_router(router, prefix="/api/v1")

@router.get("/{id}")  # detected as /api/v1/items/{id}

Chi Route Groups

r.Route("/api/v1", func(r chi.Router) {
    r.Get("/users", listUsers) // detected as /api/v1/users
})

Pattern Normalization

All framework-specific parameter syntaxes are normalized to {param}:

Framework Input Normalized
Express /users/:id /users/{id}
Gin /users/:id /users/{id}
Gin /files/*filepath /files/{filepath}
FastAPI /users/{id:int} /users/{id}
Chi /users/{id:[0-9]+} /users/{id}
Echo /users/:id /users/{id}
Echo /files/*filepath /files/{filepath}

Trailing slashes are stripped (except root /). Leading slashes are ensured.

Cross-Framework Analysis

routecheck can scan projects that use multiple frameworks simultaneously — for example, a Go API server using Gin alongside a Node.js BFF using Express. Routes from all frameworks are combined and analyzed together.

# Scan both Go and JS sources
routecheck server/ frontend/api/

This catches cross-framework conflicts like an Express BFF route that shadows a Gin backend route when both serve the same path prefix behind a reverse proxy.

Skipped Directories

When scanning recursively, these directories are automatically skipped:

  • Hidden directories (.git, .vscode, etc.)
  • node_modules
  • vendor
  • __pycache__

Architecture

cmd/routecheck/       CLI entry point
internal/
  parser/             Framework-specific route extractors
    express.go        Express.js parser
    gin.go            Gin parser
    fastapi.go        FastAPI parser
    chi.go            Chi parser
    echo.go           Echo parser
    detect.go         Auto-detection logic
    types.go          Shared types (Route, ParseResult, Parser)
  trie/               Route trie data structure
    trie.go           Insert, walk, path segmentation
  analyzer/           Conflict detection engine
    analyzer.go       Duplicate, conflict, shadow, param, missing checks
  framework/          File scanning and route collection
    scanner.go        Glob, directory walk, dedup, extension filter
  output/             Result formatting
    output.go         Text and JSON formatters

Development

# Run tests
go test ./... -v

# Build
go build -o routecheck ./cmd/routecheck

# Run against test data
./routecheck testdata/express/routes.js
./routecheck testdata/gin/routes.go
./routecheck testdata/fastapi/routes.py

# Run against test data with all frameworks
./routecheck testdata/

License

MIT

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Run tests (go test ./...)
  4. Commit your changes
  5. Push to the branch
  6. Open a Pull Request

Credits

Built as part of the daily-challenge project by @JSLEEKR.

About

Static route conflict detection for Express, Gin, FastAPI, Chi, Echo. Find shadowed routes, duplicates, and parameter conflicts. CI-friendly with JSON output.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages