Search code examples
c#httplistener

HttpListener response is not sent before listener is stopped


I use the code below to get an oAuth code using a browser login, it works just fine ie. auth code is returned BUT there is some timing issue between responseOutput.WriteAsync() and http.stop().

When in debug (breakpoint on **** below), then the response is returned to the browser as expected.

If I the comment out the line http.stop() (**** below), then the response is returned to the browser as expected.

BUT If I run the code as usual then the browser shows "page cannot be found", so, it looks as though responseOutput.WriteAsync() is not actually completing (not begin 'awaited'). Do I need to do anything else to ensure that the response is completely sent before stopping the listener?

await GetAuthorizationCode();

public async Task GetAuthorizationCode() {
    
    // Creates an Listener
    string redirectUri = "http://127.0.0.1:12345"; 
    HttpListener http = new HttpListener();
    http.Prefixes.Add(redirectUri);
    http.Start();

    // Open auth page in browser
    string authUri = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?........"; 
    var authorizationRequest = authUri;
    Process.Start(authorizationRequest);

    // Wait for auth response.
    HttpListenerContext context = await http.GetContextAsync();

    var sCode = context.Request.QueryString.Get("code");

    //Send response to the browser.
    HttpListenerResponse response = context.Response;
    string responseString = string.Format("<html><head></head><body>Auth OK.</body></html>");
    var buffer = Encoding.UTF8.GetBytes(responseString);
    response.ContentLength64 = buffer.Length;

    using (Stream responseOutput = response.OutputStream)
    {
        await responseOutput.WriteAsync(buffer, 0, buffer.Length);
        responseOutput.Close();
    }

    //****** this line causes problems
    http.Stop();

    AuthorizationCode = sCode;
}

Solution

  • It seems that I have to set KeepAlive prior to http.stop()

    response.KeepAlive = False
    

    Somehow even with calling response.close and/or with a 'using' block around the response it still needed this setting.