blob: 6a7829799aef4e3aa36f2ca1a51ae28d53e8f4a4 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
/// An entity that knows how to serve itself over http.
abstract class Page {
final StringBuffer buf = StringBuffer();
final String? id;
Page(this.id);
String get path => '/$id';
Future<String> generate(Map<String, String> params) async {
buf.clear();
// TODO(brianwilkerson) Determine if await is necessary, if so, change the
// return type of [generatePage] to `Future<void>`.
await (generatePage(params) as dynamic);
return buf.toString();
}
Future<void> generatePage(Map<String, String> params);
}
/// Contains a collection of Pages.
abstract class Site {
final String title;
final List<Page> pages = [];
Site(this.title);
Page createExceptionPage(String message, StackTrace trace);
Page createUnknownPage(String unknownPath);
Future<void> handleGetRequest(HttpRequest request) async {
try {
var path = request.uri.path;
if (path == '/') {
respondRedirect(request, pages.first.path);
return;
}
for (var page in pages) {
if (page.path == path) {
var response = request.response;
response.headers.contentType = ContentType.html;
response.write(await page.generate(request.uri.queryParameters));
response.close();
return;
}
}
await respond(request, createUnknownPage(path), HttpStatus.notFound);
} catch (e, st) {
try {
await respond(request, createExceptionPage('$e', st),
HttpStatus.internalServerError);
} catch (e, st) {
var response = request.response;
response.statusCode = HttpStatus.internalServerError;
response.headers.contentType = ContentType.text;
response.write('$e\n\n$st');
response.close();
}
}
}
Future<void> respond(
HttpRequest request,
Page page, [
int code = HttpStatus.ok,
]) async {
var response = request.response;
response.statusCode = code;
response.headers.contentType = ContentType.html;
response.write(await page.generate(request.uri.queryParameters));
await response.close();
}
Future<void> respondJson(
HttpRequest request,
Map<String, Object> json, [
int code = HttpStatus.ok,
]) async {
var response = request.response;
response.statusCode = code;
response.headers.contentType = ContentType.json;
response.write(jsonEncode(json));
await response.close();
}
Future<void> respondOk(
HttpRequest request, {
int code = HttpStatus.ok,
}) async {
if (request.headers.contentType!.subType == 'json') {
return respondJson(request, {'success': true}, code);
}
var response = request.response;
response.statusCode = code;
await response.close();
}
Future<void> respondRedirect(HttpRequest request, String pathFragment) async {
var response = request.response;
response.statusCode = HttpStatus.movedTemporarily;
await response.redirect(request.uri.resolve(pathFragment));
}
}