dartist / express

A thin express-js inspired layer around Dart's primitive HttpServer APIs
Other
126 stars 11 forks source link

Header already sent #20

Closed agreatfool closed 3 years ago

agreatfool commented 10 years ago
  app.get('/oauth2next', (HttpContext ctx) {
    Map queries = Uri.splitQueryString(ctx.uri.query);
    Map done = pinGoogleOAuth.processOAuthNext(queries).then((Map done) {
      if (done['result']) {
        ctx.res.redirect(Uri.parse(ctx.uri.host)); // FAILED on this line
      } else {
        ctx.sendJson(done);
      }
    });
  });
Uncaught Error: Bad state: Header already sent
Stack Trace:
#0      _HttpResponse.redirect (dart:io/http_impl.dart:530)
#1      main.<anonymous closure>.<anonymous closure> (file:///.../bin/web.dart:68:25)
#2      _rootRunUnary (dart:async/zone.dart:730)
#3      _RootZone.runUnary (dart:async/zone.dart:864)
#4      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488)
#5      _Future._propagateToListeners (dart:async/future_impl.dart:571)
#6      _Future._completeWithValue (dart:async/future_impl.dart:331)
#7      _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:393)
#8      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#9      _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)

Any idea when the headers were sent and by who?

SamVerschueren commented 10 years ago

Did you use pub to install Express or did you download the sourcecode of github? If I find the time I will have a look at the problem...

The querystring parameters can also be found in ctx.params by the way ;).

agreatfool commented 10 years ago

Yes, Express was installed before I ran the code.

And thank you for the hint, I found it~

  Map<String,String> get params{
    if (_params == null){
      _params = pathMatcher(routePath, req.uri.path);
      _params.addAll(req.uri.queryParameters);
    }
    return _params;
  }
SamVerschueren commented 10 years ago

What library are you using for the OAuth? Can you give a little bit more code as well. I am trying to reproduce the error.

agreatfool commented 10 years ago

Sorry for the late reply. I'm using the official oauth2 lib on pub site: https://pub.dartlang.org/packages/oauth2 You can have a look at my codes in repo: https://github.com/agreatfool/Cart Entrance is: src/bin/web.dart

Workflow is: First, send oauth privileges confirm request

app.get('/oauth2', (HttpContext ctx) {
  ctx.res.redirect(Uri.parse(pinGoogleOAuth.getOAuthUrl())); // redirect user from my site to google oauth page
});

Second, user confirm the oauth dialogue, and redirected to my site '/oauth2next'

app.get('/oauth2next', (HttpContext ctx) {
  Map queries = Uri.splitQueryString(ctx.uri.query);
  Map done = pinGoogleOAuth.processOAuthNext(queries).then((Map done) {
    if (done['result']) {
      ctx.res.redirect(Uri.parse(ctx.uri.host)); // FAILED on this line
    } else {
      ctx.sendJson(done);
    }
  });
});

Third, the logic in function pinGoogleOAuth.processOAuthNext:

  Future<Map> processOAuthNext(Map data) {
    var completer = new Completer();

    Map res = {
      'result': false,
      'message': ''
    };

    PinLogger.instance.fine('[PinGoogleOAuth] processOAuthNext data: ${JSON.encode(data)}');

    if (data.containsKey('code')) {
      // oauth code got, process next step
      LibHttp.post(
          GOOGLE_OAUTH_TOKEN_URL,
          body: {
              'code': data['code'],
              'client_id': _identifier,
              'client_secret': _secret,
              'redirect_uri': _redirectUrl,
              'grant_type': 'authorization_code'
          }
      ).then((LibHttp.Response response) {
        // token response got
        PinLogger.instance.fine('[PinGoogleOAuth] processOAuthNext auth response: ${response.body}');
        Map authResponse;
        try {
          authResponse = JSON.decode(response.body);
        } catch (e) {
          res['message'] = response.body;
          completer.complete(res);
        }
        if (authResponse.containsKey('access_token')) {
          // access token got
          var expiration = null;
          if (authResponse.containsKey('expires_in')) {
            var now = new DateTime.now();
            now.add(new Duration(seconds: authResponse['expires_in']));
            expiration = now.millisecondsSinceEpoch;
          }
          Map credentials = {
              'accessToken': authResponse['access_token'],
              'refreshToken': authResponse['refresh_token'],
              'tokenEndpoint': GOOGLE_OAUTH_TOKEN_URL,
              'scopes': _scopes,
              'expiration': expiration
          };
          if (authResponse.containsKey('id_token')) {
            credentials['idToken'] = authResponse['id_token'];
          }
          var decoder = new JsonEncoder.withIndent('    ');
          new File(_credentialsFilePath).writeAsString(decoder.convert(credentials)).then((_) {
            res['result'] = true;
            completer.complete(res);
          });
        } else if (authResponse.containsKey('error')) {
          // error
          res['message'] = 'Error: ${authResponse['error']}';
          completer.complete(res);
        } else {
          // unrecognized
          res['message'] = 'Error: Unrecognized oauth response';
          completer.complete(res);
        }
      });
    } else if (data.containsKey('error')) {
      // error
      res['message'] = 'Error: ${data['error']}';
      completer.complete(res);
    } else {
      // unrecognized
      res['message'] = 'Error: Unrecognized oauth response';
      completer.complete(res);
    }

    return completer.future;
  }
DisDis commented 10 years ago

Express don't work after update dart to 1.6. All request broken "Header already sent"

vvnab commented 9 years ago
    Express don't work after update dart to 1.6. All request broken "Header already sent"

Dart v1.9.1 All request broken "Header already sent"