Essentials icon indicating copy to clipboard operation
Essentials copied to clipboard

Add OpenAPI 3 documentation endpoint for Essentials CWS API

Open Copilot opened this issue 7 months ago • 10 comments

This PR implements a new /swagger endpoint that provides OpenAPI 3.0.3 documentation for the PepperDash Essentials CWS API, enabling integration with tools like ApiDog and automatic client generation for web applications.

Changes Made

New SwaggerHandler Implementation

  • Created SwaggerHandler class following the same pattern as GetRoutesHandler
  • Inherits from WebApiBaseRequestHandler for consistency with existing architecture
  • Dynamically generates OpenAPI 3.0.3 specification from the current route collection

Route Registration

  • Added /swagger route to EssentialsWebApi.cs initialization
  • Handler is instantiated with the same route collection and base path as GetRoutesHandler

OpenAPI Features Implemented

  • Complete API Documentation: Automatically documents all 22 existing API endpoints
  • HTTP Method Detection: Smart detection of GET vs POST operations based on route patterns
  • Path Parameters: Automatic extraction and documentation of path variables (e.g., {deviceKey}, {filter})
  • Schema Definitions: Comprehensive schemas for:
    • DeviceCommand - for device control operations
    • Device - for device information
    • Feedback - for device status queries (Bool, Int, String feedback types)
    • ApiRoutes - for route discovery
  • Proper References: Uses correct $ref syntax for schema reuse
  • Platform Awareness: Dynamic server URL generation for both appliance and server platforms

API Documentation Coverage

The OpenAPI document includes all existing endpoints:

GET Endpoints:

  • /versions - Version information
  • /devices - Device listing
  • /config - System configuration
  • /deviceFeedbacks/{deviceKey} - Device status
  • /types, /types/{filter} - Type information
  • /joinMap/{bridgeKey}, /joinMap/{bridgeKey}/{deviceKey} - Join maps
  • /tielines - Tieline information
  • /device/{deviceKey}/routingPorts - Routing ports
  • /apiPaths - Route discovery
  • /swagger - OpenAPI documentation (new)

POST Endpoints:

  • /deviceCommands/{deviceKey} - Device control
  • /restartProgram - System restart
  • /loadConfig - Configuration loading
  • Debug and administrative operations

Usage

The OpenAPI documentation is available at:

GET /cws/api/swagger

Returns a complete OpenAPI 3.0.3 JSON document that can be:

  • Imported into ApiDog for API testing and documentation
  • Used by web applications for automatic client generation
  • Consumed by other OpenAPI-compatible tools

Example Response Structure

{
  "openapi": "3.0.3",
  "info": {
    "title": "PepperDash Essentials API",
    "description": "RESTful API for PepperDash Essentials control system",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://192.168.1.100/cws/api",
      "description": "Essentials API Server"
    }
  ],
  "paths": {
    "/devices": {
      "get": {
        "summary": "DevList",
        "description": "Retrieve a list of all devices in the system",
        "responses": { ... }
      }
    }
  },
  "components": {
    "schemas": { ... }
  }
}

Fixes #1294.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • crl.entrust.net
    • Triggering command: dotnet build --configuration Release (dns block)
  • ocsp.entrust.net
    • Triggering command: dotnet build --configuration Release (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot avatar Jul 24 '25 01:07 Copilot

@copilot you started from the wrong branch. Rebase your branch off of the development branch.

andrew-welker avatar Jul 24 '25 01:07 andrew-welker

@copilot you started from the wrong branch. Rebase your branch off of the development branch.

Rebased the branch onto development branch (b47f1d6b) as requested. All SwaggerHandler implementation changes have been reapplied on top of the latest development code. Commit: 4c03867b

Copilot avatar Jul 24 '25 01:07 Copilot

@copilot Can we use attributes from existing swashbuckle nuget packages to add metadata to the handlers and their methods without having to use the 2 if statements in the swagger handler to determine what the paths should be?

andrew-welker avatar Jul 24 '25 13:07 andrew-welker

@copilot Can we use attributes from existing swashbuckle nuget packages to add metadata to the handlers and their methods without having to use the 2 if statements in the swagger handler to determine ...

I've implemented a custom attribute-based system to replace the hardcoded if statements in the SwaggerHandler. Since Swashbuckle.AspNetCore packages aren't compatible with .NET Framework 4.7.2, I created custom OpenAPI attributes that mimic Swashbuckle's approach:

  • HttpGetAttribute and HttpPostAttribute for HTTP method detection
  • OpenApiOperationAttribute for operation metadata (summary, description, operationId)
  • OpenApiResponseAttribute for response documentation
  • OpenApiParameterAttribute for parameter definitions
  • OpenApiRequestBodyAttribute for request body specifications

The SwaggerHandler now uses reflection to read these attributes instead of the hardcoded logic. I've updated several request handlers as examples (DevListRequestHandler, DevJsonRequestHandler, etc.) and the system falls back to the original logic for handlers without attributes, ensuring backward compatibility.

This makes the code much more maintainable and allows each handler to define its own OpenAPI metadata declaratively. Commit: 213973a

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • crl.entrust.net
    • Triggering command: dotnet restore src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj (dns block)
  • ocsp.entrust.net
    • Triggering command: dotnet restore src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jul 24 '25 13:07 Copilot

@copilot Looks good. Can you add the new attributes to the rest of the handlers that are defined in this repository?

andrew-welker avatar Jul 24 '25 13:07 andrew-welker

@copilot Looks good. Can you add the new attributes to the rest of the handlers that are defined in this repository?

I've added the OpenAPI attributes to all the remaining request handlers defined in this repository. This includes 13 additional handlers covering GET, POST, and mixed endpoint types. All handlers now have comprehensive OpenAPI metadata including operation summaries, descriptions, parameters, request bodies, and response codes.

The changes ensure complete API documentation coverage for:

  • Device-related handlers (DevProps, DevMethods, routing ports)
  • Join map handlers for bridges and devices
  • Type discovery handlers (with and without filters)
  • Debug-related handlers (app debug, sessions, stream debugging)
  • System utility handlers (tie lines, config management)

The system successfully builds and the SwaggerHandler can now use reflection to read these attributes for all endpoints. Commit: 95fc8dd

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • crl.entrust.net
    • Triggering command: dotnet build src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj --configuration Release (dns block)
  • ocsp.entrust.net
    • Triggering command: dotnet build src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj --configuration Release (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jul 24 '25 14:07 Copilot

@copilot This repository uses conventional commit syntax for commit messages. Can you add an empty commit with an appropriate feat message in order to trigger our CI actions?

andrew-welker avatar Jul 24 '25 14:07 andrew-welker

@copilot This repository uses conventional commit syntax for commit messages. Can you add an empty commit with an appropriate feat message in order to trigger our CI actions?

Added empty commit with conventional commit message "feat: add OpenAPI 3 documentation endpoint for Essentials CWS API" to trigger CI actions. Commit: 9c56b9b

Copilot avatar Jul 24 '25 14:07 Copilot

@copilot add attributes for missing HTTP methods like PUT and DELETE. Use conventional commit syntax.

andrew-welker avatar Jul 25 '25 13:07 andrew-welker

@copilot add attributes for missing HTTP methods like PUT and DELETE. Use conventional commit syntax.

Added HttpPutAttribute and HttpDeleteAttribute to the OpenAPI attributes system following the same pattern as the existing GET and POST attributes. The SwaggerHandler will automatically detect and process these new HTTP method attributes through reflection. Commit: 1c55003

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • crl.entrust.net
    • Triggering command: dotnet build src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj --configuration Release (dns block)
  • ocsp.entrust.net
    • Triggering command: dotnet build src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj --configuration Release (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jul 25 '25 13:07 Copilot