Aqueduct is a modern Dart HTTP server framework. The framework is composed of libraries for handling and routing HTTP requests, object-relational mapping (ORM), authentication and authorization (OAuth 2.0 provider) and documentation (OpenAPI). These libraries are used to build scalable REST APIs that run on the Dart VM.
If this is your first time viewing Aqueduct, check out the tour.
Activate Aqueduct
pub global activate aqueduct
Create a new project.
aqueduct create my_project
Open the project directory in IntelliJ IDE, Atom or Visual Studio Code. All three IDEs have a Dart plugin. For IntelliJ IDEA users, there are file and code templates for Aqueduct.
Step-by-step tutorials for beginners are available here.
You can find the API reference here or you can install it in Dash.
You can find in-depth and conceptual guides here.
An ever-expanding repository of Aqueduct examples is here.
If you are migrating from Aqueduct 2.5 to Aqueduct 3.0, see the migration guide.
AuthRedirectController
type.AuthCodeController
in favor of AuthRedirectController
.ManagedContext.insertObject
, ManagedContext.insertObjects
and ManagedContext.fetchObjectWithID
.ManagedObject
s--resolve-relative-urls
flag to document
commands to improve client applicationsSerializable.documentSchema
instance method. Removes Serializable.document
static method.values
argument to Query
constructorController
is now an abstract class that requires implementing handle
. This is a minor breaking change that should not have an impact.aqueduct setup --heroku=<name>
and instead points to documentation.BodyDecoder.decode<T>
and BodyDecoder.as<T>
. This replaces existing decodeAs*
and as*
methods.AuthDelegate.addClient
and AuthServer.addClient
.ManagedContext.transaction
to enable queries to be run in a database transaction.ResourceController
methods.Recyclable<T>
to control whether controllers are instantiated per request or are reused.Document
data type.Query.insertObject
.APIComponentDocumenter
, APIOperationDocumenter
, APIDocumentContext
.PackagePathResolver
, ApplicationOptions.isDocumenting
and APIDocumentable
.MockHTTPServer.queueHandler
and MockHTTPServer.queueOutage
.Query.where
behavior has changed to consistently use property selector syntax.whereEqualTo
and replaced with QueryExpression
.Controller.generate
renamed to Controller.link
. Removed Controller.pipe
.package:aqueduct/test
moved to package:aqueduct_test/aqueduct_test
, which is a separate dependency from aqueduct
.AuthDelegate
to provide consistency.ManagedContext.defaultContext
; context usage must be explicit.HTTPResponseException
. Responses can now be thrown instead.QueryException
s are no longer thrown for every ORM exception. If a store chooses to interpret an exception, it will still throw a QueryException
. Otherwise, the underlying driver exception will be thrown.PostgreSQLPersistentStore
now takes connection info instead of closure.Controller.listen
renamed Controller.linkFunction
.aqueduct serve
to 8888.HTTPPath
, HTTPBody
, HTTPQuery
and HTTPHeader
- have been changed to Bind.path
, Bind.body
, Bind.query
and Bind.header
, respectively.@httpGet
(and other HTTPMethod
annotations) constants. Behavior replaced by @Operation
.runOnMainIsolate
from Application.start()
and added Application.startOnMainIsolate()
as replacement.ManagedSet.haveAtLeastOneWhere
.RequestSink
to ApplicationChannel
.willOpen
with prepare
.setupRouter
with entryPoint
.AuthCodeController.renderFunction
with AuthCodeControllerDelegate
.AuthStrategy
in place of AuthorizationParser<T>
.AuthorizationParser<T>
, AuthorizationBearerParser
and AuthorizationBasicParser
.AuthValidator.fromBearerToken
and AuthValidator.fromBasicCredentials
and replaces with AuthValidator.validate<T>
. Authorization.resourceOwnerIdentifier
-> Authorization.ownerID
Request.innerRequest
-> Request.raw
AuthStorage
-> AuthServerDelegate
AuthServer.storage
-> AuthServer.delegate
ApplicationConfiguration
-> ApplicationOptions
Application.configuration
-> Application.options
HTTPFileController
-> FileController
HTTPSerializable
-> Serializable
HTTPCachePolicy
-> CachePolicy
HTTPCodecRepository
-> CodecRegistry
requiredHTTPParameter
-> requiredBinding
ManagedTableAttributes
-> Table
ManagedRelationshipDeleteRule
-> DeleteRule
ManagedRelationship
-> Relate
ManagedColumnAttributes
-> Column
managedPrimaryKey
-> primaryKey
ManagedTransientAttribute
-> Serialize
Serialize
now replaces managedTransientAttribute
, managedTransientInputAttribute
, and managedTransientOutputAttribute
.RequestController
-> Controller
RequestController.processRequest
-> Controller.handle
HTTPController
-> ResourceController
aqueduct db schema
to print an application's data model.aqueduct document serve
that serves the API documentation for an application.--machine
flag to aqueduct
tool to only emit machine-readable output.defaultDelay
to MockHTTPServer
. Defaults to null for no delay.defaultResponse
to MockHTTPServer
. Defaults to a 503 response instead of a 200.MockHTTPServer
's queueResponse
function.HTTPRequestBody.maxSize
to limit HTTP request body sizes. Defaults to 10MB.ManagedTableAttributes
to configure underlying database table to use multiple columns to test for uniqueness.Request.addResponseModifier
to allow middleware to modify responses.Response.bufferOutput
to control whether the HTTP response bytes are buffered.whereNot
to apply an inverse to other Query.where
expression, e.g. whereNot(whereIn(["a", "b"]))
.ManagedObjectController
didn't work.ResourceRegistry
to ServiceRegistry
.package:aqueduct/test.dart
.Request.acceptableContentTypes
and Request.acceptsContentType
for convenient usage of Accept header.AuthStorage.allowedScopesForAuthenticatable
to provide user attribute-based scoping, e.g. roles.Query.forEntity
and ManagedObjectController.forEntity
to dynamically instantiate these types, i.e. use runtime values to build the query.PersistentStore.newQuery
- allows a PersistentStore
implementation to provide its own implementation of Query
specific to its underlying database.Query.reduce
to perform aggregate functions on database tables, e.g. sum, average, maximum, etc.enum
s may be used as persistent properties in ManagedObject<T>
. The underlying database will store them a strings.ApplicationMessageHub
to send cross-isolate messages.HTTPCodecRepository.add
to use specify default charset for Content-Type if a request does not specify one.aqueduct create
is now mostly empty. Available templates can be listed with aqueduct create list-templates
and selected with the command-line option --template
.aqueduct auth
would fail to insert new Client IDs.joinMany
and joinOne
are deprecated, use join(set:)
and join(object:)
instead.HTTPCodecRepository
replaces Response.addEncoder
and HTTPBody.addDecoder
.Stream
s may now be Response
bodies.HTTPController
with HTTPBody
metadata.HTTPFileController
.HTTPCachePolicy
to control cache headers for a Response
.Request.body
has significantly improved behavior and has been optimized.Transfer-Encoding: chunked
when the size of the response body can be determined efficiently.ResourceRegistry
: tracks port-consuming resources like database connections to ensure they are closed when an application shuts down during testing.ManagedObject
s using Validate
and ManagedValidator
and ManagedObject.validate
.ManagedObject
s now have callbacks willUpdate
and willInsert
to modify their values before updating and inserting.aqueduct serve
on Windows.aqueduct document
for routes using listen
TestClient
to execute requests with public OAuth2 clientaqueduct db generate
.aqueduct serve
default port to 8081 so can develop in parallel to Angular2 apps that default to 8080SecurityContext
reference from ApplicationConfiguration
. SSL configured via new aqueduct serve
arguments ssl-key-path
and ssl-certificate-path
, or overriding securityContext
in RequestSink
.RequestController.letUncaughtExceptionsEscape
for better debugging during tests.ManagedObject
s can now have superclasses.ManagedRelationship
s now have a .deferred()
constructor. This allows ManagedObject
s to have relationships to ManagedObject
s in other packages.RequestSink.initializeApplication
method to do one-time startup tasks that were previously done in a start script.RequestSink
constructor now takes ApplicationConfiguration
, instead of Map
.configurationFilePath
to ApplicationConfiguration
.Response
objects so that other parts of an application can accurately read their values during processing.HTTPBody
object to represent HTTP request bodies in Request
. Decoders are now added to this type.ORM: Renamed Query.matchOn
to Query.where
.
ORM: Removed includeInResultSet
for Query
's, instead, added joinOn
and joinMany
which create subqueries that can be configured further.
ORM: Allow Query.where
to reference properties in related objects without including related objects in results, i.e. can fetch Parent
objects and filter them by values in their Child
relationships.
ORM: Joins can now be applied to belongsTo relationship properties.
ORM: Matchers such as whereNull
and whereNotNull
can be applied to a relationship property in Query.where
.
ORM: Renamed ManagedSet.matchOn
to ManagedSet.haveAtLeastOneWhere
.
ORM: Added matchers for case-insensitive string matching, and added case-insensitive option to whereEquals
and whereNotEquals
.
Auth: Added aqueduct/managed_auth
library. Implements storage of OAuth 2.0 tokens using ManagedObject
s. See API reference for more details.
Auth: Improved error and response messaging to better align with the OAuth 2.0 spec, especially with regards to the authorization code flow.
Auth: Added distinction between public and confidential clients, as defined by OAuth 2.0 spec.
Auth: Improved class and property naming.
Tooling: Added aqueduct auth
tool to create client ID and secrets and add them to a database for applications using the aqueduct/managed_auth
package.
Tooling: Added more user-friendly configuration options for aqueduct db
tool.
Tooling: Added aqueduct setup --heroku
for setting up projects to be deployed to Heroku.
Tooling: Added aqueduct serve
command for running Aqueduct applications without having to write a start script.
Tooling: Added aqueduct document
command to generate OpenAPI specification for Aqueduct applications, instead of relying on a script that came with the template.
Response.contentType
property. Adding "Content-Type" to the headers of a Response
no longer has any effect; use this property instead.ManagedDataModel
s now scan all libraries for ManagedObject<T>
subclasses to generate a data model. Use ManagedDataModel.fromCurrentMirrorSystem
to create instances of ManagedDataModel
.ManagedContext
now becomes the ManagedContext.defaultContext
; prior to this change, it was the first instantiated context. Added ManagedContext.standalone
to opt out of setting the default context.aqueduct setup
.Process.runSync
that allow Windows user to use aqueduct
executable.example/main.dart
/*
This example demonstrates an HTTP application that uses the ORM and ORM-backed OAuth2 provider.
For building and running non-example applications, install 'aqueduct' command-line tool.
pub global activate aqueduct
aqueduct create my_app
More examples available: https://github.com/stablekernel/aqueduct_examples
*/
import 'dart:async';
import 'dart:io';
import 'package:aqueduct/aqueduct.dart';
import 'package:aqueduct/managed_auth.dart';
Future main() async {
final app = Application<App>()
..options.configurationFilePath = 'config.yaml'
..options.port = 8888;
await app.start(numberOfInstances: 3);
}
class App extends ApplicationChannel {
ManagedContext context;
AuthServer authServer;
@override
Future prepare() async {
final config =
AppConfiguration.fromFile(File(options.configurationFilePath));
final db = config.database;
final persistentStore = PostgreSQLPersistentStore.fromConnectionInfo(
db.username, db.password, db.host, db.port, db.databaseName);
context = ManagedContext(
ManagedDataModel.fromCurrentMirrorSystem(), persistentStore);
authServer = AuthServer(ManagedAuthDelegate(context));
}
@override
Controller get entryPoint {
return Router()
..route('/auth/token').link(() => AuthController(authServer))
..route('/users/[:id]')
.link(() => Authorizer(authServer))
.link(() => UserController(context, authServer));
}
}
class UserController extends ResourceController {
UserController(this.context, this.authServer);
final ManagedContext context;
final AuthServer authServer;
@Operation.get()
Future<Response> getUsers() async {
final query = Query<User>(context);
return Response.ok(await query.fetch());
}
@Operation.get('id')
Future<Response> getUserById(@Bind.path('id') int id) async {
final q = Query<User>(context)..where((o) => o.id).equalTo(id);
final user = await q.fetchOne();
if (user == null) {
return Response.notFound();
}
return Response.ok(user);
}
@Operation.post()
Future<Response> createUser(@Bind.body() User user) async {
if (user.username == null || user.password == null) {
return Response.badRequest(
body: {"error": "username and password required."});
}
final salt = AuthUtility.generateRandomSalt();
final hashedPassword = authServer.hashPassword(user.password, salt);
final query = Query<User>(context)
..values = user
..values.hashedPassword = hashedPassword
..values.salt = salt
..values.email = user.username;
final u = await query.insert();
final token = await authServer.authenticate(
u.username,
query.values.password,
request.authorization.credentials.username,
request.authorization.credentials.password);
return AuthController.tokenResponse(token);
}
}
class AppConfiguration extends Configuration {
AppConfiguration.fromFile(File file) : super.fromFile(file);
DatabaseConfiguration database;
}
class User extends ManagedObject<_User>
implements _User, ManagedAuthResourceOwner<_User> {
@Serialize(input: true, output: false)
String password;
}
class _User extends ResourceOwnerTableDefinition {
@Column(unique: true)
String email;
}
You can install the package from the command line:
$ pub global activate aqueduct
The package has the following executables:
$ aqueduct
Add this to your package's pubspec.yaml file:
dependencies:
aqueduct: ^3.1.0+1
You can install packages from the command line:
with pub:
$ pub get
Alternatively, your editor might support pub get
.
Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:aqueduct/aqueduct.dart';
Version | Uploaded | Documentation | Archive |
---|---|---|---|
3.1.0+1 | Dec 18, 2018 |
|
|
3.1.0 | Dec 17, 2018 |
|
|
3.0.2 | Sep 27, 2018 |
|
|
3.0.1 | Aug 31, 2018 |
|
|
3.0.0 | Aug 6, 2018 |
|
|
2.5.0+1 | Dec 1, 2017 |
|
|
2.5.0 | Oct 12, 2017 |
|
|
2.4.0 | Aug 30, 2017 |
|
|
2.3.2 | Jul 22, 2017 |
|
|
2.3.1 | Jul 20, 2017 |
|
|
Popularity:
Describes how popular the package is relative to other packages.
[more]
|
91
|
Health:
Code health derived from static analysis.
[more]
|
98
|
Maintenance:
Reflects how tidy and up-to-date the package is.
[more]
|
100
|
Overall:
Weighted score of the above.
[more]
|
95
|
We analyzed this package on Feb 14, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:
Detected platforms: other
Primary library:
package:aqueduct/aqueduct.dart
with components:io
,isolate
,mirrors
.
Fix lib/src/auth/auth_code_controller.dart
. (-1.49 points)
Analysis of lib/src/auth/auth_code_controller.dart
reported 3 hints:
line 9 col 15: 'AuthCodeController' is deprecated and shouldn't be used.
line 13 col 21: 'AuthCodeController' is deprecated and shouldn't be used.
line 27 col 25: 'AuthCodeController' is deprecated and shouldn't be used.
Fix lib/src/db/schema/migration_source.dart
. (-0.50 points)
Analysis of lib/src/db/schema/migration_source.dart
reported 1 hint:
line 3 col 1: 'analyzer' is deprecated and shouldn't be used.
Package | Constraint | Resolved | Available |
---|---|---|---|
Direct dependencies | |||
Dart SDK | >=2.0.0 <3.0.0 | ||
analyzer | >=0.32.0 <0.35.0 | 0.34.3 | 0.35.1 |
args | ^1.5.0 | 1.5.1 | |
crypto | ^2.0.6 | 2.0.6 | |
isolate_executor | ^2.0.0 | 2.0.2+1 | |
logging | ^0.11.3 | 0.11.3+2 | |
meta | ^1.1.5 | 1.1.7 | |
open_api | ^2.0.1 | 2.0.1 | |
password_hash | ^2.0.0 | 2.0.0 | |
path | ^1.6.1 | 1.6.2 | |
postgres | ^1.0.0 | 1.0.2 | |
pub_cache | >=0.2.0 <0.3.0 | 0.2.3 | |
pub_semver | ^1.4.0 | 1.4.2 | |
safe_config | ^2.0.0 | 2.0.2 | |
yaml | ^2.1.15 | 2.1.15 | |
Transitive dependencies | |||
async | 2.0.8 | ||
charcode | 1.1.2 | ||
codable | 1.0.0 | ||
collection | 1.14.11 | ||
convert | 2.1.1 | ||
csslib | 0.14.6 | ||
front_end | 0.1.9+1 | 0.1.11 | |
glob | 1.1.7 | ||
html | 0.13.3+3 | ||
kernel | 0.3.9+1 | 0.3.11 | |
package_config | 1.0.5 | ||
plugin | 0.2.0+3 | ||
source_span | 1.5.4 | ||
string_scanner | 1.0.4 | ||
term_glyph | 1.1.0 | ||
typed_data | 1.1.6 | ||
utf | 0.9.0+5 | ||
watcher | 0.9.7+10 | ||
Dev dependencies | |||
aqueduct_test | |||
http | >=0.11.3+7 <0.13.0 | ||
matcher | >=0.12.3 <0.14.0 | ||
test | ^1.3.0 |