Search code examples
dartrikulo

How to call web services on Rikulo's dart stream server?


I've got a technical problem while trying to consume a restful web service on the Stream server.

I use HTTPClient.openUrl to retrieve a JSON response from another remote server but once the connection is opened, I can no longer write response(connect.response.write) to my browser client.

The error is listed as following:

    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)

Any one knows the correct way of calling web services on the stream server?


Solution

  • The key is you have to return Future, since your task (openUrl) is asynchronous. In your sample code, you have to do:

    return conn.then((HttpClientRequest request) {
    //^-- notice: you must return a future to indicate when the serving is done
    

    For more information, refer to Request Handling. To avoid this kind of mistake, I post a feature request here.

    Here is a working sample:

    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();
    }