πΆ Oficial Darto Documentation
Darto is a microframework inspired by Express for building web applications in Dart. It offers a simple API with familiar middleware patterns that make it easy to get started with web development!
If you find Darto useful, please consider supporting its development πBuy Me a Coffee.π Your support helps us improve the framework and make it even better!
Note: If you want data persistence, you can use the π·Dartonic package. It is a simple Query Builder for Dart inspired by Drizzle to work with databases like MySQL, PostgreSQL, SQLite.
- Installation π¦
- Basic Usage π
- Route Parameters and Query Parameters π
- Returning implicit responses
- Config static files
- Upload Files
- Middleware Usage π οΈ
- Example Routes π‘
- Sub-Routes π¦
- WebSocket Integration π
- Send email π§
- HTTP Methods π
- Template Engine Configuration π¨
- Response Methods π€
- Main Features
Run the following command to install Darto:
dart pub add darto
or
Add the package to your pubspec.yaml
file:
dependencies:
darto: ^0.0.25
Then, run the following command:
flutter pub get
import 'package:darto/darto.dart';
void main() {
final app = Darto();
// Example route
app.get('/ping', (Request req, Response res) {
res.send('pong');
});
app.listen(3000);
}
void main() {
final app = Darto();
// Example route with route parameters
app.get('/user/:id', (Request req, Response res) {
final id = req.params['id'];
res.send('User ID: $id');
});
// Example route with query parameters
app.get('/search?name=John&age=20', (Request req, Response res) {
final name = req.query['name'];
final age = req.query['age'];
res.send('Name: $name, Age: $age');
});
}
void main() {
final app = Darto();
app.get('/hello', (Request req, Response res) {
return 'Hello, World!';
});
}
To upload files, you can use the class Upload. Here's an example:
void main() {
// Serve static files from the "public" folder (using default options)
// You can access the static files in browser using the following URL:
// http://localhost:3000/public/index.html
app.static('public');
// Or you can send the file as a response
app.get('/images', (Request req, Response res) {
res.sendFile('public/image.png');
});
}
To upload files, you can use the class Upload. Here's an example:
void main() {
// Instance of Upload class and define the upload directory
final upload = Upload(join(Directory.current.path, 'uploads'));
// Route to handle file upload
app.post('/upload', upload.single('file'), (Request req, Response res) {
if (req.file != null) {
res.json(req.file);
} else {
res.status(BAD_REQUEST).json({'error': 'No file uploaded'});
}
});
}
To enable CORS (Cross-Origin Resource Sharing), you can use useCors
helper. Here's an example:
void main() {
final app = Darto();
app.useCors(
origin: [
'https://example.com',
'https://another-do
8000
main.org'
]
);
// Allow specific methods and headers
app.useCors(
methods: ['GET', 'POST'],
headers: ['Content-Type', 'Authorization'],
);
}
Darto supports different types of middleware to handle various tasks throughout the request-response lifecycle.
Global middlewares are applied to all incoming requests. You can register a global middleware using the use
method.
void main() {
final app = Darto();
// Global middleware to log incoming requests
app.use((Request req, Response res, Next next) {
print('π Request: ${req.method} ${req.originalUrl}');
next();
});
app.listen(3000, () {
print('πΉ Server is running at http://localhost:3000');
});
}
Error middlewares are applied to all incoming requests. You can register a error middleware using the use
method.
void main() {
final app = Darto();
app.timeout(5000);
// Error middleware to handle timeouts
app.use((Err err, Request req, Response res, Next next) {
if (req.timedOut && !res.finished) {
res.status(SERVICE_UNAVAILABLE).json({
'error': 'Request timed out or internal error occurred.',
});
} else {
next(err);
}
});
}
Route-specific middlewares are applied to specific routes. You can pass a middleware as an optional parameter when defining a route.
void main() {
final app = Darto();
// Middleware specific to a route
app.use('/task/:id', (Request req, Response res, Next next) {
print('Request Type: ${req.method}');
next();
});
app.get('/task/:id', (Request req, Response res) {
final id = req.params['id'];
res.send({'task': id});
});
// You can use the middleware directly in the route definition
// Create a middleware function
logMiddleware(Request req, Response res, Next next) {
print('Request Type: ${req.method}');
next();
};
// Example route with middleware
app.get('/user/:id', logMiddleware, (Request req, Response res) {
final id = req.params['id'];
res.send({'user': id});
});
app.listen(3000, () {
print('πΉ Server is running at http://localhost:3000');
});
}
// Route to get user information by ID
app.get('/user/:id', (Request req, Response res) {
final id = req.params['id'];
res.send({'user': id});
});
// Route to redirect to an external site
app.get('/go', (Request req, Response res) {
res.redirect('http://example.com');
});
// Route to get a body
app.get('/file', (Request req, Response res) async {
final body = await req.body;
res.send(body);
});
Darto also supports the creation of sub-routes so you can better organize your application. By mounting a router on a specific path prefix, all the routes defined in the sub-router will be grouped under that prefix. This makes it easy to modularize your code and maintain clarity in your route definitions. For example, you can create an authentication router that handles all routes under /auth
:
Router authRouter() {
final router = Router();
router.get('/login', (Request req, Response res) {
res.send('Login page');
});
return router;
}
void main() {
final app = Darto();
// Mount the authRouter on the "/auth" prefix:
app.use('/auth', authRouter());
}
This enables clear separation of concerns and enhances the reusability of your routing logic. π
Darto integrates with WebSockets to facilitate real-time communication in your applications. With WebSocket support, you can easily create interactive features like live chats, notifications, or interactive dashboards. The framework provides a simple API to handle WebSocket events:
import 'package:darto/darto.dart';
void main() {
final app = Darto();
// Initialize WebSocket server
final server = DartoWebsocket();
// Handle new WebSocket connections
server.on('connection', (DartoSocketChannel socket) {
socket.stream.listen((message) {
socket.sink.add('Echo: $message');
});
});
// Start the HTTP and WebSocket servers
app.listen(3000, () {
server.listen('0.0.0.0', 3001);
print('HTTP server running on http://localhost:3000');
});
}
// Get instance of DartoMailer
final mailer = DartoMailer();
// Create a transporter instance
final transporter = mailer.createTransport(
host: 'sandbox.smtp.mailtrap.io',
port: 2525,
ssl: false,
auth: {
'username': 'seu-username',
'password': 'sua-password',
},
);
// Send an email using the transporter
app.post('/send-email', (Request req, Response res) async {
final success = await transporter.sendMail(
from: 'seu-email@gmail.com',
to: 'destinatario@exemplo.com',
subject: 'Teste de Email via Gmail',
html: '''
<h1>Bem-vindo ao Darto Mailer!</h1>
<p>Este Γ© um email de teste usando Darto Mailer.</p>
''',
);
if (success) {
return res.json({'message': 'Email enviado com sucesso!'});
} else {
return res.status(500).json({'error': 'Falha ao enviar email'});
}
});
Darto supports server-side rendering using a template engine. By default, it integrates with the Mustache template engine. You can configure the engine globally in your application as shown below:
import 'dart:io';
import 'package:path/path.dart';
import 'package:darto/darto.dart';
void main() {
final app = Darto();
// Set the directory where your template files are located
app.set('views', join(Directory.current.path, 'lib', 'pages'));
// Specify the view engine extension (e.g., "mustache")
app.set('view engine', 'mustache');
// Define a route to render a template (without the extension)
app.get('/', (Request req, Response res) {
res.render('index', {
'title': 'Welcome to Server Side Rendering',
'header': 'Hello from Darto!',
'message': 'This demonstrates how to configure a template engine in Darto using Mustache.'
});
});
app.listen(3000, () {
print('HTTP server running on http://localhost:3000');
});
}
Create your template file at lib/pages/index.mustache
:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{title}}</title>
</head>
<body>
<h1>{{header}}</h1>
<p>{{message}}</p>
</body>
</html>
Darto supports the following HTTP methods:
- GET
Retrieves data from the server.
- Example:
app.get('/users', (Request req, Response res) => res.send('Get users'));
- Example:
- POST
Sends data to the server to create a new resource.
- Example:
app.post('/users', (Request req, Response res) => res.send('Create user'));
- Example:
- PUT
Updates an existing resource on the server.
- Example:
app.put('/users/:id', (Request req, Response res) => res.send('Update user'));
- Example:
- DELETE
Deletes a resource from the server.
- Example:
app.delete('/users/:id', (Request req, Response res) => res.send('Delete user'));
- Example:
- PATCH
Updates a specific field of a resource on the server.
- Example:
app.patch('/users/:id', (Request req, Response res) => res.send('Update user'));
- Example:
- HEAD
Retrieves the headers of a resource without the body.
- Example:
app.head('/users/:id', (Request req, Response res) => res.send('Get user'));
- Example:
- OPTIONS
Retrieves the supported HTTP methods for a resource.
- Example:
app.options('/users/:id', (Request req, Response res) => res.send('Get user'));
- Example:
- TRACE
Performs a message loop-back test along the path to the resource.
- Example:
app.trace('/users/:id', (Request req, Response res) => res.send('Get user'));
- Example:
Darto provides several methods to control the response sent to the client:
- send
Sends a response with the specified data.
- Example:
res.send('Hello, World!');
- Example:
- json
Sends a JSON response with the specified data.
- Example:
res.json({'message': 'Hello, World!'});
- Example:
- end
Ends the response and sends it to the client.
- Example:
res.end();
- Example:
res.end('Hello, World!');
- Example:
- status
Sets the HTTP status code for the response.
- Example:
res.status(200).send('OK');
- Example:
- redirect
Redirects the client to a new URL.
- Example:
res.redirect('https://example.com');
- Example:
- download
Initiates a file download by specifying the file path and optional options.
- Example:
res.download('path/to/file.txt', { filename: 'custom-filename.txt' });
- Example:
- sendFile
Sends a file as a response.
- Example:
res.sendFile('path/to/file.txt');
- Example:
- error
Sends an error response with the specified error message.
- Example:
res.error('An error occurred.');
- Example:
- cookie
Sets a cookie in the response.
- Example:
res.cookie('cookieName', 'cookieValue');
- Example:
- clearCookie
Clears a cookie from the response.
- Example:
res.clearCookie('cookieName');
- Example:
- render
Renders a template with the specified data and sends it as a response.
- Example:
res.render('template', { data: 'Hello, World!' });
- Example:
-
Middlewares
Easily apply both global and route-specific middlewares to process requests, manage authentication, logging, data manipulation, and more. -
File Uploads
Supports file uploads natively using theUpload
class, allowing the seamless handling and storage of files sent by clients. -
File Downloads
With thedownload
method, you can send files as attachments, specify custom file names, and set up error callbacks for a controlled download experience. -
Static File Serving
Serve static files from designated directories using thestatic
method, making folders (e.g., "public") accessible directly via URL. -
Send Files (sendFile)
Automatically handles the correct Content-Type based on file extensions to ensure files such as HTML, CSS, JavaScript, images, PDFs, etc., are served with the proper headers. -
Flexible Routing
Define routes with dynamic parameters (e.g.,/user/:id
) similar to Express.js, allowing easy extraction of parameters for RESTful API design. -
Sub-Routes Organize your routes into sub-routes for better modularity and maintainability.
-
CORS and Custom Headers
Configure CORS and set custom HTTP headers to adhere to security policies and enhance communication. -
Input Sanitization and Basic Security
Incorporates input sanitization mechanisms along with basic protections to avoid injection attacks and mitigate denial-of-service (DoS) scenarios. -
WebSocket Support Integrates WebSocket support to facilitate real-time communication and interactive features in your applications.
-
Error Handling Implement robust error handling mechanisms to gracefully manage errors and provide meaningful feedback to users.
-
Template Engine Integration Integrate popular template engines Mustache to create dynamic and interactive web pages.
Made by evendersondev with β€οΈ for Dart/Flutter developers! π―