Added authentication
This commit is contained in:
@@ -1,162 +1,154 @@
|
||||
# EonaCat.DoxaApi
|
||||
|
||||
A self-contained, API documentation UI for ASP.NET Core
|
||||
**A modern, self-contained, dependency-free API documentation UI for ASP.NET Core**
|
||||
|
||||
EonaCat.DoxaApi scans your controllers with plain `System.Reflection` and ASP.NET Core's own `IActionDescriptorCollectionProvider`,
|
||||
builds a small OpenAPI-like JSON document with `System.Text.Json`, and serves a UI
|
||||
This can also be used in an offline environment!
|
||||
DoxaApi reflects over your controllers, generates an OpenAPI-compatible document, and serves a fast, single-page documentation UI with zero JavaScript dependencies. No npm build step, no CDN calls, no telemetry - one NuGet package, one line in `Program.cs`.
|
||||
|
||||

|
||||

|
||||
|
||||
## Install
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
dotnet add package EonaCat.DoxaApi
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```csharp
|
||||
using EonaCat.DoxaApi;
|
||||
using EonaCat.DoxaApi.Middleware;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddDoxaApi(options =>
|
||||
{
|
||||
options.Title = "My API";
|
||||
options.Description = "Internal service API";
|
||||
options.AccentColor = "#6366f1"; // any hex color
|
||||
options.Title = "Sample API";
|
||||
options.Description = "A demo service showing off the DoxaApi UI.";
|
||||
options.Version = "v1";
|
||||
options.AccentColor = "#6366f1";
|
||||
|
||||
// Optional: declare how clients authenticate.
|
||||
options.AddBearerAuth(description: "Sign in and paste your JWT here.");
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseRouting();
|
||||
app.UseDoxaApi(); // serves UI at /doxa and spec at /doxa/DoxaApi.json
|
||||
app.UseDoxaApi(options => options.RoutePrefix = "doxa");
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
Run your app and open `https://localhost:xxxx/doxa`.
|
||||
Run the app and open `/doxa`. That's the whole setup.
|
||||
|
||||
## Features
|
||||
|
||||
- **Route-table style navigation** - endpoints grouped by controller, each method color-coded (GET/POST/PUT/PATCH/DELETE), searchable with `/`.
|
||||
- **Schema viewer** - nested request/response shapes rendered as readable, syntax-colored trees, with required fields marked.
|
||||
- **Try it out** - a real three-pane layout: browse → inspect → call, with path/query/header inputs, an editable JSON body (pre-filled with a generated example), and a live response panel with status, timing, and syntax-highlighted JSON.
|
||||
- **Light & dark themes**, persisted, with a system-preference default.
|
||||
- **XML doc comment support** - `/// <summary>`, `<param>`, and `<returns>` are read directly from your project's generated `.xml` doc file (enable `<GenerateDocumentationFile>true</GenerateDocumentationFile>` in your csproj).
|
||||
- **Attributes for fine control**: `[EonaCat.DoxaApiGroup]`, `[EonaCat.DoxaApiSummary]`, `[EonaCat.DoxaApiDescription]`, `[EonaCat.DoxaApiExample]`, `[EonaCat.DoxaApiHidden]`.
|
||||
- **Zero external NuGet dependencies** - only references your app's own ASP.NET Core shared framework.
|
||||
|
||||
## Authoring your documentation
|
||||
|
||||
DoxaApi reads standard `///` XML doc comments and a handful of optional attributes:
|
||||
|
||||
```csharp
|
||||
[ApiController]
|
||||
[Route("api/users")]
|
||||
[DoxaApiGroup("Users")]
|
||||
public class UsersController : ControllerBase
|
||||
{
|
||||
/// <summary>Creates a new user.</summary>
|
||||
/// <param name="request">The user to create.</param>
|
||||
/// <returns>The created user.</returns>
|
||||
[HttpPost]
|
||||
[DoxaApiExample("""{ "name": "Grace Hopper", "email": "grace@example.com" }""")]
|
||||
public ActionResult<User> Create([FromBody] CreateUserRequest request) { ... }
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[Obsolete("Use POST /api/users/{id}/archive instead.")]
|
||||
public IActionResult Delete(Guid id) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
| Attribute | Purpose |
|
||||
|||
|
||||
| `[DoxaApiGroup("Name")]` | Groups endpoints in the nav (class or method level) |
|
||||
| `[DoxaApiSummary("...")]` | Overrides the auto-generated summary |
|
||||
| `[DoxaApiDescription("...")]` | Adds a longer description |
|
||||
| `[DoxaApiExample("""{ ... }""")]` | Supplies a realistic request body example |
|
||||
| `[DoxaApiHidden]` | Excludes a controller/action from the docs entirely |
|
||||
| `[DoxaApiAuth("schemeId")]` | Marks an endpoint as requiring a specific security scheme |
|
||||
| `[DoxaApiAllowAnonymous]` | Marks an endpoint as public, overriding any default scheme |
|
||||
| `[Obsolete("...")]` | Flags the endpoint as deprecated in the UI |
|
||||
|
||||
Standard ASP.NET Core `[Authorize]` / `[AllowAnonymous]` attributes are also detected automatically.
|
||||
|
||||
|
||||
|
||||
## Authentication
|
||||
|
||||
Declare the security schemes your API actually uses, and DoxaApi takes care of the rest - detecting which endpoints need them, badging them in the docs, and prompting for credentials in the UI's **Authorize** dialog.
|
||||
|
||||
```csharp
|
||||
builder.Services.AddDoxaApi(options =>
|
||||
{
|
||||
options.AddBearerAuth(); // Authorization: Bearer <token>
|
||||
options.AddApiKeyAuth("apiKey", "X-API-Key", "header"); // custom header
|
||||
options.AddBasicAuth(); // HTTP Basic
|
||||
options.AddOAuth2ClientCredentials("oauth2",
|
||||
tokenUrl: "https://auth.example.com/connect/token",
|
||||
scopes: new() { ["api.read"] = "Read access" });
|
||||
|
||||
options.DefaultSecurityScheme = "bearer"; // applied to any [Authorize] endpoint
|
||||
// without an explicit [DoxaApiAuth]
|
||||
});
|
||||
```
|
||||
|
||||
Credentials entered in the UI are stored in the browser's `localStorage` (never sent anywhere except the documented API itself) and are automatically attached to every "Try it" request, cURL snippet, and generated code sample for endpoints that require them.
|
||||
|
||||
|
||||
|
||||
## Mock server
|
||||
|
||||
Every endpoint can return a schema-shaped fake response without touching your real controllers - flip the **"Send to mock server"** toggle in the Try-it panel, or call it directly:
|
||||
|
||||
```
|
||||
GET /doxa/mock?operationId=Users_GetById
|
||||
```
|
||||
|
||||
Useful for frontend teams who need to start building against an API before the backend is finished. Disable it with `options.EnableMockServer = false;` if you'd rather it not be exposed.
|
||||
|
||||
## API console
|
||||
|
||||
The **Console** (top bar) lets you fire an arbitrary HTTP request - any method, any absolute URL, custom headers and body - through the server rather than the browser. Because the request happens server-side, it isn't subject to the browser's CORS policy, which makes it useful for poking at a different host than the one serving the docs. Disable with `options.EnableConsole = false;`.
|
||||
|
||||
## Code generation
|
||||
|
||||
Every endpoint's Try-it panel includes a **Code** tab with ready-to-paste snippets in cURL, JavaScript (`fetch`), Python (`requests`), C# (`HttpClient`), and Go (`net/http`) - automatically including whatever auth headers you've configured.
|
||||
|
||||
## Comparing spec versions
|
||||
|
||||
Click **Compare** and upload a previous (or upcoming) OpenAPI/Swagger/DoxaApi JSON file to see exactly which endpoints were added, removed, or changed - including parameter, request-body, and security differences. Handy in code review for catching accidental breaking changes before they ship.
|
||||
|
||||
## Import & export
|
||||
|
||||
DoxaApi documents are available at:
|
||||
|
||||
- `/doxa/doxaApi.json` - native format
|
||||
- `/doxa/openapi.json` - OpenAPI 3.0.3
|
||||
- `/doxa/swagger.json` - Swagger 2.0
|
||||
|
||||
...and the **Import** button accepts any of the three formats back in, so you can merge in a hand-written spec, or load an API documented elsewhere.
|
||||
|
||||
## Configuration reference
|
||||
|
||||
```csharp
|
||||
builder.Services.AddDoxaApi(options =>
|
||||
{
|
||||
options.Title = "My API"; // shown in the top bar and browser tab
|
||||
options.Description = "..."; // shown on the welcome screen
|
||||
options.Title = "My API";
|
||||
options.Description = "...";
|
||||
options.Version = "v1";
|
||||
options.RoutePrefix = "doxa"; // UI served at /{RoutePrefix}
|
||||
options.AccentColor = "#6366f1"; // primary button/accent color
|
||||
options.Theme = "auto"; // "auto" | "light" | "dark"
|
||||
options.RoutePrefix = "doxa"; // served at /doxa
|
||||
options.Servers.Add("https://api.example.com");
|
||||
options.Theme = "auto"; // "auto" | "dark" | "light"
|
||||
options.AccentColor = "#6366f1";
|
||||
options.EnableMockServer = true;
|
||||
options.EnableConsole = true;
|
||||
});
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
```csharp
|
||||
[EonaCat.DoxaApiGroup("Users")] // override the left-nav group name
|
||||
public class UsersController : ControllerBase
|
||||
{
|
||||
/// <summary>Lists all users.</summary> // picked up automatically
|
||||
[HttpGet]
|
||||
public ActionResult<List<User>> GetUsers() => ...;
|
||||
|
||||
[HttpPost]
|
||||
[EonaCat.DoxaApiExample("""{ "name": "Ada" }""")] // overrides the auto-generated example
|
||||
public ActionResult<User> Create(CreateUserRequest request) => ...;
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[EonaCat.DoxaApiHidden] // omit from docs entirely
|
||||
public IActionResult Delete(Guid id) => ...;
|
||||
}
|
||||
```
|
||||
|
||||
## OpenAPI & Swagger
|
||||
|
||||
EonaCat.DoxaApi exposes dedicated endpoints for importing and exporting industry-standard spec formats alongside its own native JSON.
|
||||
|
||||
### Export
|
||||
|
||||
| URL | Format | Notes |
|
||||
|-----|--------|-------|
|
||||
| `/{RoutePrefix}/DoxaApi.json` | Native EonaCat.DoxaApi JSON | Always available; used by the built-in UI |
|
||||
| `/{RoutePrefix}/openapi.json` | **OpenAPI 3.0.3** | Import into Postman, Insomnia, Stoplight, etc. |
|
||||
| `/{RoutePrefix}/swagger.json` | **Swagger 2.0** | Import into older tools, AWS API Gateway, Azure APIM, etc. |
|
||||
|
||||
```bash
|
||||
# Download the OpenAPI 3.0 spec
|
||||
curl http://localhost:5000/doxa/openapi.json -o openapi.json
|
||||
|
||||
# Download the Swagger 2.0 spec
|
||||
curl http://localhost:5000/doxa/swagger.json -o swagger.json
|
||||
```
|
||||
|
||||
### Import
|
||||
|
||||
`POST /{RoutePrefix}/import`
|
||||
|
||||
Send any OpenAPI 3.x or Swagger 2.0 JSON document in the request body. The server detects the format automatically and returns the native EonaCat.DoxaApi document.
|
||||
|
||||
```bash
|
||||
# Import a third-party OpenAPI spec and get the EonaCat.DoxaApi document back
|
||||
curl -X POST http://localhost:5000/doxa/import \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-binary @path/to/openapi.json
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Preview any public or third-party OpenAPI/Swagger spec in the EonaCat.DoxaApi UI
|
||||
- Validate that your spec round-trips correctly through import → export
|
||||
- Use the import endpoint as a conversion proxy (OpenAPI 3 ↔ Swagger 2)
|
||||
|
||||
### Programmatic use
|
||||
|
||||
The `OpenApiExporter`, `SwaggerExporter`, and `OpenApiImporter` classes in the
|
||||
`EonaCat.DoxaApi.Interop` namespace are `public static` and can be used directly in your
|
||||
own code:
|
||||
|
||||
```csharp
|
||||
using EonaCat.DoxaApi.Interop;
|
||||
using EonaCat.DoxaApi.Models;
|
||||
|
||||
// Export: ApiDocument → OpenAPI 3.0 JsonObject
|
||||
ApiDocument doc = /* ... */;
|
||||
System.Text.Json.Nodes.JsonObject openApi = OpenApiExporter.Export(doc);
|
||||
string json = openApi.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
|
||||
|
||||
// Export: ApiDocument → Swagger 2.0 JsonObject
|
||||
System.Text.Json.Nodes.JsonObject swagger = SwaggerExporter.Export(doc);
|
||||
|
||||
// Import: OpenAPI 3.x or Swagger 2.0 string → ApiDocument
|
||||
ApiDocument imported = OpenApiImporter.Import(File.ReadAllText("openapi.json"));
|
||||
|
||||
// Import from a Stream
|
||||
await using var stream = File.OpenRead("swagger.json");
|
||||
ApiDocument imported2 = OpenApiImporter.Import(stream);
|
||||
```
|
||||
|
||||
## Sample project
|
||||
|
||||
See `/sample/SampleApi` for a complete working example with two controllers (`Users`, `Orders`) demonstrating nested objects, enums, arrays, path/query parameters, and a deprecated endpoint.
|
||||
|
||||
```bash
|
||||
cd sample/SampleApi
|
||||
dotnet run
|
||||
# open http://localhost:5000/doxa
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
```
|
||||
Reference in New Issue
Block a user