Обработка данных POST с помощью Dart Route после прослушивания потока

Я использую route для обработки http-запросов к моему серверу. Это мой текущий код маршрута:

HttpServer.bind("127.0.0.1", 8080).then((server) {
    new Router(server)
    ..filter(new RegExp(r'/.*'), addCorsHeaders)
    ..filter(new RegExp(r'/admin/.*'), authenticate)
    ..serve(userGetURL, method: 'GET').listen(userGetHandler)
    ..serve(userPostURL, method: 'POST').listen(userPostHandler);
}); 

Я пытаюсь получить данные JSON, которые я отправляю по URL-адресу. Данные будут использоваться для получения объекта из базы данных и возврата его вызывающей стороне в виде JSON. В основном я пытаюсь создать серверное приложение, которое будет обрабатывать все данные, и клиентское приложение, которое будет их отображать.

Я не могу понять, как получить данные из POST. Все, что я пробовал, требует, чтобы я слушал поток, но его уже слушают. Вот как я пытался получить данные POST:

userPostHandler(HttpRequest req) {
    req.listen((List<int> buffer) {
        // Return the data back to the client.
        res.write(new String.fromCharCodes(buffer));
        res.close();
    }
}

Проблема в том, что я получаю ошибку Bad state: Stream has already been listened to..

EDIT: фильтры

Future<bool> authenticate(HttpRequest req) {
  if (req.method == 'POST') {
    // Post data is not null
    // Authenticate user
    String userName = '';
    String password = '';
    User user = new User();
    user.DBConnect().then((User user) {
      return new Future.value(user.ValidateUser(userName, password));
    });
  }
}

Future<bool> addCorsHeaders(HttpRequest req) {
  print('${req.method}: ${req.uri.path}');
  req.response.headers.add('Access-Control-Allow-Origin', '*, ');
  req.response.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS, GET');
  req.response.headers.add('Access-Control-Allow-Headers',
      'Origin, X-Requested-With, Content-Type, Accept');
  return new Future.value(true);
}

person coryrwest    schedule 31.12.2013    source источник
comment
Я попробовал ваш код, и он работает без ошибок. asBroadcastStream() не было необходимости.   -  person Günter Zöchbauer    schedule 02.01.2014
comment
Я думаю, вы также слушаете один из ваших обработчиков фильтров.   -  person Günter Zöchbauer    schedule 02.01.2014
comment
В фильтре niether есть listens. Я думал, что проблема была в ..serve(..).listen(userPostHandler). Разве это не так?   -  person coryrwest    schedule 02.01.2014
comment
Да а как кажется, потому что где-то уже слушают. Я не мог заставить asBroadcastStream() работать. Ваша ошибка воспроизводится только тогда, когда я также добавляю прослушиватель в обработчик фильтра.   -  person Günter Zöchbauer    schedule 02.01.2014
comment
Я добавил фильтры, которые использую. Я не уверен, есть ли что-то там в качестве неявного слушателя. Любые идеи?   -  person coryrwest    schedule 02.01.2014
comment
Я не вижу никаких проблем в добавленном вами коде. Я думаю, что было бы лучше сообщить об этом как об ошибке.   -  person Günter Zöchbauer    schedule 02.01.2014
comment
Хорошо, спасибо за вашу помощь.   -  person coryrwest    schedule 02.01.2014


Ответы (2)


Я никогда не использовал пакет Route, но мне интересно, почему вы хотите слушать внутри обработчика. Разве вы не можете просто получить доступ к свойствам, которые хотите обработать?

В противном случае вы могли бы попробовать

req.asBroadcastStream().listen(...)

BroadcastStream поддерживает несколько прослушивателей. Дополнительные сведения см. в этой статье Использование потоков для передачи данных.

person Günter Zöchbauer    schedule 31.12.2013
comment
Как мне получить доступ к нужным свойствам, можете ли вы привести пример? - person coryrwest; 31.12.2013
comment
Можете ли вы предоставить больше информации о том, чего вы хотите достичь? Ваш пример (req.listen((List<int> buffer) ... не очень полезен, так как я не вижу, на что ссылается res., и мне интересно, действительно ли listen() обеспечивает List<int>. Если вы просто хотите создать ответ, загляните на github. com/dart-lang/route/blob/master/example/server.dart - person Günter Zöchbauer; 01.01.2014
comment
Я добавил абзац к моему вопросу, объясняя, что я пытаюсь сделать. Я хочу, чтобы клиентское приложение отправляло идентификатор объекта в серверное приложение, а серверное приложение возвращало этот объект клиентскому приложению. - person coryrwest; 02.01.2014

Используя следующий код, я смог заставить работать POST:

void main() {
    HttpServer.bind("127.0.0.1", 8080).then((server) {
        new Router(server)
        ..filter(new RegExp(r'/.*'), addCorsHeaders)
          ..filter(new RegExp(r'/admin/.*'), authenticate)
           ..serve(userGetURL, method: 'GET').listen(userGetHandler)
            ..serve(userPostURL, method: 'POST').listen(userPostHandler);
    }); 
}

Future userPostHandler(HttpRequest req) {
  bool headerSent = false;
  // Start listening before writing to the response.
  req.listen((List<int> buffer) {
    if (!headerSent) {
      req.response.write("User POST");
      headerSent = true;
    }
    req.response.write(new String.fromCharCodes(buffer));
    },
    // Use onDone to close the response.
    onDone: () => req.response.close()
  );
}

Вот что я понял. Любая запись в ответ автоматически истощает тело и, таким образом, уничтожает данные POST. Как упоминалось здесь. Кроме того, прослушивание ответа выполняется асинхронно и поэтому должно быть завершено до вызова функции close().

person coryrwest    schedule 03.01.2014