d9088aeec6
ci / 📄 License Check (push) Has been cancelled
ci / ✅ Semantic Pull Request (push) Has been cancelled
ci / 🔤 Check Spelling (push) Has been cancelled
ci / 👀 Detect Changes (push) Has been cancelled
ci / 🎯 Build ${{ matrix.package }} (${{ matrix.os }}) (push) Has been cancelled
ci / 🎯 Build ${{ matrix.package }} (push) Has been cancelled
ci / 🔎 Verify ${{ matrix.package }} (push) Has been cancelled
ci / ci (push) Has been cancelled
Deploy Artifact Proxy Dev / ☁️ Artifact Proxy (push) Has been cancelled
Shorebird CI / changes (push) Has been cancelled
Shorebird CI / CSpell (push) Has been cancelled
Shorebird CI / artifact_proxy (push) Has been cancelled
Shorebird CI / dex (push) Has been cancelled
Shorebird CI / discord_gcp_alerts (push) Has been cancelled
Shorebird CI / flutter_version_resolver (push) Has been cancelled
Shorebird CI / jwt (push) Has been cancelled
Shorebird CI / scoped_deps (push) Has been cancelled
Shorebird CI / shorebird_build_trace (push) Has been cancelled
Shorebird CI / shorebird_ci (push) Has been cancelled
Shorebird CI / shorebird_cli (push) Has been cancelled
Shorebird CI / shorebird_code_push_client (push) Has been cancelled
Shorebird CI / shorebird_code_push_protocol (push) Has been cancelled
Shorebird CI / shorebird_redis_client (push) Has been cancelled
Shorebird CI / stripe_api (push) Has been cancelled
Shorebird CI / required (push) Has been cancelled
- Updated AAR releaser test to use ShorebirdProcess.defaultFlutterStorageBaseUrl. - Changed macOS releaser test to reference a new troubleshooting URL. - Enhanced shorebird_yaml_test with deserialization for AOT patch metadata. - Modified network_checker_test to check self-hosted URLs from ShorebirdEnv. - Added tests for artifact paths in shorebird_artifacts_test. - Updated shorebird_cli_command_runner_test to reflect new repository URL. - Improved shorebird_env_test with additional tests for shorebirdRoot and engine revision fallback. - Adjusted shorebird_flutter_test to use environment variables for Flutter Git URL. - Updated shorebird_process_test to utilize default Flutter storage URL. - Enhanced shorebird_validator_test to link to the default hosted URL. - Updated shorebird_web_console_test to use the configured hosted URL. - Refactored code_push_client to use default hosted URL for API requests. - Updated README and generation scripts for the code_push_protocol package to reflect new OpenAPI spec source. - Modified shared.sh to allow configurable Flutter repository and storage URLs. Signed-off-by: Tony <tonylu@tony-cloud.com>
176 lines
5.2 KiB
Dart
176 lines
5.2 KiB
Dart
// print is used for diagnostic logs.
|
|
// ignore_for_file: avoid_print
|
|
|
|
import 'package:artifact_proxy/artifact_proxy.dart';
|
|
import 'package:artifact_proxy/config.dart';
|
|
import 'package:shelf/shelf.dart';
|
|
|
|
const String _explainerHtml = """
|
|
<html>
|
|
<head>
|
|
<title>Shorebird Artifact Proxy</title>
|
|
</head>
|
|
<body>
|
|
<p>
|
|
This server proxies requests for Flutter artifacts to the correct location,
|
|
depending on the engine revision. Most artifacts are served from the configured
|
|
Flutter artifact origin, but a few artifacts are served from the configured
|
|
open Shorebird artifact mirror to add support for code push.
|
|
</p>
|
|
<p>
|
|
See the workspace README and docs/CI.md for open artifact mirror details.
|
|
</p>
|
|
<p>
|
|
Source code can be found here:
|
|
<a
|
|
href='https://git.tonycloud.org/flutter/shorebird'>
|
|
https://git.tonycloud.org/flutter/shorebird</a>
|
|
</p>
|
|
<p>
|
|
If you're seeing problems with this open artifact proxy, file an issue against
|
|
the repository that hosts this workspace.
|
|
</p>
|
|
</body>
|
|
</html>
|
|
""";
|
|
|
|
/// A [Handler] that proxies artifact requests to the correct location.
|
|
Handler artifactProxyHandler({
|
|
required ArtifactManifestClient client,
|
|
Uri? flutterArtifactBaseUri,
|
|
Uri? shorebirdArtifactBaseUri,
|
|
}) {
|
|
final flutterBaseUri =
|
|
flutterArtifactBaseUri ?? defaultFlutterArtifactBaseUri;
|
|
final shorebirdBaseUri =
|
|
shorebirdArtifactBaseUri ?? defaultShorebirdArtifactBaseUri;
|
|
|
|
return (Request request) async {
|
|
final path = request.url.path;
|
|
if (path.isEmpty) {
|
|
return Response.ok(
|
|
_explainerHtml,
|
|
headers: {'content-type': 'text/html'},
|
|
);
|
|
}
|
|
|
|
RegExpMatch? engineArtifactMatch;
|
|
for (final pattern in engineArtifactPatterns) {
|
|
final match = RegExp(pattern).firstMatch(path);
|
|
if (match != null && match.group(1) != null) {
|
|
engineArtifactMatch = match;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (engineArtifactMatch != null) {
|
|
final shorebirdEngineRevision = engineArtifactMatch.group(1)!;
|
|
final ArtifactsManifest manifest;
|
|
try {
|
|
manifest = await client.getManifest(shorebirdEngineRevision);
|
|
} on Exception catch (error) {
|
|
return Response.notFound(
|
|
'Failed to fetch manifest for $shorebirdEngineRevision\n$error',
|
|
);
|
|
}
|
|
|
|
final normalizedPath = path.replaceAll(
|
|
shorebirdEngineRevision,
|
|
r'$engine',
|
|
);
|
|
|
|
final shouldOverride = manifest.artifactOverrides.contains(
|
|
normalizedPath,
|
|
);
|
|
|
|
if (shouldOverride) {
|
|
final location = getShorebirdArtifactLocation(
|
|
artifactPath: normalizedPath,
|
|
engine: shorebirdEngineRevision,
|
|
bucket: manifest.storageBucket,
|
|
baseUri: shorebirdBaseUri,
|
|
);
|
|
print('Shorebird engine artifact detected, forwarding to: $location');
|
|
return Response.found(location);
|
|
}
|
|
|
|
final location = getFlutterArtifactLocation(
|
|
artifactPath: normalizedPath,
|
|
engine: manifest.flutterEngineRevision,
|
|
baseUri: flutterBaseUri,
|
|
);
|
|
print('Flutter artifact detected, forwarding to: $location');
|
|
return Response.found(location);
|
|
}
|
|
|
|
final isRecognizedFlutterArtifact = flutterArtifactPatterns.any(
|
|
(pattern) => RegExp(pattern).hasMatch(path),
|
|
);
|
|
|
|
if (!isRecognizedFlutterArtifact) {
|
|
return Response.notFound('Unrecognized artifact path: $path');
|
|
}
|
|
|
|
final location = getFlutterArtifactLocation(
|
|
artifactPath: path,
|
|
baseUri: flutterBaseUri,
|
|
);
|
|
print('Flutter artifact detected, forwarding to: $location');
|
|
return Response.found(location);
|
|
};
|
|
}
|
|
|
|
/// Default public Flutter artifact origin.
|
|
final defaultFlutterArtifactBaseUri = Uri.parse(
|
|
'https://storage.googleapis.com',
|
|
);
|
|
|
|
/// Default root for open self-hosted Shorebird artifacts.
|
|
final defaultShorebirdArtifactBaseUri = Uri.parse(
|
|
'http://localhost:8080/artifacts',
|
|
);
|
|
|
|
/// Returns the location of the artifact at [artifactPath] using the
|
|
/// specified [engine] revision for original Flutter artifacts.
|
|
String getFlutterArtifactLocation({
|
|
required String artifactPath,
|
|
String? engine,
|
|
Uri? baseUri,
|
|
}) {
|
|
final adjustedPath = engine != null
|
|
? artifactPath.replaceAll(r'$engine', engine)
|
|
: artifactPath;
|
|
|
|
return _joinUri(
|
|
baseUri ?? defaultFlutterArtifactBaseUri,
|
|
adjustedPath,
|
|
).toString();
|
|
}
|
|
|
|
/// Returns the location of the artifact at [artifactPath] using the
|
|
/// specified [engine] revision for Shorebird artifacts.
|
|
String getShorebirdArtifactLocation({
|
|
required String artifactPath,
|
|
required String engine,
|
|
required String bucket,
|
|
Uri? baseUri,
|
|
}) {
|
|
final adjustedPath = artifactPath.replaceAll(r'$engine', engine);
|
|
final bucketUri = Uri.tryParse(bucket);
|
|
final resolvedBaseUri = bucketUri != null && bucketUri.hasScheme
|
|
? bucketUri
|
|
: baseUri ?? defaultShorebirdArtifactBaseUri;
|
|
final path = bucketUri != null && bucketUri.hasScheme
|
|
? adjustedPath
|
|
: [if (bucket.isNotEmpty) bucket, adjustedPath].join('/');
|
|
return _joinUri(resolvedBaseUri, path).toString();
|
|
}
|
|
|
|
Uri _joinUri(Uri base, String path) {
|
|
final basePath = base.path.endsWith('/')
|
|
? base.path.substring(0, base.path.length - 1)
|
|
: base.path;
|
|
final relativePath = path.startsWith('/') ? path.substring(1) : path;
|
|
return base.replace(path: '$basePath/$relativePath');
|
|
}
|