mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 12:45:47 +00:00
Test HttpListener so that PowerShell Core tests don't have to rely on an internet web service (#3778)
This commit is contained in:
1 parent
779d563d7d
commit
f0b03bc57d
2 files changed
+197
No files matched your search
@@ -0,0 +1,10 @@
|
||||
@{
|
||||
ModuleVersion = '1.0.0'
|
||||
GUID = 'e148b26c-0594-4963-99e5-419d4ff302e2'
|
||||
Author = 'Steve Lee'
|
||||
CompanyName = 'Microsoft'
|
||||
Copyright = '(c) Microsoft. All rights reserved.'
|
||||
Description = 'Creates a new HTTP Listener for testing purposes'
|
||||
RootModule = 'HttpListener.psm1'
|
||||
FunctionsToExport = @('Start-HttpListener','Stop-HttpListener')
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
Function Stop-HTTPListener {
|
||||
<#
|
||||
.Synopsis
|
||||
Stop HTTP Listener used for PowerShell tests rather than rely on 3rd party websites
|
||||
.Description
|
||||
Sends `exit` command to HTTP Listener causing it to exit.
|
||||
.Parameter Port
|
||||
Port to use, default is 8080
|
||||
.Example
|
||||
Stop-HTTPListener -Port 8080
|
||||
#>
|
||||
Param (
|
||||
[Parameter()]
|
||||
[Int] $Port = 8080
|
||||
)
|
||||
|
||||
Invoke-WebRequest -Uri "http://localhost:$port/PowerShell?test=exit"
|
||||
}
|
||||
|
||||
Function Start-HTTPListener {
|
||||
<#
|
||||
.Synopsis
|
||||
Creates a new HTTP Listener to be used for PowerShell tests rather than rely on 3rd party websites
|
||||
.Description
|
||||
Creates a new HTTP Listener supporting several test cases intended to be used only by PowerShell tests.
|
||||
|
||||
Use Ctrl-C to stop the listener. You'll need to send another web request to allow the listener to stop since
|
||||
it will be blocked waiting for a request.
|
||||
.Parameter Port
|
||||
Port to listen, default is 8080
|
||||
.Example
|
||||
Start-HTTPListener -Port 8080
|
||||
Invoke-WebRequest -Uri "http://localhost:8080/PowerShell/?test=linkheader&maxlinks=5"
|
||||
#>
|
||||
Param (
|
||||
[Parameter()]
|
||||
[Int] $Port = 8080,
|
||||
|
||||
[Parameter()]
|
||||
[switch] $AsJob
|
||||
)
|
||||
|
||||
Process {
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
[scriptblock]$script = {
|
||||
param ($Port)
|
||||
|
||||
# HttpListener.QueryString is not being populated, need to follow-up with CoreFx, workaround is to parse it ourselves
|
||||
Function ParseQueryString([string]$url)
|
||||
{
|
||||
Write-Verbose "Parsing: $url"
|
||||
$uri = [uri]$url
|
||||
$queryItems = @{}
|
||||
if ($uri.Query -ne $null)
|
||||
{
|
||||
foreach ($segment in $uri.Query.Split("&"))
|
||||
{
|
||||
if ($segment -match "\??(?<name>\w*)(=(?<value>.*?))?$")
|
||||
{
|
||||
$name = $matches["name"]
|
||||
$value = $matches["value"]
|
||||
if ($value -ne $null)
|
||||
{
|
||||
$value = [System.Web.HttpUtility]::UrlDecode($value)
|
||||
}
|
||||
$queryItems.Add($name, $value)
|
||||
Write-Verbose "Found: $name = $value"
|
||||
}
|
||||
}
|
||||
}
|
||||
return $queryItems
|
||||
}
|
||||
|
||||
$listener = [System.Net.HttpListener]::New()
|
||||
$urlPrefix = "/PowerShell"
|
||||
$url = "http://localhost:$Port$urlPrefix"
|
||||
$listener.Prefixes.Add($url + "/") # trailing slash required for registration
|
||||
$listener.AuthenticationSchemes = [System.Net.AuthenticationSchemes]::Anonymous
|
||||
try {
|
||||
Write-Warning "Note that thread is blocked waiting for a request. After using Ctrl-C to stop listening, you need to send a valid HTTP request to stop the listener cleanly."
|
||||
Write-Warning "Use Stop-HttpListener or Invoke-WebRequest -Uri '${Url}?test=exit' to stop the listener."
|
||||
Write-Verbose "Listening on $Url..."
|
||||
$listener.Start()
|
||||
$exit = $false
|
||||
while ($exit -eq $false) {
|
||||
$context = $listener.GetContext()
|
||||
$request = $context.Request
|
||||
|
||||
$queryItems = ParseQueryString($request.Url)
|
||||
|
||||
$test = $queryItems["test"]
|
||||
Write-Verbose "Testing: $test"
|
||||
|
||||
# the status code to return for the response
|
||||
$statusCode = [System.Net.HttpStatusCode]::OK
|
||||
# this is the body of the response, return json/xml as appropriate
|
||||
$output = ""
|
||||
# this is hashtable of headers in the response
|
||||
$outputHeader = @{}
|
||||
# this is the contenttype, example 'application/json'
|
||||
$contentType = $null
|
||||
|
||||
switch ($test)
|
||||
{
|
||||
$null
|
||||
{
|
||||
$statusCode = [System.Net.HttpStatusCode]::BadRequest
|
||||
$output = "Test not specified"
|
||||
}
|
||||
"exit"
|
||||
{
|
||||
Write-Verbose "Received command to exit listener"
|
||||
$output = "Exit command received"
|
||||
$exit = $true
|
||||
}
|
||||
"response"
|
||||
{
|
||||
$statusCode = $queryItems["statuscode"]
|
||||
$contentType = $queryItems["contenttype"]
|
||||
$output = $queryItems["output"]
|
||||
}
|
||||
"redirect"
|
||||
{
|
||||
$redirect = $queryItems["redirect"]
|
||||
if ($redirect -eq $null)
|
||||
{
|
||||
$statusCode = [System.Net.HttpStatusCode]::Found
|
||||
$redirectedUrl = "${Url}?test=redirect&redirect=false"
|
||||
Write-Verbose "$redirectedUrl"
|
||||
$outputHeader.Add("Location",$redirectedUrl)
|
||||
Write-Verbose "Redirecting to $($outputHeader.Location)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = $request | ConvertTo-Json
|
||||
}
|
||||
}
|
||||
default
|
||||
{
|
||||
$statusCode = [System.Net.HttpStatusCode]::NotFound
|
||||
$output = "Unknown Test: $Test"
|
||||
}
|
||||
}
|
||||
|
||||
$response = $context.Response
|
||||
if ($contentType -ne $null)
|
||||
{
|
||||
Write-Verbose "Setting ContentType to $contentType"
|
||||
$response.ContentType = $contentType
|
||||
}
|
||||
if ($statusCode -ne $null)
|
||||
{
|
||||
$response.StatusCode = $statusCode
|
||||
}
|
||||
$response.Headers.Clear()
|
||||
foreach ($header in $outputHeader.Keys)
|
||||
{
|
||||
$response.Headers.Add($header, $outputHeader[$header])
|
||||
}
|
||||
if ($output -ne $null)
|
||||
{
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($output)
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$output = $response.OutputStream
|
||||
$output.Write($buffer,0,$buffer.Length)
|
||||
$output.Close()
|
||||
}
|
||||
$response.Close()
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
$listener.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
if ($AsJob)
|
||||
{
|
||||
Start-Job -ScriptBlock $script -ArgumentList $Port
|
||||
}
|
||||
else
|
||||
{
|
||||
& $script -Port $Port
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user