Search code examples
c#.net.net-corehttplistener

HttpListener application closed after handling first request


await main.RunWebHookSubscription();
//

public async Task RunWebHookSubscription()
        {

            Console.WriteLine("Hook waiting");

            HttpListener listener = new HttpListener();
            listener.Prefixes.Add("http://localhost:8080/hook/");
            listener.Start();
            Task<HttpListenerContext> context = listener.GetContextAsync();
            await HandleRequestAsyncRun(await context);
        }

        async Task HandleRequestAsyncRun(HttpListenerContext context)
        {
            var request = context.Request;
            var body = WebHookRequestHadler(request);
            Console.Write(body);
            var eventData = JsonSerializer.Deserialize<WebHookEventData>(body);
            //TODO Call method
        }

        string WebHookRequestHadler(HttpListenerRequest request)
        {
            
            if (!request.HasEntityBody)
            {
                return null;
            }
            using (System.IO.Stream body = request.InputStream) // here we have data
            {
                using (var reader = new System.IO.StreamReader(body, request.ContentEncoding))
                {
                    return reader.ReadToEnd();
                }
            }

After handling the first request my application closed. How can I handle requests permanently?


Solution

  • You need to hand off the context to another thread, and then loop back to accept another connection.

    You should also dispose the context with using, and stop the listener in a finally.

    public async Task RunWebHookSubscription()
    {
        Console.WriteLine("Hook waiting");
    
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8080/hook/");
        listener.Start();
        try
        {
            while (true)
            {
                context = await listener.GetContextAsync();
                Task.Run(async () =>
                {
                    using (context.Response)
                        await HandleRequestAsyncRun(context);
                });
            }
        }
        finally
        {
            listener.Stop();
        }
    }
    

    Consider using Console.CancelKeyPress along with a CancellationTokenSource to cancel the listener loop.