我在尝试在Stream服务器上使用restful Web服务时遇到了技术问题。
我使用HTTPClient.openUrl从另一台远程服务器检索JSON响应,但是一旦打开连接,我就不能再将响应(connect.response.write)写入浏览器客户端。
错误列如下:
Unhandled exception:
Bad state: StreamSink is closed
#0 _FutureImpl._scheduleUnhandledError.<anonymous closure> (dart:async:325:9)
#1 Timer.run.<anonymous closure> (dart:async:2251:21)
#2 Timer.run.<anonymous closure> (dart:async:2259:13)
#3 Timer.Timer.<anonymous closure> (dart:async-patch:15:15)
#4 _Timer._createTimerHandler._handleTimeout (dart:io:6730:28)
#5 _Timer._createTimerHandler._handleTimeout (dart:io:6738:7)
#6 _Timer._createTimerHandler.<anonymous closure> (dart:io:6746:23)
#7 _ReceivePortImpl._handleMessage (dart:isolate-patch:81:92)
任何人都知道在流服务器上调用Web服务的正确方法吗?
答案 0 :(得分:2)
关键是你必须返回Future,因为你的任务(openUrl)是异步的。在您的示例代码中,您必须执行以下操作:
return conn.then((HttpClientRequest request) {
//^-- notice: you must return a future to indicate when the serving is done
有关详细信息,请参阅Request Handling。为了避免这种错误,我发布了a feature request here。
以下是一份工作样本:
library issues;
import "dart:io";
import "dart:uri";
import "package:rikulo_commons/io.dart" show IOUtil;
import "package:stream/stream.dart";
void main() {
new StreamServer(uriMapping: {
"/": (connect)
=> new HttpClient().getUrl(new Uri("http://google.com"))
.then((req) => req.close())
.then((res) => IOUtil.readAsString(res))
.then((result) {
connect.response.write(result);
})
}).start();
}
答案 1 :(得分:0)
这是我的原始代码:
void startProcess(HttpConnect connect){
String method = "GET";
String url = "http://XXXXXX/activiti-rest/service/deployments";
Map authentication = {"username":"XXXXX", "password":"XXXXX"};
Map body = {"XXXXX":"XXXXX", "XXXXX":"XXXXX"};
processRequest(connect, method, url, authentication, body.toString());
}
void processRequest(HttpConnect connect, String method, String url, Map authentication, String body) {
HttpClient client = new HttpClient();
Uri requestUri = Uri.parse(url);
Future<HttpClientRequest> conn = client.openUrl(method, requestUri);
conn.then((HttpClientRequest request) {
request.headers.add(HttpHeaders.CONTENT_TYPE, Constants.CONTENT_TYPE_JSON);
// Add base64 authentication header, the class is contained in a separate dart file
String base64 = Base64String.encode('${authentication["username"]}:${authentication["password"]}');
base64 = 'Basic $base64';
request.headers.add("Authorization", base64);
switch( method ) {
case Constants.METHOD_GET: break;
case Constants.METHOD_POST:
body = body.replaceAllMapped(new RegExp(r'\b\w+\b'), (match) => '"${match.group(0)}"' );//no replacement for now
request.write(body);
break;
}
return request.close();
})
.then((HttpClientResponse response) {
return IOUtil.readAsString(response);
})
.then((String result) {
connect.response.write(result);
});
}