dart 的官方网站提供了一个simple dart server,具体使用方法参考相关github的地址。
https://github.com/dart-lang/pub_server
我们选了一个PC作为服务器,24小时不关机。然后在内网中部署服务。
配置好后,服务启起来。
主要障碍在于上传的过程需要科学上网,科学上网结束后,又需要切回到内网。
使用flutter 默认的pub client进行上传的步骤:
1、配置fq环境(因为上传过程中需要google验证,需要fq)
2、设置命令行窗口代理 window set https_proxy=https://127.0.0.1:{翻墙工具的本地监听端口}
3、上传前检查配置 flutter packages pub publish --dry-run
4、开始上传 flutter packages pub publish --server=http://10.118.63.101:8080
如果上传过程中没有收到验证,把代理设置为全局模式。
如果第一次上传 uploading。。。卡住,需要多试几次。只要上传成功一次,后面上传就很容易。
如果上传时提示包过大,删除build目录,删除ios目录,删除Android目录。然后重试。
如果工程中没有LICENSE,可以新建一个text文本命名为LICENSE,内容 可以为空。
如果上传地址不对,最好插件的pubspec.yaml中也加入 publish_to: http://10.118.63.101:8080
国庆到了,突然诸多科学上网工具都不好使了。这于是非常不方便了,开发的dart插件无法上传。
很自然想到,有没有办法自己写个dart pub工具,于是去找系统的pub工具是怎样执行的。
发现执行的是一个pub.dart.snapshot文件。这是一个dart库打包构建后的产物。
那么如果能够把dart pub client中oauth google认证的流程给去掉,不就可以了吗?
dart是开源的,dart pub tool应该也是开源的,于是找找看。
没想到找到了:https://github.com/dart-lang/pub
有个lish文件,包含了publish命令,找到关键代码。
Future _publish(List<int> packageBytes) async {
Uri cloudStorageUrl;
try {
await oauth2.withClient(cache, (client) {
return log.progress('Uploading', () async {
// TODO(nweiz): Cloud Storage can provide an XML-formatted error. We
// should report that error and exit.
var newUri = server.resolve("/api/packages/versions/new");
var response = await client.get(newUri, headers: pubApiHeaders);
var parameters = parseJsonResponse(response);
var url = _expectField(parameters, 'url', response);
if (url is! String) invalidServerResponse(response);
cloudStorageUrl = Uri.parse(url);
var request = http.MultipartRequest('POST', cloudStorageUrl);
var fields = _expectField(parameters, 'fields', response);
if (fields is! Map) invalidServerResponse(response);
fields.forEach((key, value) {
if (value is! String) invalidServerResponse(response);
request.fields[key] = value;
});
request.followRedirects = false;
request.files.add(http.MultipartFile.fromBytes('file', packageBytes,
filename: 'package.tar.gz'));
var postResponse =
await http.Response.fromStream(await client.send(request));
var location = postResponse.headers['location'];
if (location == null) throw PubHttpException(postResponse);
handleJsonSuccess(await client.get(location, headers: pubApiHeaders));
});
});
} on PubHttpException catch (error) {
var url = error.response.request.url;
if (url == cloudStorageUrl) {
// TODO(nweiz): the response may have XML-formatted information about
// the error. Try to parse that out once we have an easily-accessible
// XML parser.
fail(log.red('Failed to upload the package.'));
} else if (Uri.parse(url.origin) == Uri.parse(server.origin)) {
handleJsonError(error.response);
} else {
rethrow;
}
}
}
重点在于删掉外层的oauth2.withClient(),里面的client替换成自己的http.Client()。
Future _publish(List<int> packageBytes) async {
Uri cloudStorageUrl;
try {
// await oauth2.withClient(cache, (client) {
var httpClient =http.Client();
return log.progress('Uploading', () async {
// TODO(nweiz): Cloud Storage can provide an XML-formatted error. We
// should report that error and exit.
var newUri = server.resolve("/api/packages/versions/new");
// var uri=Uri(scheme: "http", host: "$newUri", queryParameters: pubApiHeaders);
var response = await httpClient.get(newUri, headers: pubApiHeaders);
// var response = await httpClient.get(uri);
var parameters = parseJsonResponse(response);
var url = _expectField(parameters, 'url', response);
if (url is! String) invalidServerResponse(response);
cloudStorageUrl = Uri.parse(url);
var request = http.MultipartRequest('POST', cloudStorageUrl);
var fields = _expectField(parameters, 'fields', response);
if (fields is! Map) invalidServerResponse(response);
fields.forEach((key, value) {
if (value is! String) invalidServerResponse(response);
request.fields[key] = value;
});
request.followRedirects = false;
request.files.add(http.MultipartFile.fromBytes('file', packageBytes,
filename: 'package.tar.gz'));
var postResponse =
await http.Response.fromStream(await httpClient.send(request));
var location = postResponse.headers['location'];
if (location == null) throw PubHttpException(postResponse);
handleJsonSuccess(await httpClient.get(location, headers: pubApiHeaders));
});
// });
} on PubHttpException catch (error) {
var url = error.response.request.url;
if (url == cloudStorageUrl) {
// TODO(nweiz): the response may have XML-formatted information about
// the error. Try to parse that out once we have an easily-accessible
// XML parser.
fail(log.red('Failed to upload the package.'));
} else if (Uri.parse(url.origin) == Uri.parse(server.origin)) {
handleJsonError(error.response);
} else {
rethrow;
}
}
}
可以选择编译成自己的snapshot文件,命令形式如下。
dart [--package_root=<path>] --snapshot=<output_file> <dart_file>
dart --snapshot=my.dart.snapshot D:\code\pub-master\bin\pub.dart
生成的产物如下
dart my.dart.snapshot xxx工程的路径
很快就成功了,再也没有认证过程来烦恼了。
修改后的文件:https://github.com/ameryzhu/pub/blob/master/lib/src/command/lish.dart
完整的folk库:
https://github.com/ameryzhu/pub
使用方式: