Public/Resolve-Request.ps1
function Resolve-Request { <# .SYNOPSIS Handles an incoming request .DESCRIPTION Do not call this function directly. This function has to be part of the public API as it is called from outside of the module scope by the thread that listens for incoming requests. .PARAMETER TcpClient A connected TcpClent object representing the client making the request. .PARAMETER CancellationTokenSource The token source object to use for initiating a server shutdown #> param ( [System.Net.Sockets.TcpClient]$TcpClient, [System.Threading.CancellationTokenSource]$CancellationTokenSource ) $httpLogEntry = $null $errorLogEntry = $null try { # Record start time of request processing $startTime = [datetime]::UtcNow # Get the client's data stream $stream = $TcpClient.GetStream() # Create a request object fromn the stream $request = [HttpRequest]::new($stream) try { # Read the request stream, i.e. get request and headers $request.Read() # Process request and get response $response = Invoke-Route -Context $request } catch [HttpException] { # Under normal circumstances, an [HttpResponse] will always be returned, # unless there was an error forming the response, in which case an [HttpException] will be thrown. # Any other exception is fatal and handled further down. $response = [HttpResponse]::new($_.Exception, $request) } # Send response to client $responseBytes = $response.GetBytes() $stream.Write($responseBytes, 0, $responseBytes.Length) # Record overall processing time, $timeTaken = [int]([datetime]::UtcNow - $startTime).TotalMilliseconds # Create an entry for the HTTP log $httpLogEntry = [HttpLogEntry]::new($request, $response, $startTime, $timeTaken, $TcpClient.Client) # Create an entry for the error log if there was an error $errorLogEntry = $( if ($response.Status.StatusCode -ge 400) { [ErrorLogEntry]::new($request, $response, $startTime, $timeTaken, $TcpClient.Client) } else { $null } ) } catch { # This is a fatal error! Write-OperatingSystemLogEntry -EventId ([EventId]::Fatal) -Message "Resolve-Route`n$($_.Exception.Message)`n`n$($_.Exception.GetType().FullName)`n$($_.ScriptStackTrace)" Stop-Server -CancellationTokenSource $CancellationTokenSource throw } finally { # Close client connection. $TcpClient.Dispose() } # Update log files if ($null -ne $SharedVariables.LoggingQueue) { $httpLogString = $httpLogEntry.ToString() $errorLogString = $( if ($null -ne $errorLogEntry) { $errorLogEntry.ToString() } else { $null } ) # Add to logging output queue for processing by logging thread. $SharedVariables.LoggingQueue.Add([System.Collections.Generic.KeyValuePair[string, string]]::new($httpLogString, $errorLogString)) } if ($response -is [TerminationResponse]) { # User request to terminate server. Stop-Server -CancellationTokenSource $CancellationTokenSource } } |