๐ Glider API
A FastAPI-inspired Dart backend server package for building APIs with ease
Glider API is a powerful, lightweight, and developer-friendly backend framework for Dart that brings the elegance and simplicity of FastAPI to the Dart ecosystem. Build robust REST APIs with minimal boilerplate code, automatic documentation generation, and built-in validation.
๐ Example API
Here's a complete working example of a REST API built with Glider API:
import 'package:glider_api/glider_api.dart';
Future<void> main() async {
final app = ApiClient();
app.enableDevelopmentMode(enableDocs: true);
app.use(GliderMiddleware.cors());
app.use(GliderMiddleware.jsonParser());
app.use(GliderMiddleware.errorHandler(includeStackTrace: true));
app.get('/', () => {'message': 'Hello from glider_api'});
var usersList = [];
app.get('/users', () => GliderResponse.ok(usersList));
app.post('/users', (GliderRequest req) async {
final name = await req.validateField('name', Validators.string(minLength: 2));
final email = await req.validateField('email', Validators.email);
usersList.add({'id': usersList.length + 1, 'name': name, 'email': email});
return GliderResponse.ok({'name': name, 'email': email});
});
app.patch('/users/<id>', (GliderRequest req) async {
final id = req.param('id');
final name = await req.validateField('name', Validators.string(minLength: 2));
final email = await req.validateField('email', Validators.email);
final user = usersList.firstWhere((user) => user['id'] == int.parse(id!));
user['name'] = name;
user['email'] = email;
return GliderResponse.ok(user);
});
app.delete('/users/<id>', (GliderRequest req) async {
final id = req.param('id');
usersList.removeWhere((user) => user['id'] == int.parse(id!));
return GliderResponse.ok({"message": "User deleted", "id": id, "users": usersList});
});
await app.listen(port: 8080);
}
Try it out:
# Run the example
dart run example/simple_api.dart
# Test the API
curl http://localhost:8080/
curl http://localhost:8080/users
curl -X POST http://localhost:8080/users -H "Content-Type: application/json" -d '{"name":"John Doe","email":"john@example.com"}'
โจ Features
๐ฏ Core Features
- FastAPI-inspired Syntax: Familiar and intuitive API design patterns
- Automatic Documentation: OpenAPI/Swagger docs generation out of the box
- Built-in Validation: Comprehensive request validation with custom validators
- Middleware Support: Flexible middleware system for cross-cutting concerns
- Type Safety: Full Dart type safety with generic route handlers
- Development Tools: Rich development experience with logging and debugging
๐ง Development Features
- Hot Reload: Development server with automatic reloading
- Request Logging: Detailed request/response logging for debugging
- Error Handling: Comprehensive error handling with stack traces
- CORS Support: Built-in CORS middleware for cross-origin requests
- JSON Parsing: Automatic JSON request body parsing
๐ Documentation & API
- Auto-generated Docs: Interactive API documentation at
/docs - OpenAPI Spec: Standard OpenAPI 3.0 specification generation
- ReDoc Support: Beautiful documentation with ReDoc
- Schema Learning: Automatic schema inference from request/response data
๐ก๏ธ Security & Validation
- Input Validation: Built-in validators for strings, emails, numbers, etc.
- Custom Validators: Create your own validation rules
- Error Responses: Standardized error response format
- Request Sanitization: Automatic request data sanitization
๐ Quick Start
Installation
Add glider_api to your pubspec.yaml:
dependencies:
glider_api: ^0.0.1
Basic Example
import 'package:glider_api/glider_api.dart';
Future<void> main() async {
final app = ApiClient();
// Enable development mode with docs
app.enableDevelopmentMode(enableDocs: true);
// Add global middleware
app.use(GliderMiddleware.cors());
app.use(GliderMiddleware.jsonParser());
app.use(GliderMiddleware.errorHandler(includeStackTrace: true));
// Define routes
app.get('/', () => {'message': 'Hello from glider_api!'});
app.get('/users', () => GliderResponse.ok([
{'id': 1, 'name': 'John Doe', 'email': 'john@example.com'},
{'id': 2, 'name': 'Jane Smith', 'email': 'jane@example.com'},
]));
app.post('/users', (GliderRequest req) async {
final name = await req.validateField('name', Validators.string(minLength: 2));
final email = await req.validateField('email', Validators.email);
return GliderResponse.ok({
'id': DateTime.now().millisecondsSinceEpoch,
'name': name,
'email': email,
});
});
// Start the server
await app.listen(port: 8080);
}
๐๏ธ PostgreSQL Integration Demo
Setting up PostgreSQL with Glider API
This section demonstrates how to integrate PostgreSQL with your Glider API application.
1. Install PostgreSQL Dependencies
# Install PostgreSQL client for Dart
dart pub add postgres
2. Database Configuration
import 'package:postgres/postgres.dart';
class DatabaseConfig {
static const String host = 'localhost';
static const int port = 5432;
static const String database = 'glider_api_db';
static const String username = 'postgres';
static const String password = 'your_password';
static PostgreSQLConnection get connection => PostgreSQLConnection(
host,
port,
database,
username: username,
password: password,
);
}
3. Database Service
class UserService {
final PostgreSQLConnection _db;
UserService(this._db);
Future<void> initialize() async {
await _db.open();
// Create users table
await _db.execute('''
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''');
}
Future<List<Map<String, dynamic>>> getAllUsers() async {
final results = await _db.query('SELECT * FROM users ORDER BY created_at DESC');
return results.map((row) => {
'id': row[0],
'name': row[1],
'email': row[2],
'created_at': row[3],
}).toList();
}
Future<Map<String, dynamic>?> getUserById(int id) async {
final results = await _db.query(
'SELECT * FROM users WHERE id = @id',
substitutionValues: {'id': id},
);
if (results.isEmpty) return null;
final row = results.first;
return {
'id': row[0],
'name': row[1],
'email': row[2],
'created_at': row[3],
};
}
Future<Map<String, dynamic>> createUser(String name, String email) async {
final results = await _db.query(
'INSERT INTO users (name, email) VALUES (@name, @email) RETURNING *',
substitutionValues: {'name': name, 'email': email},
);
final row = results.first;
return {
'id': row[0],
'name': row[1],
'email': row[2],
'created_at': row[3],
};
}
Future<Map<String, dynamic>?> updateUser(int id, String name, String email) async {
final results = await _db.query(
'UPDATE users SET name = @name, email = @email WHERE id = @id RETURNING *',
substitutionValues: {'id': id, 'name': name, 'email': email},
);
if (results.isEmpty) return null;
final row = results.first;
return {
'id': row[0],
'name': row[1],
'email': row[2],
'created_at': row[3],
};
}
Future<bool> deleteUser(int id) async {
final results = await _db.query(
'DELETE FROM users WHERE id = @id',
substitutionValues: {'id': id},
);
return results.isNotEmpty;
}
}
4. API with PostgreSQL Integration
import 'package:glider_api/glider_api.dart';
import 'package:postgres/postgres.dart';
Future<void> main() async {
final app = ApiClient();
// Initialize database
final db = DatabaseConfig.connection;
final userService = UserService(db);
await userService.initialize();
app.enableDevelopmentMode(enableDocs: true);
app.use(GliderMiddleware.cors());
app.use(GliderMiddleware.jsonParser());
app.use(GliderMiddleware.errorHandler(includeStackTrace: true));
// User routes with PostgreSQL
app.get('/users', () async {
final users = await userService.getAllUsers();
return GliderResponse.ok(users);
});
app.get('/users/<id>', (GliderRequest req) async {
final id = int.tryParse(req.param('id') ?? '');
if (id == null) {
return GliderResponse.badRequest('Invalid user ID');
}
final user = await userService.getUserById(id);
if (user == null) {
return GliderResponse.notFound('User not found');
}
return GliderResponse.ok(user);
});
app.post('/users', (GliderRequest req) async {
final name = await req.validateField('name', Validators.string(minLength: 2));
final email = await req.validateField('email', Validators.email);
try {
final user = await userService.createUser(name, email);
return GliderResponse.created(user);
} catch (e) {
if (e.toString().contains('duplicate key')) {
return GliderResponse.conflict('Email already exists');
}
rethrow;
}
});
app.patch('/users/<id>', (GliderRequest req) async {
final id = int.tryParse(req.param('id') ?? '');
if (id == null) {
return GliderResponse.badRequest('Invalid user ID');
}
final name = await req.validateField('name', Validators.string(minLength: 2));
final email = await req.validateField('email', Validators.email);
final user = await userService.updateUser(id, name, email);
if (user == null) {
return GliderResponse.notFound('User not found');
}
return GliderResponse.ok(user);
});
app.delete('/users/<id>', (GliderRequest req) async {
final id = int.tryParse(req.param('id') ?? '');
if (id == null) {
return GliderResponse.badRequest('Invalid user ID');
}
final deleted = await userService.deleteUser(id);
if (!deleted) {
return GliderResponse.notFound('User not found');
}
return GliderResponse.ok({'message': 'User deleted successfully'});
});
await app.listen(port: 8080);
}
๐ API Reference
HTTP Methods
Glider API supports all standard HTTP methods:
app.get('/path', handler);
app.post('/path', handler);
app.put('/path', handler);
app.patch('/path', handler);
app.delete('/path', handler);
app.head('/path', handler);
app.options('/path', handler);
Request Validation
// String validation
final name = await req.validateField('name', Validators.string(minLength: 2, maxLength: 50));
// Email validation
final email = await req.validateField('email', Validators.email);
// Number validation
final age = await req.validateField('age', Validators.number(min: 0, max: 120));
// Custom validation
final customField = await req.validateField('custom', Validators.custom((value) {
if (value.toString().contains('forbidden')) {
throw ValidationError('Value contains forbidden content');
}
return value;
}));
Response Helpers
// Success responses
GliderResponse.ok(data);
GliderResponse.created(data);
GliderResponse.noContent();
// Error responses
GliderResponse.badRequest('Invalid data');
GliderResponse.unauthorized('Authentication required');
GliderResponse.forbidden('Access denied');
GliderResponse.notFound('Resource not found');
GliderResponse.conflict('Resource conflict');
GliderResponse.internalServerError('Server error');
Middleware
// CORS middleware
app.use(GliderMiddleware.cors());
// JSON parser middleware
app.use(GliderMiddleware.jsonParser());
// Error handler middleware
app.use(GliderMiddleware.errorHandler(includeStackTrace: true));
// Custom middleware
app.use((request, next) async {
// Pre-processing
print('Request to: ${request.path}');
final response = await next();
// Post-processing
print('Response status: ${response.statusCode}');
return response;
});
๐ Deployment Guide
Local Development
# Clone the repository
git clone <your-repo-url>
cd mk_backend
# Install dependencies
dart pub get
# Run the example
dart run example/simple_api.dart
Docker Deployment
1. Create Dockerfile
FROM dart:stable AS build
WORKDIR /app
COPY pubspec.* ./
RUN dart pub get
COPY . .
RUN dart compile exe bin/glider_api.dart -o bin/glider_api
FROM ubuntu:latest
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /app/bin/glider_api /app/bin/glider_api
EXPOSE 8080
CMD ["/app/bin/glider_api"]
2. Build and Run
# Build the Docker image
docker build -t glider-api .
# Run the container
docker run -p 8080:8080 glider-api
Cloud Deployment
Heroku Deployment
- Create
Procfile:
web: dart run bin/glider_api.dart
- Deploy to Heroku:
heroku create your-app-name
git push heroku main
Google Cloud Run
- Deploy to Cloud Run:
gcloud run deploy glider-api \
--source . \
--platform managed \
--region us-central1 \
--allow-unauthenticated
AWS Lambda (with custom runtime)
- Create deployment package:
dart compile exe bin/glider_api.dart -o bootstrap
zip -r function.zip bootstrap
- Deploy to Lambda:
aws lambda create-function \
--function-name glider-api \
--runtime provided.al2 \
--handler bootstrap \
--zip-file fileb://function.zip
๐งช Testing
# Run tests
dart test
# Run tests with coverage
dart test --coverage=coverage
genhtml coverage/lcov.info -o coverage/html
๐ Examples
Check out the example/ directory for complete working examples:
- Simple API (
example/simple_api.dart): Basic CRUD operations - Matrimony API (
example/matrimonry_api.dart): User management system
๐ค Contributing
We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Open Source Status
โ ๏ธ Important Notice: This repository is currently not open-source yet, but it will be made open-source soon! We're working hard to prepare it for the open-source community.
๐จโ๐ป Developer Details
Developed with โค๏ธ by Mirshad Kvr
Made with โค๏ธ for the Dart community
โญ Star this repository if you find it helpful!