C
C#2y ago
marsastro

❔ ✅ HttpListener only receives context once

Hey, I've set up a class that listens for traffic on localhost coming from a different app. The class looks like this:
public class FluxApiService
{
private HueApiService _hueApiService;
private HttpListener _listener;
private string _url = "http://localhost:8000/";

public FluxApiService(HueApiService hueApiService)
{
_listener = new HttpListener();
_listener.Prefixes.Add(_url);
_hueApiService = hueApiService;
}

public void Start()
{
Task.Run(async () => { await HandleIncomingConnections(); });
}

private async Task HandleIncomingConnections()
{
_listener.Start();

while (true)
{
try
{
HttpListenerContext ctx = await _listener.GetContextAsync();

HttpListenerRequest req = ctx.Request;

if (req.Url == null) continue;

var colorTemp = HttpUtility.ParseQueryString(req.Url.Query).Get("ct");
var brightness = HttpUtility.ParseQueryString(req.Url.Query).Get("bri");

if (colorTemp == null || brightness == null) continue;

await _hueApiService.UpdateScenes(int.Parse(colorTemp), Math.Clamp(float.Parse(brightness) * 100f, 0f, 100f));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
_listener.Stop();
break;
}
}
}
}
public class FluxApiService
{
private HueApiService _hueApiService;
private HttpListener _listener;
private string _url = "http://localhost:8000/";

public FluxApiService(HueApiService hueApiService)
{
_listener = new HttpListener();
_listener.Prefixes.Add(_url);
_hueApiService = hueApiService;
}

public void Start()
{
Task.Run(async () => { await HandleIncomingConnections(); });
}

private async Task HandleIncomingConnections()
{
_listener.Start();

while (true)
{
try
{
HttpListenerContext ctx = await _listener.GetContextAsync();

HttpListenerRequest req = ctx.Request;

if (req.Url == null) continue;

var colorTemp = HttpUtility.ParseQueryString(req.Url.Query).Get("ct");
var brightness = HttpUtility.ParseQueryString(req.Url.Query).Get("bri");

if (colorTemp == null || brightness == null) continue;

await _hueApiService.UpdateScenes(int.Parse(colorTemp), Math.Clamp(float.Parse(brightness) * 100f, 0f, 100f));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
_listener.Stop();
break;
}
}
}
}
Everything in the try block runs once, and then execution goes back to the top of the loop and starts awaiting the _listener.GetContextAsync() call again. But it never does anything else, and I know for a fact the traffic it receives at localhost:8000 happens periodically. So it picks up the first one it receives, and then it just stops doing anything. It never enters the catch block, so there isn't any exception thrown.
5 Replies
djmurp
djmurp2y ago
First thing to check would be to check at which point it is not executing e.g. is it definitely staying inside the while loop? is it never returning from _listener.GetContextAsync();? It might be easier to put a Console.WriteLine at the top of the while so you can be sure it's still executing. does it work if you make Start() return a Task and return HandleIncomingConnections() directly? or the same but making it async and "await HandleIncomingConnections()" you may be "await"ing the call to HandleIncomingConnections, but you aren't awaiting the task that is executing the await
marsastro
marsastroOP2y ago
I've done a lot of writelines and breakpoints, so I can say with 99.9% certainty that it stops when it reaches the await _listener.GetContextAsync() during the second iteration of the loop. So it definitely stays in the while loop. Not returning from getcontextasync seems to be the issue. I'll try the thing you suggested with Start in a little bit!
djmurp
djmurp2y ago
another thing to try: since it's working the first time it means that something may be "holding on", so you might need to respond (via methods in ctx.Response). Closing the response (ctx.Response.Close()) will allow the listener to listen for a new request. It's optional to send a response depending on if your consumer (other app) needs one, but you should at least call Close() on the response object if it still fails, send the code that is calling FluxApiService.Start()
marsastro
marsastroOP2y ago
I'm about to try now, but I think you might be spot on with the response part I had a different version that worked, and in that version I wrote a response I probably broke something when I chose to omit responding Yup, that did the trick! Thanks for the help!
Accord
Accord2y ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server