Closed insinfo closed 2 months ago
Based on initial scanning through the code, "x-frame-options" is not explicitly set anywhere. Will have to run through debug and analysis session to see where this comes from.
It comes from HttpServer.defaultResponseHeaders
. It's not set directly by Angel: https://api.dart.dev/stable/2.17.7/dart-io/HttpServer/defaultResponseHeaders.html
IIRC you can do something like HttpServer.defaultResponseHeaders.remove("x-frame-options");
.
@thosakwe Can I do this in the angel instance without modifying the angel package code?
@thosakwe Can I do this in the angel instance without modifying the angel package code?
Hi Isaque, Http.defaultResponseHeaders
is a global variable, if I remember correctly. It's not dependent on Angel, so you should be able to remove x-frame-options
without modifying any Angel package code.
It's been a long time since I've touched Dart/Angel code, but I think you can just do something like this in the entry point of your program:
main() async {
// Change global settings on startup
HttpServer.defaultResponseHeaders.remove("x-frame-options");
var app = Angel();
// ... Initialize app logic...
}
Best of luck, and thanks everyone for keeping the spirit of Angel alive. It means a lot to me.
@thosakwe Thank you very much for the feedback, I saw that get defaultResponseHeaders is an instance property, it's not static, so I had to modify the angel3_hot.dart and angel3_production.dart files
// TODO add this
/// Boots a shared server instance. Use this if launching multiple isolates.
Future<HttpServer> Function(dynamic, int) _startSharedHttpServer() {
return (address, int port) async {
final server =
await HttpServer.bind(address ?? '127.0.0.1', port, shared: true);
server.defaultResponseHeaders.remove('X-Frame-Options', 'SAMEORIGIN');
return Future.value(server);
};
}
Future<AngelHttp> _generateServer() async {
var app = await generator();
await Future.forEach(app.startupHooks, app.configure);
app.optimizeForProduction();
// TODO change to _startSharedHttpServer
final angelServer = await AngelHttp.custom(app, _startSharedHttpServer());
return Future.value(angelServer);
}
/// Starts listening to requests and filesystem events.
Future<HttpServer> startServer([address, int? port]) async {
var isHot = true;
_server = await _generateServer();
if (_paths.isNotEmpty != true) {
_logWarning(
'You have instantiated a HotReloader without providing any filesystem paths to watch.');
}
bool sw(String s) {
return Platform.executableArguments.any((ss) => ss.startsWith(s));
}
if (!sw('--observe') && !sw('--enable-vm-service')) {
_logWarning(
'You have instantiated a HotReloader without passing `--enable-vm-service` or `--observe` to the Dart VM. Hot reloading will be disabled.');
isHot = false;
} else {
var info = await dev.Service.getInfo();
var uri = info.serverUri!;
uri = uri.replace(path: p.join(uri.path, 'ws'));
if (uri.scheme == 'https') {
uri = uri.replace(scheme: 'wss');
} else {
uri = uri.replace(scheme: 'ws');
}
_client = await vm.vmServiceConnectUri(uri.toString());
_vmachine ??= await _client.getVM();
_mainIsolate ??= _vmachine?.isolates?.first;
if (_vmachine != null) {
for (var isolate in _vmachine!.isolates ?? <vm.IsolateRef>[]) {
if (isolate.id != null) {
await _client.setIsolatePauseMode(isolate.id!,
exceptionPauseMode: 'None');
}
}
}
await _listenToFilesystem();
}
_onChange.stream
//.transform( _Debounce( Duration(seconds: 1)))
.listen(_handleWatchEvent);
while (_requestQueue.isNotEmpty) {
await _handle(_requestQueue.removeFirst());
}
var server = _io = await HttpServer.bind(address ?? '127.0.0.1', port ?? 0);
// TODO add this
server.defaultResponseHeaders.remove('X-Frame-Options', 'SAMEORIGIN');
server.listen(handleRequest);
// Print a Flutter-like prompt...
if (enableHotkeys) {
var serverUri =
Uri(scheme: 'http', host: server.address.address, port: server.port);
Uri? observatoryUri;
if (isHot) {
observatoryUri = await dev.Service.getInfo().then((i) => i.serverUri!);
}
print(styleBold.wrap(
'\n🔥 To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".'));
stdout.write('Your server is listening at: ');
print(wrapWith('$serverUri', [cyan, styleUnderlined]));
if (isHot) {
stdout.write(
'An Observatory debugger and profiler on ${Platform.operatingSystem} is available at: ');
print(wrapWith('$observatoryUri', [cyan, styleUnderlined]));
} else {
stdout.write(
'The observatory debugger and profiler are not available.\n');
}
print(
'For a more detailed help message, press "h". To quit, press "q".\n');
if (_paths.isNotEmpty) {
print(darkGray.wrap(
'Changes to the following path(s) will also trigger a hot reload:'));
for (var p in _paths) {
print(darkGray.wrap(' * $p'));
}
stdout.writeln();
}
// Listen for hotkeys
try {
stdin.lineMode = stdin.echoMode = false;
} catch (_) {}
late StreamSubscription<int> sub;
try {
sub = stdin.expand((l) => l).listen((ch) async {
if (ch == $r) {
_handleWatchEvent(
WatchEvent(ChangeType.MODIFY, '[manual-reload]'), isHot);
}
if (ch == $R) {
_logInfo('Manually restarting server...\n');
await _killServer();
await _server!.close();
var addr = _io.address.address;
var port = _io.port;
await _io.close(force: true);
await startServer(addr, port);
} else if (ch == $q) {
stdin.echoMode = stdin.lineMode = true;
await close();
await sub.cancel();
exit(0);
} else if (ch == $h) {
print(
'Press "r" to hot reload the Dart VM, and restart the active server.');
print(
'Press "R" to restart the server, WITHOUT a hot reload of the VM.');
print('Press "q" to quit the server.');
print('Press "h" to display this help information.');
stdout.writeln();
}
});
} catch (_) {}
}
return server;
}
// TODO add this
/// Boots a shared server instance. Use this if launching multiple isolates.
static Future<HttpServer> Function(dynamic, int) startSharedHttpServer() {
return (address, int port) async {
final server =
await HttpServer.bind(address ?? '127.0.0.1', port, shared: true);
server.defaultResponseHeaders.remove('X-Frame-Options', 'SAMEORIGIN');
return Future.value(server);
};
}
static Future<HttpServer> Function(dynamic, int) startSharedSecureHttpServer(
SecurityContext securityContext) {
return (address, int port) async {
final server = await HttpServer.bindSecure(
address ?? '127.0.0.1', port, securityContext,
shared: true);
server.defaultResponseHeaders.remove('X-Frame-Options', 'SAMEORIGIN');
return Future.value(server);
};
}
static void isolateMain(RunnerArgsWithId argsWithId) {
var args = argsWithId.args;
hierarchicalLoggingEnabled = false;
var zone = Zone.current.fork(specification: ZoneSpecification(
print: (self, parent, zone, msg) {
args.loggingSendPort.send(LogRecord(Level.INFO, msg, args.loggerName));
},
));
zone.run(() async {
var client =
pub_sub.IsolateClient('client${argsWithId.id}', args.pubSubSendPort);
var app = Angel(reflector: args.reflector)
..container.registerSingleton<pub_sub.Client>(client)
..container.registerSingleton(InstanceInfo(id: argsWithId.id));
app.shutdownHooks.add((_) => client.close());
await app.configure(args.configureServer);
app.logger = Logger(args.loggerName)
..onRecord.listen((rec) => Runner.handleLogRecord(rec, args.options));
AngelHttp http;
late SecurityContext securityContext;
Uri serverUrl;
if (args.options.ssl || args.options.http2) {
securityContext = SecurityContext();
if (args.options.certificateFile != null) {
securityContext.useCertificateChain(args.options.certificateFile!,
password: args.options.certificatePassword);
}
if (args.options.keyFile != null) {
securityContext.usePrivateKey(args.options.keyFile!,
password: args.options.keyPassword);
}
}
if (args.options.ssl) {
// TODO change to startSharedSecureHttpServer
http = AngelHttp.custom(
app, startSharedSecureHttpServer(securityContext),
useZone: args.options.useZone);
} else {
// TODO change to startSharedHttpServer
http = AngelHttp.custom(app, startSharedHttpServer(),
useZone: args.options.useZone);
}
Driver driver;
if (args.options.http2) {
securityContext.setAlpnProtocols(['h2'], true);
var http2 = AngelHttp2.custom(app, securityContext, startSharedHttp2,
useZone: args.options.useZone);
http2.onHttp1.listen(http.handleRequest);
driver = http2;
} else {
driver = http;
}
await driver.startServer(args.options.hostname, args.options.port);
serverUrl = driver.uri;
if (args.options.ssl || args.options.http2) {
serverUrl = serverUrl.replace(scheme: 'https');
}
print('Instance #${argsWithId.id} listening at $serverUrl');
});
}
angel3_production:8.1.0
now can support passing addition parameters to add or remove headers. See example in the updated README.md. For angel3_hot
, defaultResponseHeaders
method is already accessible. See example in the updated README.md.
@duquefirehawk Thank you very much for your commitment and dedication to this project
How to remove "x-frame-options" header from files returned by VirtualDirectory Middleware from angel3_static package: ^4.1.0