Skip to content

Commit

Permalink
Add support for custom response headers (#61)
Browse files Browse the repository at this point in the history
example:
`--headers header=value;header2=value;`
  • Loading branch information
johnpryan authored Dec 20, 2023
1 parent c151e80 commit 3c0f0ad
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 14 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## 4.0.2-wip
## 4.1.0

- Add "headers" option to add additional response headers.
For example: `--headers="header1=value;header2=value;"`
- Update minimum Dart SDK to `3.0.0`.

## 4.0.1
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ $ dhttpd --path build/web/ # Serves app at http://localhost:8080

```console
$ dhttpd --help
-p, --port=<port> The port to listen on.
(defaults to "8080")
--path=<path> The path to serve. If not set, the current directory is used.
--host=<host> The hostname to listen on.
(defaults to "localhost")
-h, --help Displays the help.
-p, --port=<port> The port to listen on.
(defaults to "8080")
--path=<path> The path to serve. If not set, the current directory is used.
--headers=<headers> HTTP headers to apply to each response. header=value;header2=value
--host=<host> The hostname to listen on.
(defaults to "localhost")
-h, --help Displays the help.
```

[path]: https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path
9 changes: 9 additions & 0 deletions bin/dhttpd.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@ Future<void> main(List<String> args) async {
await Dhttpd.start(
path: options.path,
port: options.port,
headers:
options.headers != null ? _parseKeyValuePairs(options.headers!) : null,
address: options.host,
);

print('Server started on port ${options.port}');
}

Map<String, String> _parseKeyValuePairs(String str) => <String, String>{
for (var match in _regex.allMatches(str))
match.group(1)!: match.group(2)!,
};

final _regex = RegExp(r'([\w-]+)=([\w-]+)(;|$)');
14 changes: 14 additions & 0 deletions lib/dhttpd.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ class Dhttpd {
String? path,
int port = defaultPort,
Object address = defaultHost,
Map<String, String>? headers,
}) async {
path ??= Directory.current.path;

final pipeline = const Pipeline()
.addMiddleware(logRequests())
.addMiddleware(_headersMiddleware(headers))
.addHandler(createStaticHandler(path, defaultDocument: 'index.html'));

final server = await io.serve(pipeline, address, port);
Expand All @@ -46,3 +48,15 @@ class Dhttpd {

Future<void> destroy() => _server.close();
}

Middleware _headersMiddleware(Map<String, String>? headers) =>
(Handler innerHandler) => (Request request) async {
final response = await innerHandler(request);
final responseHeaders = Map<String, String>.from(response.headers);
if (headers != null) {
for (var entry in headers.entries) {
responseHeaders[entry.key] = entry.value;
}
}
return response.change(headers: responseHeaders);
};
7 changes: 7 additions & 0 deletions lib/src/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class Options {
' If not set, the current directory is used.')
final String? path;

@CliOption(
valueHelp: 'headers',
help:
'HTTP headers to apply to each response. header=value;header2=value')
final String? headers;

@CliOption(
defaultsTo: defaultHost,
valueHelp: 'host',
Expand All @@ -34,6 +40,7 @@ class Options {
Options({
required this.port,
this.path,
this.headers,
required this.host,
required this.help,
});
Expand Down
6 changes: 6 additions & 0 deletions lib/src/options.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: dhttpd
version: 4.0.2-wip
version: 4.1.0

description: A static HTTP file server for easy local hosting of a directory.
repository: https://github.com/kevmoo/dhttpd
Expand Down
13 changes: 7 additions & 6 deletions test/readme_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ Future<void> _readmeCheck(List<String> args) async {

expect(expected, r'''```console
$ dhttpd --help
-p, --port=<port> The port to listen on.
(defaults to "8080")
--path=<path> The path to serve. If not set, the current directory is used.
--host=<host> The hostname to listen on.
(defaults to "localhost")
-h, --help Displays the help.
-p, --port=<port> The port to listen on.
(defaults to "8080")
--path=<path> The path to serve. If not set, the current directory is used.
--headers=<headers> HTTP headers to apply to each response. header=value;header2=value
--host=<host> The hostname to listen on.
(defaults to "localhost")
-h, --help Displays the help.
```''');

expect(readme.readAsStringSync(), contains(expected));
Expand Down

0 comments on commit 3c0f0ad

Please sign in to comment.