swagger-api/swagger-ui
Swagger UI renders interactive API docs from your OpenAPI (Swagger) spec, letting teams and consumers explore endpoints without implementation details. Available as npm packages (swagger-ui, swagger-ui-dist) and Docker for easy hosting and bundling.
## Getting Started
### Minimal Setup in Laravel
1. **Install via npm** (recommended for Laravel projects):
```bash
npm install swagger-ui-dist --save
Or use the standalone dist:
npm install swagger-ui-dist@latest --save
Publish OpenAPI/Swagger Spec:
darkaonline/l5-swagger or manually generate a public/api-docs.json file via:
// routes/api.php
Route::get('/api-docs', function () {
return response()->json(\OpenApi\Generator::openapi());
});
Serve Swagger UI:
resources/views/vendor/swagger.blade.php):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>API Documentation</title>
<link rel="stylesheet" type="text/css" href="{{ asset('vendor/swagger-ui-dist/swagger-ui.css') }}">
</head>
<body>
<div id="swagger-ui"></div>
<script src="{{ asset('vendor/swagger-ui-dist/swagger-ui-bundle.js') }}"></script>
<script>
const ui = SwaggerUIBundle({
url: "{{ route('api.docs') }}",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
layout: "StandaloneLayout"
});
</script>
</body>
</html>
Route::get('/docs', [\App\Http\Controllers\SwaggerController::class, 'show']);
First Use Case:
/docs to visualize your API endpoints.darkaonline/l5-swagger to auto-generate OpenAPI specs from route annotations:
use OpenApi\Annotations as OA;
/**
path="/users",
summary="Get all users",
@OA\Response(response="200", description="List of users")
- **Versioned Docs**:
Serve multiple specs (e.g., `v1`, `v2`) via route parameters:
```php
Route::get('/docs/{version}', function ($version) {
return response()->json(\OpenApi\Generator::openapi($version));
});
API Key Auth:
Configure in swagger-ui-bundle.js:
const ui = SwaggerUIBundle({
url: "/api-docs",
oauth2RedirectUrl: window.location.origin + "/docs/oauth2-redirect.html",
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
layout: "StandaloneLayout",
// Add API key auth
requestInterceptor: (request) => {
request.headers['X-API-KEY'] = 'your-api-key';
return request;
}
});
OAuth2 Flow: Define flows in your OpenAPI spec:
components:
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://example.com/oauth/authorize
tokenUrl: https://example.com/oauth/token
scopes:
read: Grants read access
Initialize OAuth in Swagger UI:
ui.initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret", // Avoid in production!
appName: "your-app-name",
scopeSeparator: " ",
additionalQueryStringParams: {}
});
Theming: Override CSS variables in a custom stylesheet:
/* resources/css/swagger-ui.css */
:root {
--swagger-primary-color: #6200ee;
--swagger-background-color: #f5f5f5;
}
Load it after Swagger UI’s CSS:
<link rel="stylesheet" href="{{ asset('css/swagger-ui.css') }}">
Plugins: Extend functionality via plugins (e.g., add a custom button):
ui.initOAuth({ ... });
ui.preauthorizeApiKey("api_key", "your-api-key");
// Add a custom plugin
ui.plugins = ui.plugins || [];
ui.plugins.push({
components: {
Topbar: {
Component: function (props) {
return (
<div>
<button onClick={() => alert('Custom Action')}>
Custom Button
</button>
</div>
);
}
}
}
});
Deep Linking: Enable for shareable URLs:
const ui = SwaggerUIBundle({
url: "/api-docs",
deepLinking: true,
// ...
});
Lazy Loading: Load Swagger UI dynamically on demand:
// resources/js/swagger-loader.js
export default function loadSwaggerUI() {
const script = document.createElement('script');
script.src = '/vendor/swagger-ui-dist/swagger-ui-bundle.js';
script.onload = () => {
const ui = SwaggerUIBundle({ url: "/api-docs", dom_id: '#swagger-ui' });
};
document.body.appendChild(script);
}
Call it conditionally:
@if(config('app.debug'))
<div id="swagger-ui"></div>
<script src="{{ asset('js/swagger-loader.js') }}"></script>
@endif
Cache Spec: Cache the OpenAPI spec response in Laravel:
Route::get('/api-docs', function () {
return Cache::remember('api-docs', now()->addHours(1), function () {
return response()->json(\OpenApi\Generator::openapi());
});
});
CORS Issues:
// app/Http/Middleware/Cors.php
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', env('SWAGGER_UI_ORIGIN', '*'))
->header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
}
tokenUrl and authorizationUrl are CORS-enabled.OAuth2 Client Secret Leak:
clientSecret in frontend JS. Use a backend proxy:
// Safe: Proxy OAuth2 flow through Laravel
ui.initOAuth({
clientId: "your-client-id",
// clientSecret handled server-side
appName: "your-app-name",
// Redirect to Laravel endpoint for token exchange
onOAuthComplete: (response) => {
fetch('/docs/oauth2-callback', {
method: 'POST',
body: JSON.stringify(response),
headers: { 'Content-Type': 'application/json' }
}).then(() => window.location.reload());
}
});
Deep Linking Conflicts:
/users/{user}), escape { and } in operationId:
paths:
/users/{user_id}:
get:
operationId: getUserById # Avoid: getUserBy{user_id}
Spec Validation Errors:
zircote/swagger-php to validate specs:
use Zircote\Swagger\Validator;
$validator = new Validator();
$result = $validator->validateFile('api-docs.json');
if (!$result->isValid()) {
throw new \Exception("Invalid OpenAPI spec: " . $result->errorsAsString());
}
Console Logs:
const ui = SwaggerUIBundle({
url: "/api-docs",
debug: true, // Logs to console
// ...
});
Network Tab:
200).Network tab.How can I help you explore Laravel packages today?