mirror of
https://github.com/felixblaschke/shelf_plus.git
synced 2025-08-03 17:43:18 +08:00
upgrade dependencies - version 1.9
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
## 1.9.0
|
||||
|
||||
- Upgrade dependencies
|
||||
|
||||
## 1.8.0
|
||||
|
||||
- `shelfRun()` lifecycle hooks `onWillClose` and `onClosed` supports asynchronous execution
|
||||
|
127
README.md
127
README.md
@ -7,7 +7,6 @@ the Shelf platform. It's a great base to **start off** your apps fast, while
|
||||
**maintaining full compatibility** with the **Shelf** ecosystem.
|
||||
|
||||
<!-- #code doc_files/quickstart.dart -->
|
||||
|
||||
```dart
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
|
||||
@ -18,10 +17,9 @@ Handler init() {
|
||||
|
||||
app.get('/', () => 'Hello World!');
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
It comes with a lot of awesome features, like **zero-configuration** initializer, build-in **hot-reload**
|
||||
@ -29,38 +27,32 @@ and a **super powerful** and **intuitive router upgrade**. Continue reading and
|
||||
you can't ever code without **Shelf Plus**.
|
||||
|
||||
<!-- #toc -->
|
||||
|
||||
## Table of Contents
|
||||
|
||||
[**Router Plus**](#router-plus)
|
||||
|
||||
- [Routes API](#routes-api)
|
||||
- [Middleware](#middleware)
|
||||
- [ResponseHandler](#responsehandler)
|
||||
- [Cascading multiple routers](#cascading-multiple-routers)
|
||||
- [Routes API](#routes-api)
|
||||
- [Middleware](#middleware)
|
||||
- [ResponseHandler](#responsehandler)
|
||||
- [Cascading multiple routers](#cascading-multiple-routers)
|
||||
|
||||
[**Middleware collection**](#middleware-collection)
|
||||
|
||||
- [setContentType](#setcontenttype)
|
||||
- [typeByExtension](#typebyextension)
|
||||
- [download](#download)
|
||||
- [setContentType](#setcontenttype)
|
||||
- [typeByExtension](#typebyextension)
|
||||
- [download](#download)
|
||||
|
||||
[**Request body handling**](#request-body-handling)
|
||||
|
||||
- [Object deserialization](#object-deserialization)
|
||||
- [Custom accessors for model classes](#custom-accessors-for-model-classes)
|
||||
- [Custom accessors for third party body parser](#custom-accessors-for-third-party-body-parser)
|
||||
- [Object deserialization](#object-deserialization)
|
||||
- [Custom accessors for model classes](#custom-accessors-for-model-classes)
|
||||
- [Custom accessors for third party body parser](#custom-accessors-for-third-party-body-parser)
|
||||
|
||||
[**Shelf Run**](#shelf-run)
|
||||
|
||||
- [Custom configuration](#custom-configuration)
|
||||
- [Multithreading](#multithreading)
|
||||
- [Custom configuration](#custom-configuration)
|
||||
- [Multithreading](#multithreading)
|
||||
|
||||
[**Examples**](#examples)
|
||||
|
||||
- [Enable CORS](#enable-cors)
|
||||
- [Rest Service](#rest-service)
|
||||
- [WebSocket chat server](#websocket-chat-server)
|
||||
- [Enable CORS](#enable-cors)
|
||||
- [Rest Service](#rest-service)
|
||||
- [WebSocket chat server](#websocket-chat-server)
|
||||
<!-- // end of #toc -->
|
||||
|
||||
## Router Plus
|
||||
@ -70,7 +62,6 @@ It **shares the same [routing logic](https://pub.dev/documentation/shelf_router/
|
||||
but allows you to handle responses in a very simple way.
|
||||
|
||||
<!-- #code doc_files/router_plus_intro.dart -->
|
||||
|
||||
```dart
|
||||
var app = Router().plus;
|
||||
|
||||
@ -86,7 +77,6 @@ app.get('/file', () => File('path/to/file.zip'));
|
||||
|
||||
app.get('/person', () => Person(name: 'John', age: 42));
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
The core mechanic is called **ResponseHandler** which continuously refines a data structure,
|
||||
@ -96,11 +86,9 @@ This extensible system comes with support for text, json, binaries, files, json
|
||||
You can access the **Router Plus** by calling the **`.plus`** getter on a regular Shelf Router.
|
||||
|
||||
<!-- #code doc_files/router_plus_upgrade.dart -->
|
||||
|
||||
```dart
|
||||
var app = Router().plus;
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### Routes API
|
||||
@ -110,11 +98,9 @@ methods. You basically use an HTTP verb, define a route to match and specify a h
|
||||
that generates the response.
|
||||
|
||||
<!-- #code doc_files/routes_api_verb.dart -->
|
||||
|
||||
```dart
|
||||
app.get('/path/to/match', () => 'a response');
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
You can return any type, as long the **ResponseHandler** mechanism has a capable
|
||||
@ -125,7 +111,6 @@ object, specify it as the first parameter. Any other parameter will match the
|
||||
route parameters, if defined.
|
||||
|
||||
<!-- #code doc_files/routes_api_signature.dart -->
|
||||
|
||||
```dart
|
||||
app.get('/minimalistic', () => 'response');
|
||||
|
||||
@ -138,7 +123,6 @@ app.get('/customer/<id>', (Request request) {
|
||||
return 'response: ${request.routeParameter('id')}';
|
||||
});
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### Middleware
|
||||
@ -146,7 +130,6 @@ app.get('/customer/<id>', (Request request) {
|
||||
Router Plus provides several options to place your middleware ([Shelf Middleware](https://pub.dev/documentation/shelf/latest/shelf/Middleware.html)).
|
||||
|
||||
<!-- #code doc_files/middleware_intro.dart -->
|
||||
|
||||
```dart
|
||||
var app = Router().plus;
|
||||
|
||||
@ -158,19 +141,16 @@ app.get('/request1', () => 'response', use: middlewareB);
|
||||
// combine middleware with + operator
|
||||
app.get('/request2', () => 'response', use: middlewareB + middlewareC);
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
You can also apply middleware dynamically inside a route handler, using the `>>` operator.
|
||||
|
||||
<!-- #code doc_files/middleware_in_requesthandler.dart -->
|
||||
|
||||
```dart
|
||||
app.get('/request/<value>', (Request request, String value) {
|
||||
return middleware(value) >> 'response';
|
||||
});
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### ResponseHandler
|
||||
@ -193,7 +173,6 @@ ResponseHandler process the **return value** of a route handler, until it matche
|
||||
_Example:_
|
||||
|
||||
<!-- #code doc_files/response_handler_example.dart -->
|
||||
|
||||
```dart
|
||||
import 'dart:io';
|
||||
|
||||
@ -228,7 +207,7 @@ Handler init() {
|
||||
onClose: (ws) => ws.send('Bye!'),
|
||||
));
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
||||
class Person {
|
||||
@ -240,7 +219,6 @@ class Person {
|
||||
Map<String, dynamic> toJson() => {'name': name};
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
#### Custom ResponseHandler
|
||||
@ -249,7 +227,6 @@ You can add your own ResponseHandler by using a [Shelf Middleware](https://pub.d
|
||||
created with the `.middleware` getter on a ResponseHandler function.
|
||||
|
||||
<!-- #code doc_files/response_handler_custom.dart -->
|
||||
|
||||
```dart
|
||||
// define custom ResponseHandler
|
||||
ResponseHandler catResponseHandler = (Request request, dynamic maybeCat) =>
|
||||
@ -260,16 +237,13 @@ app.use(catResponseHandler.middleware);
|
||||
|
||||
app.get('/cat', () => Cat());
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
<!-- #code doc_files/response_handler_custom_cat.dart -->
|
||||
|
||||
```dart
|
||||
class Cat {
|
||||
String interact() => 'Purrrrr!';
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### Cascading multiple routers
|
||||
@ -279,6 +253,23 @@ So, you can also use it in a [Shelf Cascade](https://pub.dev/documentation/shelf
|
||||
This package provides a `cascade()` function, to quickly set up a cascade.
|
||||
|
||||
<!-- #code doc_files/cascade.dart -->
|
||||
```dart
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
|
||||
void main() => shelfRun(init);
|
||||
|
||||
Handler init() {
|
||||
var app1 = Router().plus;
|
||||
var app2 = Router().plus;
|
||||
|
||||
app1.get('/maybe', () => Response.notFound('no idea'));
|
||||
|
||||
app2.get('/maybe', () => 'got it!');
|
||||
|
||||
return cascade([app1.call, app2.call]);
|
||||
}
|
||||
```
|
||||
<!-- // end of #code -->
|
||||
|
||||
```dart
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
@ -307,13 +298,11 @@ to simplify common tasks.
|
||||
Sets the `content-type` header of a `Response` to the specified **mime-type**.
|
||||
|
||||
<!-- #code doc_files/mw_set_content_type.dart -->
|
||||
|
||||
```dart
|
||||
app.get('/one', () => setContentType('application/json') >> '1');
|
||||
|
||||
app.get('/two', () => '2', use: setContentType('application/json'));
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
<!-- #space1 -->
|
||||
@ -324,11 +313,9 @@ Sets the `content-type` header of a `Response` to the **mime-type** of the
|
||||
specified **file extension**.
|
||||
|
||||
<!-- #code doc_files/mw_type_by_extension.dart -->
|
||||
|
||||
```dart
|
||||
app.get('/', () => '<h1>Hi!</h1>', use: typeByExtension('html'));
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
<!-- #space1 -->
|
||||
@ -339,6 +326,15 @@ Sets the `content-disposition` header of a `Response`, so browsers will download
|
||||
server response instead of displaying it. Optionally you can define a specific **file name**.
|
||||
|
||||
<!-- #code doc_files/mw_download.dart -->
|
||||
```dart
|
||||
app.get('/wallpaper/download', () => File('image.jpg'), use: download());
|
||||
|
||||
app.get('/invoice/<id>', (Request request, String id) {
|
||||
File document = pdfService.generateInvoice(id);
|
||||
return download(filename: 'invoice_$id.pdf') >> document;
|
||||
});
|
||||
```
|
||||
<!-- // end of #code -->
|
||||
|
||||
```dart
|
||||
app.get('/wallpaper/download', () => File('image.jpg'), use: download());
|
||||
@ -357,7 +353,6 @@ You can access it by calling the `.body` getter on a [Shelf Request](https://pub
|
||||
It comes with build-in support for text, JSON and binary.
|
||||
|
||||
<!-- #code doc_files/request_body_intro.dart -->
|
||||
|
||||
```dart
|
||||
app.post('/text', (Request request) async {
|
||||
var text = await request.body.asString;
|
||||
@ -369,7 +364,6 @@ app.post('/json', (Request request) async {
|
||||
return 'You send me: ${person.name}';
|
||||
});
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
<!-- #space1 -->
|
||||
@ -380,14 +374,11 @@ A recommended way to deserialize a json-encoded object is to provide a
|
||||
**reviver function**, that can be generated by code generators.
|
||||
|
||||
<!-- #code doc_files/request_body_deserialize1.dart -->
|
||||
|
||||
```dart
|
||||
var person = await request.body.as(Person.fromJson);
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
<!-- #code doc_files/request_body_deserialize2.dart -->
|
||||
|
||||
```dart
|
||||
class Person {
|
||||
final String name;
|
||||
@ -400,7 +391,6 @@ class Person {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
<!-- #space1 -->
|
||||
@ -411,23 +401,19 @@ You can add own accessors for model classes by creating an
|
||||
extension on `RequestBodyAccessor`.
|
||||
|
||||
<!-- #code doc_files/request_body_ext_model1.dart -->
|
||||
|
||||
```dart
|
||||
extension PersonAccessor on RequestBodyAccessor {
|
||||
Future<Person> get asPerson async => Person.fromJson(await asJson);
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
<!-- #code doc_files/request_body_ext_model2.dart -->
|
||||
|
||||
```dart
|
||||
app.post('/person', (Request request) async {
|
||||
var person = await request.body.asPerson;
|
||||
return 'You send me: ${person.name}';
|
||||
});
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
<!-- #space1 -->
|
||||
@ -438,6 +424,14 @@ You can plug-in any other body parser by creating an
|
||||
extension on `RequestBodyAccessor`.
|
||||
|
||||
<!-- #code doc_files/request_body_ext_third_party.dart -->
|
||||
```dart
|
||||
extension OtherFormatBodyParserAccessor on RequestBodyAccessor {
|
||||
Future<OtherBodyFormat> get asOtherFormat async {
|
||||
return ThirdPartyLib().process(request.read());
|
||||
}
|
||||
}
|
||||
```
|
||||
<!-- // end of #code -->
|
||||
|
||||
```dart
|
||||
extension OtherFormatBodyParserAccessor on RequestBodyAccessor {
|
||||
@ -452,7 +446,6 @@ extension OtherFormatBodyParserAccessor on RequestBodyAccessor {
|
||||
Shelf Run is **zero-configuration** web-server initializer with **hot-reload** support.
|
||||
|
||||
<!-- #code doc_files/shelf_run_intro.dart -->
|
||||
|
||||
```dart
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
|
||||
@ -462,7 +455,6 @@ Handler init() {
|
||||
return (Request request) => Response.ok('Hello!');
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
It's important to use a dedicated `init` function, returning a [Shelf Handler](https://pub.dev/documentation/shelf/latest/shelf/Handler.html),
|
||||
@ -489,11 +481,9 @@ Shelf Run uses a default configuration, that can be modified via **environment v
|
||||
You can override the default values with optional parameters in the `shelfRun()` function.
|
||||
|
||||
<!-- #code doc_files/shelf_run_override_default.dart -->
|
||||
|
||||
```dart
|
||||
void main() => shelfRun(init, defaultBindPort: 3000);
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### Multithreading
|
||||
@ -505,7 +495,6 @@ You can enable the [shared](https://api.dart.dev/stable/2.16.0/dart-io/HttpServe
|
||||
**Example of an application using multiple isolates**
|
||||
|
||||
<!-- #code doc_files/isolates.dart -->
|
||||
|
||||
```dart
|
||||
import 'dart:isolate';
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
@ -529,10 +518,9 @@ Handler init() {
|
||||
return 'Hello from isolate: ${Isolate.current.debugName}';
|
||||
});
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
You can test this application and compare different count of isolates:
|
||||
@ -546,7 +534,6 @@ xargs -I % -P 8 curl "http://localhost:8080" < <(printf '%s\n' {1..400})
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- // end of #space -->
|
||||
|
||||
## Examples
|
||||
@ -556,7 +543,6 @@ xargs -I % -P 8 curl "http://localhost:8080" < <(printf '%s\n' {1..400})
|
||||
[CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) can be enabled by using the [shelf_cors_headers](https://pub.dev/packages/shelf_cors_headers) package:
|
||||
|
||||
<!-- #code example/example_cors/bin/example_cors.dart -->
|
||||
|
||||
```dart
|
||||
import 'package:shelf_cors_headers/shelf_cors_headers.dart';
|
||||
import 'package:shelf_plus/shelf_plus.dart';
|
||||
@ -573,7 +559,6 @@ Handler init() {
|
||||
return app;
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### Rest Service
|
||||
@ -583,7 +568,6 @@ Implementation of a CRUD, rest-like backend service. ([Full sources](example/exa
|
||||
**example_rest.dart**
|
||||
|
||||
<!-- #code example/example_rest/bin/example_rest.dart -->
|
||||
|
||||
```dart
|
||||
import 'dart:io';
|
||||
|
||||
@ -636,13 +620,11 @@ Handler init() {
|
||||
return app;
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
**person.dart**
|
||||
|
||||
<!-- #code example/example_rest/bin/person.dart -->
|
||||
|
||||
```dart
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
@ -672,7 +654,6 @@ class Person {
|
||||
static Person fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
|
||||
### WebSocket chat server
|
||||
@ -682,7 +663,6 @@ Implementation of a WebSocket-based chat application. ([Full sources](example/ex
|
||||
**example_websocket_chat.dart**
|
||||
|
||||
<!-- #code example/example_websocket_chat/bin/example_websocket_chat.dart -->
|
||||
|
||||
```dart
|
||||
import 'dart:io';
|
||||
|
||||
@ -729,5 +709,4 @@ Handler init() {
|
||||
return app;
|
||||
}
|
||||
```
|
||||
|
||||
<!-- // end of #code -->
|
||||
<!-- // end of #code -->
|
@ -10,5 +10,5 @@ Handler init() {
|
||||
|
||||
app2.get('/maybe', () => 'got it!');
|
||||
|
||||
return cascade([app1, app2]);
|
||||
return cascade([app1.call, app2.call]);
|
||||
}
|
||||
|
@ -20,5 +20,5 @@ Handler init() {
|
||||
return 'Hello from isolate: ${Isolate.current.debugName}';
|
||||
});
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -12,5 +12,5 @@ Handler init() {
|
||||
return middleware(value) >> 'response';
|
||||
});
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -18,5 +18,5 @@ Handler init() {
|
||||
// combine middleware with + operator
|
||||
app.get('/request2', () => 'response', use: middlewareB + middlewareC);
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -16,5 +16,5 @@ Handler init() {
|
||||
return download(filename: 'invoice_$id.pdf') >> document;
|
||||
});
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ Handler init() {
|
||||
|
||||
app.get('/two', () => '2', use: setContentType('application/json'));
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ Handler init() {
|
||||
// #begin
|
||||
app.get('/', () => '<h1>Hi!</h1>', use: typeByExtension('html'));
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ Handler init() {
|
||||
|
||||
app.get('/', () => 'Hello World!');
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -14,5 +14,5 @@ Handler init() {
|
||||
return 'You send me: ${person.name}';
|
||||
});
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ Handler init() {
|
||||
return 'You send me: ${person.name}';
|
||||
});
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
||||
extension PersonAccessor on RequestBodyAccessor {
|
||||
|
@ -17,5 +17,5 @@ Handler init() {
|
||||
return 'You send me: ${person.name}';
|
||||
});
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ Handler init() {
|
||||
|
||||
app.get('/cat', () => Cat());
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
||||
class Cat {
|
||||
|
@ -31,7 +31,7 @@ Handler init() {
|
||||
onClose: (ws) => ws.send('Bye!'),
|
||||
));
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
||||
class Person {
|
||||
|
@ -24,5 +24,5 @@ Handler init() {
|
||||
|
||||
app.get('/person', () => Person(name: 'John', age: 42));
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -6,5 +6,5 @@ Handler init() {
|
||||
// #begin
|
||||
var app = Router().plus;
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -16,5 +16,5 @@ Handler init() {
|
||||
return 'response: ${request.routeParameter('id')}';
|
||||
});
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ Handler init() {
|
||||
// #begin
|
||||
app.get('/path/to/match', () => 'a response');
|
||||
// #end
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ Handler init() {
|
||||
|
||||
app.get('/file', () => File('thesis.pdf'));
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
||||
class Person {
|
||||
|
@ -15,5 +15,5 @@ Handler init() {
|
||||
|
||||
app.get('/', () => 'world', use: greeterMiddleware);
|
||||
|
||||
return app;
|
||||
return app.call;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class _RouterPlusHandler {
|
||||
dynamic result;
|
||||
|
||||
try {
|
||||
result = Function.apply(handler, [request, ...map.values.toList()]);
|
||||
result = Function.apply(handler, [request, ...map.values]);
|
||||
} on NoSuchMethodError catch (_) {
|
||||
try {
|
||||
result = handler();
|
||||
@ -115,7 +115,7 @@ class RouterPlus {
|
||||
_RouterPlusHandler(handler, [
|
||||
..._middlewareList,
|
||||
if (localMiddleware != null) localMiddleware,
|
||||
]));
|
||||
]).call);
|
||||
_routeAdded = true;
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ class RouterPlus {
|
||||
_RouterPlusHandler(handler, [
|
||||
..._middlewareList,
|
||||
if (use != null) use,
|
||||
]));
|
||||
]).call);
|
||||
_routeAdded = true;
|
||||
}
|
||||
|
||||
|
26
pubspec.yaml
26
pubspec.yaml
@ -1,24 +1,24 @@
|
||||
name: shelf_plus
|
||||
description: Shelf Plus is a quality of life addon for your server-side development within the Shelf platform.
|
||||
version: 1.8.0
|
||||
version: 1.9.0
|
||||
repository: https://github.com/felixblaschke/shelf_plus
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <4.0.0"
|
||||
|
||||
dependencies:
|
||||
shelf: ^1.4.0
|
||||
shelf_router: ^1.1.3
|
||||
shelf_static: ^1.1.1
|
||||
shelf_hotreload: ^1.4.0
|
||||
shelf_web_socket: ^1.0.3
|
||||
shelf: ^1.4.1
|
||||
shelf_router: ^1.1.4
|
||||
shelf_static: ^1.1.2
|
||||
shelf_hotreload: ^1.5.0
|
||||
shelf_web_socket: ^1.0.4
|
||||
mime_type: ^1.0.0
|
||||
web_socket_channel: ^2.3.0
|
||||
web_socket_channel: ^2.4.4
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.0.1
|
||||
test: ^1.22.1
|
||||
dio: ^4.0.0
|
||||
json_annotation: ^4.7.0
|
||||
json_serializable: ^6.5.4
|
||||
build_runner: ^2.3.3
|
||||
lints: ^3.0.0
|
||||
test: ^1.25.2
|
||||
dio: ^5.4.1
|
||||
json_annotation: ^4.8.1
|
||||
json_serializable: ^6.7.1
|
||||
build_runner: ^2.4.8
|
||||
|
@ -18,7 +18,7 @@ void main() {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
await dio.Dio().post('${server.host}/route', data: 'hello');
|
||||
|
||||
@ -37,7 +37,7 @@ void main() {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
await dio.Dio().post('${server.host}/route', data: 'hello');
|
||||
|
||||
@ -53,7 +53,7 @@ void main() {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
await dio.Dio().post('${server.host}/route', data: {'a': '1', 'b': 2});
|
||||
|
||||
@ -70,7 +70,7 @@ void main() {
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
await dio.Dio().post('${server.host}/route',
|
||||
data: Person(name: 'john', age: 42).toJson());
|
||||
|
@ -25,7 +25,7 @@ void main() {
|
||||
app.add('get', '/add-get', () => 'add-get');
|
||||
app.all('/all', () => 'all');
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
expect(await server.fetchBody<String>('get', '/get'), 'get');
|
||||
expect(await server.fetchBody<String>('head', '/head'), '');
|
||||
@ -49,7 +49,7 @@ void main() {
|
||||
app.get('/b2/<name>', (Request request) => 'b');
|
||||
app.get('/b3/<name>', (Request request, String name) => 'b:$name');
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
expect(await server.fetchBody<String>('get', '/a1'), 'a');
|
||||
expect(await server.fetchBody<String>('get', '/a2'), 'a');
|
||||
@ -73,7 +73,7 @@ void main() {
|
||||
app.get('/persons', () => persons);
|
||||
app.get('/persons/john', () => persons.where((p) => p.firstName == 'John'));
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r1 = await server.fetch('get', '/object');
|
||||
expect(r1.headers['content-type']?.first, 'application/json');
|
||||
@ -109,7 +109,7 @@ void main() {
|
||||
|
||||
server = await runTestServer(Pipeline()
|
||||
.addMiddleware(addResponseHandler([catHandler]))
|
||||
.addHandler(app));
|
||||
.addHandler(app.call));
|
||||
|
||||
expect(await server.fetchBody<String>('get', '/cat'), 'Purrr!');
|
||||
});
|
||||
@ -119,7 +119,7 @@ void main() {
|
||||
|
||||
app.get('/cat', () => Cat(), use: catHandler.middleware);
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
expect(await server.fetchBody<String>('get', '/cat'), 'Purrr!');
|
||||
});
|
||||
|
||||
@ -130,7 +130,7 @@ void main() {
|
||||
|
||||
app.get('/number', () => '1', use: wrapBody('b') + wrapBody('c'));
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
expect(await server.fetchBody<String>('get', '/number'), 'a(b(c(1)))');
|
||||
});
|
||||
@ -143,7 +143,7 @@ void main() {
|
||||
|
||||
app.use(returnHello());
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
expect(await server.fetchBody<String>('get', '/'), 'hello');
|
||||
expect(await server.fetchBody<String>('post', '/dynamic_route'), 'hello');
|
||||
@ -156,7 +156,7 @@ void main() {
|
||||
|
||||
app.get('/person', () => Person(firstName: 'John', lastName: 'Doe'));
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r1 = await server.fetch('get', '/person');
|
||||
expect(r1.headers['content-type']?.first, 'application/json');
|
||||
@ -172,7 +172,7 @@ void main() {
|
||||
return File('test/test_data/$path');
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r1 = await server.fetch('get', '/bird');
|
||||
expect(r1.headers[HttpHeaders.contentTypeHeader]?.first, 'image/jpeg');
|
||||
@ -193,7 +193,7 @@ void main() {
|
||||
app.get('/image', () => File('test/test_data/bird.jpg'),
|
||||
use: download(filename: 'bird.jpg'));
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r = await server.fetch('get', '/image');
|
||||
expect(r.headers['content-disposition']?.first,
|
||||
@ -205,7 +205,7 @@ void main() {
|
||||
|
||||
app.get('/data', () => wrapBody('a') >> 'b');
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r = await server.fetch('get', '/data');
|
||||
expect(r.data, 'a(b)');
|
||||
@ -219,7 +219,7 @@ void main() {
|
||||
|
||||
app.get('/html2', () => '<h1>Headline</h1>', use: typeByExtension('html'));
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r1 = await server.fetch('get', '/html1');
|
||||
expect(r1.headers[HttpHeaders.contentTypeHeader]?.first, 'text/html');
|
||||
@ -235,7 +235,7 @@ void main() {
|
||||
app1.get('/a', () => Response.notFound(''));
|
||||
app2.get('/a', () => 'ok');
|
||||
|
||||
server = await runTestServer(cascade([app1, app2]));
|
||||
server = await runTestServer(cascade([app1.call, app2.call]));
|
||||
|
||||
var r = await server.fetch('get', '/a');
|
||||
expect(r.data, 'ok');
|
||||
@ -248,7 +248,7 @@ void main() {
|
||||
return 'Hi ${request.routeParameter('name')}, I like ${request.routeParameter('action')}';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r = await server.fetch('get', '/sports/john');
|
||||
expect(r.data, 'Hi john, I like sports');
|
||||
@ -258,10 +258,10 @@ void main() {
|
||||
var app = Router().plus;
|
||||
var subapp = Router().plus;
|
||||
|
||||
app.mount('/prefix/', subapp);
|
||||
app.mount('/prefix/', subapp.call);
|
||||
subapp.get('/data', () => 'ok');
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r = await server.fetch('get', '/prefix/data');
|
||||
expect(r.data, 'ok');
|
||||
@ -273,7 +273,7 @@ void main() {
|
||||
app.get('/bird1', () => File('test/test_data/bird.jpg').readAsBytesSync());
|
||||
app.get('/bird2', () => File('test/test_data/bird.jpg').openRead());
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r1 = await server.fetch('get', '/bird1');
|
||||
expect(r1.headers[HttpHeaders.contentTypeHeader]?.first,
|
||||
@ -298,7 +298,7 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
final channel = WebSocketChannel.connect(
|
||||
Uri.parse('${server.websocketHost}/ws'),
|
||||
@ -327,13 +327,13 @@ void main() {
|
||||
|
||||
var app = Router().plus;
|
||||
|
||||
app.mount('/', restrictedApp);
|
||||
app.mount('/', restrictedApp.call);
|
||||
|
||||
app.get('/public', () {
|
||||
return 'public data';
|
||||
});
|
||||
|
||||
server = await runTestServer(app);
|
||||
server = await runTestServer(app.call);
|
||||
|
||||
var r = await server.fetch('get', '/public');
|
||||
expect(r.data, 'public data');
|
||||
|
Reference in New Issue
Block a user