Skip to content

Instantly share code, notes, and snippets.

@kenreilly
Last active December 4, 2023 23:19
Show Gist options
  • Save kenreilly/598c3b324a64d173516f4f52ce8344d2 to your computer and use it in GitHub Desktop.
Save kenreilly/598c3b324a64d173516f4f52ce8344d2 to your computer and use it in GitHub Desktop.
Dart Metaprogramming - API Service
import 'dart:io';
import 'dart:convert';
import 'dart:mirrors';
import 'package:api_sdk/framework/api-method.dart';
import 'package:api_sdk/framework/api-route.dart';
import 'package:http_server/http_server.dart';
abstract class ServiceBase {
InstanceMirror _self;
ServiceBase() { _self = reflect(this); }
void dispose() => _self = null;
}
class RESTSession {
final HttpRequestBody body;
RESTSession(this.body);
}
abstract class APIService extends ServiceBase {
static final List<APIService> _instances = [];
static final List<APIRoute> _routes = [];
RoutePath _route = RoutePath('/');
APIService(): super() {
_instances.add(this);
_self.type.metadata.forEach((m) => (m.reflectee is RoutePath) ? (_route = _route + m.reflectee) : null);
_self.type.declarations.forEach((Symbol s, DeclarationMirror m) { if (m is MethodMirror) (_load(s, m)); });
}
@override
void dispose() {
_instances.remove(this);
super.dispose();
}
static void onRequest(HttpRequestBody reqbody) async {
HttpResponse response = reqbody.request.response;
APIRoute route = await _routes.firstWhere((route) => route.check(reqbody.request), orElse: () => null);
if (route == null) {
await (response..statusCode = 404)..write('NotFound');
await response.close();
return;
}
if (route.verb == 'WS') { return route.upgrade(reqbody); }
try {
dynamic data = await route.handle(reqbody);
response.statusCode = 200;
if (data is String) {
response.write(data);
}
else if (data is File) {
List<int> bytes = await data.readAsBytes();
response.write(base64.encode(bytes));
}
else {
await response.add(data);
}
} catch(e) {
response.addError(e);
}
await response.close();
}
void _load(Symbol s, MethodMirror m) {
if (m.metadata.isEmpty) return;
String _verb;
RoutePath _path;
bool _json;
m.metadata.forEach((InstanceMirror i) {
if (i.reflectee == JSON) { _json = true; }
else if (i.reflectee is APIMethod) {
_verb = MirrorSystem.getName(i.type.simpleName);
_path = _route + RoutePath(i.reflectee.route);
}
});
_routes.add(APIRoute(this, _verb, _path, m, json: _json));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment