diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8b5a7ffba21..37e83f1ed51 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -109,7 +109,7 @@ Additional references: **Always create a pull request to the `master` branch of this repository**. -![Github-PR-dev.png](Images/Github-PR-dev.png) +![GitHub-PR.png](Images/GitHub-PR.png) * It's recommended to avoid a PR with too many changes. A large PR not only stretches the review time, but also makes it much harder to spot issues. diff --git a/.github/Images/Github-PR-dev.png b/.github/Images/GitHub-PR.png similarity index 100% rename from .github/Images/Github-PR-dev.png rename to .github/Images/GitHub-PR.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 58180fe088c..959bb6521ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v6.0.0-rc.2 - 2017-11-14 +## v6.0.0-rc.2 - 2017-12-14 ### Breaking changes diff --git a/docker/tests/Templates/centos7/Dockerfile b/docker/tests/Templates/centos7/Dockerfile index 89816a47828..fc755dde23b 100644 --- a/docker/tests/Templates/centos7/Dockerfile +++ b/docker/tests/Templates/centos7/Dockerfile @@ -19,4 +19,4 @@ RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG RUN curl -L -o powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm $PACKAGELOCATIONSTUB/powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN yum install -y powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/debian.8/Dockerfile b/docker/tests/Templates/debian.8/Dockerfile index f6224837884..31a599715ce 100644 --- a/docker/tests/Templates/debian.8/Dockerfile +++ b/docker/tests/Templates/debian.8/Dockerfile @@ -24,4 +24,4 @@ RUN curl -L -o powershell_$PSVERSIONSTUB-1.debian.8_amd64.deb $PACKAGELOCATIONST RUN dpkg -i powershell_$PSVERSIONSTUB-1.debian.8_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/debian.9/Dockerfile b/docker/tests/Templates/debian.9/Dockerfile index 80e21cd407b..b64d6891aab 100644 --- a/docker/tests/Templates/debian.9/Dockerfile +++ b/docker/tests/Templates/debian.9/Dockerfile @@ -24,4 +24,4 @@ RUN curl -L -o powershell_$PSVERSIONSTUB-1.debian.9_amd64.deb $PACKAGELOCATIONST RUN dpkg -i powershell_$PSVERSIONSTUB-1.debian.9_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/fedora25/Dockerfile b/docker/tests/Templates/fedora25/Dockerfile index 828c3660078..c82d129f893 100644 --- a/docker/tests/Templates/fedora25/Dockerfile +++ b/docker/tests/Templates/fedora25/Dockerfile @@ -19,4 +19,4 @@ RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG RUN curl -L -o powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm $PACKAGELOCATIONSTUB/powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN dnf install -y powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/fedora26/Dockerfile b/docker/tests/Templates/fedora26/Dockerfile index b4207d7c22a..d786307b316 100644 --- a/docker/tests/Templates/fedora26/Dockerfile +++ b/docker/tests/Templates/fedora26/Dockerfile @@ -20,4 +20,4 @@ RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG RUN curl -L -o powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm $PACKAGELOCATIONSTUB/powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN dnf install -y powershell-$PSVERSIONSTUBRPM-1.rhel.7.x86_64.rpm RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/kalilinux/Dockerfile b/docker/tests/Templates/kalilinux/Dockerfile index 6d02c38a465..f97424c0c6a 100644 --- a/docker/tests/Templates/kalilinux/Dockerfile +++ b/docker/tests/Templates/kalilinux/Dockerfile @@ -26,4 +26,4 @@ RUN dpkg -i libssl1.0.0_1.0.1t-1+deb8u7_amd64.deb || : RUN dpkg -i powershell_$PSVERSIONSTUB-1.ubuntu.16.04_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/opensuse42.2/Dockerfile b/docker/tests/Templates/opensuse42.2/Dockerfile index 5ac50b1a01d..d44cbb32ff5 100644 --- a/docker/tests/Templates/opensuse42.2/Dockerfile +++ b/docker/tests/Templates/opensuse42.2/Dockerfile @@ -35,4 +35,4 @@ RUN tar zxf powershell-$PSVERSIONSTUB-linux-x64.tar.gz -C /opt/microsoft/powersh RUN ln -s /opt/microsoft/powershell/$PSVERSIONSTUB/pwsh $POWERSHELL_LINKFILE RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/ubuntu14.04/Dockerfile b/docker/tests/Templates/ubuntu14.04/Dockerfile index 1533bc2395d..181610b6c28 100644 --- a/docker/tests/Templates/ubuntu14.04/Dockerfile +++ b/docker/tests/Templates/ubuntu14.04/Dockerfile @@ -24,4 +24,4 @@ RUN curl -L -o powershell_$PSVERSIONSTUB-1.ubuntu.14.04_amd64.deb $PACKAGELOCATI RUN dpkg -i powershell_$PSVERSIONSTUB-1.ubuntu.14.04_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/ubuntu16.04/Dockerfile b/docker/tests/Templates/ubuntu16.04/Dockerfile index db84a97f535..211e6d974e5 100644 --- a/docker/tests/Templates/ubuntu16.04/Dockerfile +++ b/docker/tests/Templates/ubuntu16.04/Dockerfile @@ -24,4 +24,4 @@ RUN curl -L -o powershell_$PSVERSIONSTUB-1.ubuntu.16.04_amd64.deb $PACKAGELOCATI RUN dpkg -i powershell_$PSVERSIONSTUB-1.ubuntu.16.04_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/Templates/ubuntu17.04/Dockerfile b/docker/tests/Templates/ubuntu17.04/Dockerfile index 506cb8b5112..dae4b3fe0c0 100644 --- a/docker/tests/Templates/ubuntu17.04/Dockerfile +++ b/docker/tests/Templates/ubuntu17.04/Dockerfile @@ -24,4 +24,4 @@ RUN curl -L -o powershell_$PSVERSIONSTUB-1.ubuntu.17.04_amd64.deb $PACKAGELOCATI RUN dpkg -i powershell_$PSVERSIONSTUB-1.ubuntu.17.04_amd64.deb || : RUN apt-get install -y -f RUN git clone --recursive https://github.com/PowerShell/PowerShell.git -RUN pwsh -c "Import-Module /PowerShell/build.psm1;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" +RUN pwsh -c "Import-Module /PowerShell/build.psm1;Restore-PSPester -Destination /usr/local/share/powershell/Modules;exit (Invoke-Pester $TESTLISTSTUB -PassThru).FailedCount" diff --git a/docker/tests/containerTestCommon.psm1 b/docker/tests/containerTestCommon.psm1 index 50d011fbdb7..37b3489172f 100644 --- a/docker/tests/containerTestCommon.psm1 +++ b/docker/tests/containerTestCommon.psm1 @@ -243,6 +243,7 @@ function Test-PSPackage $buildArgs += "--build-arg","$versionStubName=$versionStubValue" $buildArgs += "--build-arg","$testlistStubName=$testlistStubValue" $buildArgs += "--build-arg","$packageLocationStubName=$packageLocationStubValue" + $buildArgs += "--no-cache" $buildArgs += $dir.FullName $dockerResult = Invoke-Docker -Command 'build' -Params $buildArgs -FailureAction warning diff --git a/docs/installation/windows.md b/docs/installation/windows.md index c26bcd32bdd..3d1dc891f02 100644 --- a/docs/installation/windows.md +++ b/docs/installation/windows.md @@ -30,6 +30,48 @@ Be noted that when using the ZIP archive, you won't get the prerequisites check So in order for remoting over WinRM to work properly on Windows versions prior to Windows 10, you need to make sure the [prerequisites](#prerequisites) are met. +## Deploying on Windows IoT + +Windows IoT already comes with Windows PowerShell which we will use to deploy PowerShell Core 6. + +* Create `PSSession` to target device + +```powershell +$s = New-PSSession -ComputerName -Credential Administrator +``` + +* Copy the zip package to the device + +```powershell +# change the destination to however you had partitioned it with sufficient space for the zip and the unzipped contents +# the path should be local to the device +Copy-Item .\PowerShell-6.0.0-rc.2-win-arm32.zip -Destination u:\users\administrator\Downloads -ToSession $s +``` + +* Connect to the device and expand the archive + +```powershell +Enter-PSSession $s +cd u:\users\administrator\downloads +Expand-Archive .\PowerShell-6.0.0-rc.2-win-arm32.zip +``` + +* Setup remoting to PowerShell Core 6 + +```powershell +cd .\PowerShell-6.0.0-rc.2-win-arm32 +# Be sure to use the -PowerShellHome parameter otherwise it'll try to create a new endpoint with Windows PowerShell 5.1 +.\Install-PowerShellRemoting.ps1 -PowerShellHome . +# You'll get an error message and will be disconnected from the device because it has to restart WinRM +``` + +* Connect to PowerShell Core 6 endpoint on device + +```powershell +# Be sure to use the -Configuration parameter. If you omit it, you will connect to Windows PowerShell 5.1 +Enter-PSSession -ComputerName -Credential Administrator -Configuration powershell.6.0.0-rc.2 +``` + ## Deploying on Nano Server These instructions assume that Windows PowerShell is running on the Nano Server image and that it has been generated by the [Nano Server Image Builder](https://technet.microsoft.com/windows-server-docs/get-started/deploy-nano-server). diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index bf77837d4fe..98e86925975 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -3,7 +3,7 @@ # # This is a Pester test suite which validate the Web cmdlets. # -# Note: These tests use data from http://httpbin.org/ +# Note: These tests use data from WebListener # # Invokes the given command via script block invocation. @@ -642,7 +642,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { # patch Returns PATCH data. # put Returns PUT data. # delete Returns DELETE data - $testMethods = @("GET", "POST", "PATCH", "PUT", "DELETE") + $testMethods = @("POST", "PATCH", "PUT", "DELETE") $contentTypes = @("text/plain", "application/xml", "application/json") foreach ($contentType in $contentTypes) @@ -650,20 +650,11 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { foreach ($method in $testMethods) { # Operation options - $operation = $method.ToLower() - $uri = "http://httpbin.org/$operation" + $uri = Get-WebListenerUrl -Test $method $body = GetTestData -contentType $contentType + $command = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method -ContentType $contentType" - if ($method -eq "GET") - { - $command = "Invoke-WebRequest -Uri $uri" - } - else - { - $command = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method -ContentType $contentType -TimeoutSec 5" - } - - It "$command" { + It "Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Body [body data]" { $result = ExecuteWebCommand -command $command ValidateResponse -response $result @@ -671,22 +662,9 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { # Validate response content $jsonContent = $result.Output.Content | ConvertFrom-Json $jsonContent.url | Should Match $uri - - # For a GET request, there is no data property to validate. - if ($method -ne "GET") - { - $jsonContent.headers.'Content-Type' | Should Match $contentType - - # Validate that the response Content.data field is the same as what we sent. - if ($contentType -eq "application/xml") - { - $jsonContent.data | Should Be $body - } - else - { - $jsonContent.data | Should Match $body - } - } + $jsonContent.headers.'Content-Type' | Should Match $contentType + # Validate that the response Content.data field is the same as what we sent. + $jsonContent.data | Should Be $body } } } @@ -760,9 +738,12 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { It "Validate Invoke-WebRequest default ContentType for CustomMethod POST" { - $command = "Invoke-WebRequest -Uri 'http://httpbin.org/post' -CustomMethod POST -Body 'testparam=testvalue'" + $uri = Get-WebListenerUrl -Test 'Post' + $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod POST -Body 'testparam=testvalue'" $result = ExecuteWebCommand -command $command - ($result.Output.Content | ConvertFrom-Json).form.testparam | Should Be "testvalue" + $jsonResult = $result.Output.Content | ConvertFrom-Json + $jsonResult.form.testparam | Should Be "testvalue" + $jsonResult.Headers.'Content-Type' | Should Be "application/x-www-form-urlencoded" } It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET" { @@ -775,14 +756,20 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { It "Validate Invoke-WebRequest returns HTTP errors in exception" { - $command = "Invoke-WebRequest -Uri http://httpbin.org/status/418" + $query = @{ + body = "I am a teapot!!!" + statuscode = 418 + responsephrase = "I am a teapot" + } + $uri = Get-WebListenerUrl -Test 'Response' -Query $query + $command = "Invoke-WebRequest -Uri '$uri'" $result = ExecuteWebCommand -command $command - $result.Error.ErrorDetails.Message | Should Match "\-=\[ teapot \]" - $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.ErrorDetails.Message | Should Be $query.body + $result.Error.Exception | Should BeOfType 'Microsoft.PowerShell.Commands.HttpResponseException' $result.Error.Exception.Response.StatusCode | Should Be 418 - $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." + $result.Error.Exception.Response.ReasonPhrase | Should Be $query.responsephrase + $result.Error.Exception.Message | Should Match ": 418 \($($query.responsephrase)\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } @@ -1622,7 +1609,9 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { It "Validate Invoke-RestMethod error with -Proxy option - ''" -TestCases $testCase { param($proxy_address, $name, $protocol) - $command = "Invoke-RestMethod -Uri '${protocol}://httpbin.org/' -Proxy '${proxy_address}'" + # A non-loopback URI is required but the external resource will not be accessed + $uri = 'http://httpbin.org' + $command = "Invoke-RestMethod -Uri '$uri' -Proxy '${proxy_address}'" $result = ExecuteWebCommand -command $command $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" @@ -1679,7 +1668,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { # patch Returns PATCH data. # put Returns PUT data. # delete Returns DELETE data - $testMethods = @("GET", "POST", "PATCH", "PUT", "DELETE") + $testMethods = @("POST", "PATCH", "PUT", "DELETE") $contentTypes = @("text/plain", "application/xml", "application/json") foreach ($contentType in $contentTypes) @@ -1687,41 +1676,20 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { foreach ($method in $testMethods) { # Operation options - $operation = $method.ToLower() - $uri = "http://httpbin.org/$operation" + $uri = Get-WebListenerUrl -Test $method $body = GetTestData -contentType $contentType + $command = "Invoke-RestMethod -Uri $uri -Body '$body' -Method $method -ContentType $contentType" - if ($method -eq "GET") - { - $command = "Invoke-RestMethod -Uri $uri" - } - else - { - $command = "Invoke-RestMethod -Uri $uri -Body '$body' -Method $method -ContentType $contentType -TimeoutSec 5" - } - - It "$command" { + It "Invoke-RestMethod -Uri $uri -Method $method -ContentType $contentType -Body [body data]" { $result = ExecuteWebCommand -command $command # Validate response $result.Output.url | Should Match $uri + $result.Output.headers.'Content-Type' | Should Match $contentType - # For a GET request, there is no data property to validate. - if ($method -ne "GET") - { - $result.Output.headers.'Content-Type' | Should Match $contentType - - # Validate that the response Content.data field is the same as what we sent. - if ($contentType -eq "application/xml") - { - $result.Output.data | Should Be $body - } - else - { - $result.Output.data | Should Match $body - } - } + # Validate that the response Content.data field is the same as what we sent. + $result.Output.data | Should Be $body } } } @@ -1794,9 +1762,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { It "Validate Invoke-RestMethod default ContentType for CustomMethod POST" { - $command = "Invoke-RestMethod -Uri 'http://httpbin.org/post' -CustomMethod POST -Body 'testparam=testvalue'" + $uri = Get-WebListenerUrl -Test 'Post' + $command = "Invoke-RestMethod -Uri '$uri' -CustomMethod POST -Body 'testparam=testvalue'" $result = ExecuteWebCommand -command $command $result.Output.form.testparam | Should Be "testvalue" + $result.Output.Headers.'Content-Type' | Should Be "application/x-www-form-urlencoded" } It "Validate Invoke-RestMethod body is converted to query params for CustomMethod GET" { @@ -1809,14 +1779,20 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { It "Validate Invoke-RestMethod returns HTTP errors in exception" { - $command = "Invoke-RestMethod -Uri http://httpbin.org/status/418" + $query = @{ + body = "I am a teapot!!!" + statuscode = 418 + responsephrase = "I am a teapot" + } + $uri = Get-WebListenerUrl -Test 'Response' -Query $query + $command = "Invoke-RestMethod -Uri '$uri'" $result = ExecuteWebCommand -command $command - $result.Error.ErrorDetails.Message | Should Match "\-=\[ teapot \]" - $result.Error.Exception | Should BeOfType Microsoft.PowerShell.Commands.HttpResponseException + $result.Error.ErrorDetails.Message | Should Be $query.body + $result.Error.Exception | Should BeOfType 'Microsoft.PowerShell.Commands.HttpResponseException' $result.Error.Exception.Response.StatusCode | Should Be 418 - $result.Error.Exception.Response.ReasonPhrase | Should Be "I'm a teapot" - $result.Error.Exception.Message | Should Match ": 418 \(I'm a teapot\)\." + $result.Error.Exception.Response.ReasonPhrase | Should Be $query.responsephrase + $result.Error.Exception.Message | Should Match ": 418 \($($query.responsephrase)\)\." $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" } @@ -2489,48 +2465,50 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" { Context "InFile parameter negative tests" { - - $testCases = @( + BeforeAll { + $uri = Get-WebListenerUrl -Test 'Post' + $testCases = @( #region INVOKE-WEBREQUEST - @{ - Name = 'Validate error for Invoke-WebRequest -InFile ""' - ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile ""} - ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' - } + @{ + Name = 'Validate error for Invoke-WebRequest -InFile ""' + ScriptBlock = {Invoke-WebRequest -Uri $uri -Method Post -InFile ""} + ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' + } - @{ - Name = 'Validate error for Invoke-WebRequest -InFile' - ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile} - ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' - } + @{ + Name = 'Validate error for Invoke-WebRequest -InFile' + ScriptBlock = {Invoke-WebRequest -Uri $uri -Method Post -InFile} + ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' + } - @{ - Name = "Validate error for Invoke-WebRequest -InFile $TestDrive\content.txt" - ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile $TestDrive\content.txt} - ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' - } + @{ + Name = "Validate error for Invoke-WebRequest -InFile $TestDrive\content.txt" + ScriptBlock = {Invoke-WebRequest -Uri $uri -Method Post -InFile $TestDrive\content.txt} + ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand' + } #endregion #region INVOKE-RESTMETHOD - @{ - Name = "Validate error for Invoke-RestMethod -InFile ''" - ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile ''} - ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' - } + @{ + Name = "Validate error for Invoke-RestMethod -InFile ''" + ScriptBlock = {Invoke-RestMethod -Uri $uri -Method Post -InFile ''} + ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' + } - @{ - Name = "Validate error for Invoke-RestMethod -InFile " - ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile} - ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' - } + @{ + Name = "Validate error for Invoke-RestMethod -InFile " + ScriptBlock = {Invoke-RestMethod -Uri $uri -Method Post -InFile} + ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' + } - @{ - Name = "Validate error for Invoke-RestMethod -InFile $TestDrive\content.txt" - ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile $TestDrive\content.txt} - ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' - } + @{ + Name = "Validate error for Invoke-RestMethod -InFile $TestDrive\content.txt" + ScriptBlock = {Invoke-RestMethod -Uri $uri -Method Post -InFile $TestDrive\content.txt} + ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeRestMethodCommand' + } #endregion - ) + ) + } It "" -TestCases $testCases { param ($scriptblock, $expectedFullyQualifiedErrorId) @@ -2551,18 +2529,21 @@ Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Featu BeforeAll { $filePath = Join-Path $TestDrive test.txt - New-Item -Path $filePath -Value "hello" -ItemType File -Force + New-Item -Path $filePath -Value "hello=world" -ItemType File -Force + $uri = Get-WebListenerUrl -Test 'Post' } It "Invoke-WebRequest -InFile" { - $result = Invoke-WebRequest -InFile $filePath -Uri http://httpbin.org/post -Method Post + $result = Invoke-WebRequest -InFile $filePath -Uri $uri -Method Post $content = $result.Content | ConvertFrom-Json - $content.form | Should Match "hello" + $content.form.hello.Count | Should Be 1 + $content.form.hello[0] | Should Match "world" } It "Invoke-RestMethod -InFile" { - $result = Invoke-RestMethod -InFile $filePath -Uri http://httpbin.org/post -Method Post - $result.form | Should Match "hello" + $result = Invoke-RestMethod -InFile $filePath -Uri $uri -Method Post + $result.form.hello.Count | Should Be 1 + $result.form.hello[0] | Should Match "world" } } } diff --git a/test/tools/Modules/WebListener/WebListener.psm1 b/test/tools/Modules/WebListener/WebListener.psm1 index 981f09f2bbd..b34ac9256e3 100644 --- a/test/tools/Modules/WebListener/WebListener.psm1 +++ b/test/tools/Modules/WebListener/WebListener.psm1 @@ -1,4 +1,4 @@ -Class WebListener +Class WebListener { [int]$HttpPort [int]$HttpsPort @@ -8,7 +8,7 @@ Class WebListener WebListener () { } - [String] GetStatus() + [String] GetStatus() { return $This.Job.JobStateInfo.State } @@ -16,23 +16,23 @@ Class WebListener [WebListener]$WebListener -function Get-WebListener +function Get-WebListener { [CmdletBinding(ConfirmImpact = 'Low')] [OutputType([WebListener])] param() - process + process { return [WebListener]$Script:WebListener } } -function Start-WebListener +function Start-WebListener { [CmdletBinding(ConfirmImpact = 'Low')] [OutputType([WebListener])] - param + param ( [ValidateRange(1,65535)] [int]$HttpPort = 8083, @@ -46,8 +46,8 @@ function Start-WebListener [ValidateRange(1,65535)] [int]$TlsPort = 8086 ) - - process + + process { $runningListener = Get-WebListener if ($null -ne $runningListener -and $runningListener.GetStatus() -eq 'Running') @@ -60,7 +60,7 @@ function Start-WebListener $serverPfx = 'ServerCert.pfx' $serverPfxPassword = 'password' $initCompleteMessage = 'Now listening on' - + $serverPfxPath = Join-Path $MyInvocation.MyCommand.Module.ModuleBase $serverPfx $timeOut = (get-date).AddSeconds($initTimeoutSeconds) $Job = Start-Job { @@ -69,7 +69,7 @@ function Start-WebListener dotnet $using:appDll $using:serverPfxPath $using:serverPfxPassword $using:HttpPort $using:HttpsPort $using:Tls11Port $using:TlsPort } $Script:WebListener = [WebListener]@{ - HttpPort = $HttpPort + HttpPort = $HttpPort HttpsPort = $HttpsPort Tls11Port = $Tls11Port TlsPort = $TlsPort @@ -83,8 +83,8 @@ function Start-WebListener $isRunning = $initStatus -match $initCompleteMessage } while (-not $isRunning -and (get-date) -lt $timeOut) - - if (-not $isRunning) + + if (-not $isRunning) { $Job | Stop-Job -PassThru | Receive-Job $Job | Remove-Job @@ -94,13 +94,13 @@ function Start-WebListener } } -function Stop-WebListener +function Stop-WebListener { [CmdletBinding(ConfirmImpact = 'Low')] [OutputType([Void])] param() - - process + + process { $Script:WebListener.job | Stop-Job -PassThru | Remove-Job $Script:WebListener = $null @@ -131,10 +131,14 @@ function Get-WebListenerUrl { 'Cert', 'Compression', 'Delay', + 'Delete', 'Encoding', 'Get', 'Home', 'Multipart', + 'Patch', + 'Post', + 'Put', 'Redirect', 'Response', 'ResponseHeaders', @@ -173,7 +177,7 @@ function Get-WebListenerUrl { { $Uri.Path = '{0}/{1}' -f $Test, $TestValue } - else + else { $Uri.Path = $Test } diff --git a/test/tools/WebListener/Controllers/GetController.cs b/test/tools/WebListener/Controllers/GetController.cs index ccd082ef13f..59df91e0f68 100644 --- a/test/tools/WebListener/Controllers/GetController.cs +++ b/test/tools/WebListener/Controllers/GetController.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -29,8 +30,26 @@ public JsonResult Index() {"args" , args}, {"headers", headers}, {"origin" , Request.HttpContext.Connection.RemoteIpAddress.ToString()}, - {"url" , UriHelper.GetDisplayUrl(Request)} + {"url" , UriHelper.GetDisplayUrl(Request)}, + {"method" , Request.Method} }; + + if (Request.HasFormContentType) + { + Hashtable form = new Hashtable(); + foreach (var key in Request.Form.Keys) + { + form.Add(key,Request.Form[key]); + } + output["form"] = form; + } + + string data = new StreamReader(Request.Body).ReadToEnd(); + if (!String.IsNullOrEmpty(data)) + { + output["data"] = data; + } + return Json(output); } public IActionResult Error() diff --git a/test/tools/WebListener/Controllers/ResponseController.cs b/test/tools/WebListener/Controllers/ResponseController.cs index c2688cf0556..cfef8d1aaf2 100644 --- a/test/tools/WebListener/Controllers/ResponseController.cs +++ b/test/tools/WebListener/Controllers/ResponseController.cs @@ -12,6 +12,7 @@ using mvc.Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Microsoft.AspNetCore.Http.Features; namespace mvc.Controllers { @@ -36,6 +37,12 @@ public String Index() Response.StatusCode = statusCode; } + StringValues responsePhrase; + if ( Request.Query.TryGetValue("responsephrase", out responsePhrase)) + { + Response.HttpContext.Features.Get().ReasonPhrase = responsePhrase.FirstOrDefault(); + } + StringValues body; if (Request.Query.TryGetValue("body", out body)) { diff --git a/test/tools/WebListener/README.md b/test/tools/WebListener/README.md index efa200a3e61..4be07b52287 100644 --- a/test/tools/WebListener/README.md +++ b/test/tools/WebListener/README.md @@ -2,9 +2,9 @@ ASP.NET Core 2.0 app for testing HTTP and HTTPS Requests. -# Run with `dotnet` +## Run with `dotnet` -``` +```bash dotnet restore dotnet publish --output bin --configuration Release cd bin @@ -13,7 +13,7 @@ dotnet WebListener.dll ServerCert.pfx password 8083 8084 8085 8086 The test site can then be accessed via `http://localhost:8083/`, `https://localhost:8084/`, `https://localhost:8085/`, or `https://localhost:8086/`. -The `WebListener.dll` takes 6 arguments: +The `WebListener.dll` takes 6 arguments: * The path to the Server Certificate * The Server Certificate Password @@ -22,7 +22,7 @@ The `WebListener.dll` takes 6 arguments: * The TCP Port to bind on for HTTPS using TLS 1.1 * The TCP Port to bind on for HTTPS using TLS 1.0 -# Run With WebListener Module +## Run With WebListener Module ```powershell Import-Module .\build.psm1 @@ -30,13 +30,13 @@ Publish-PSTestTools $Listener = Start-WebListener -HttpPort 8083 -HttpsPort 8084 -Tls11Port 8085 -TlsPort = 8086 ``` -# Tests +## Tests -## / or /Home/ +### / or /Home/ Returns a static HTML page containing links and descriptions of the available tests in WebListener. This can be used as a default or general test where no specific test functionality or return data is required. -## /Auth/Basic/ +### /Auth/Basic/ Provides a mock Basic authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned. @@ -51,7 +51,7 @@ Invoke-RestMethod -Uri $uri -Credential $credential -SkipCertificateCheck "headers":{ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", "Connection": "Keep-Alive", - "Authorization": "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk", + "Authorization": "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk", "Host": "localhost:8084" }, "origin": "127.0.0.1", @@ -60,7 +60,7 @@ Invoke-RestMethod -Uri $uri -Credential $credential -SkipCertificateCheck } ``` -## /Auth/Negotiate/ +### /Auth/Negotiate/ Provides a mock Negotiate authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned. @@ -74,7 +74,7 @@ Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck "headers":{ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", "Connection": "Keep-Alive", - "Authorization": "Negotiate jjaguasgtisi7tiqkagasjjajvs", + "Authorization": "Negotiate jjaguasgtisi7tiqkagasjjajvs", "Host": "localhost:8084" }, "origin": "127.0.0.1", @@ -83,7 +83,7 @@ Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck } ``` -## /Auth/NTLM/ +### /Auth/NTLM/ Provides a mock NTLM authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned. @@ -97,7 +97,7 @@ Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck "headers":{ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", "Connection": "Keep-Alive", - "Authorization": "NTLM jjaguasgtisi7tiqkagasjjajvs", + "Authorization": "NTLM jjaguasgtisi7tiqkagasjjajvs", "Host": "localhost:8084" }, "origin": "127.0.0.1", @@ -106,17 +106,18 @@ Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck } ``` -## /Cert/ +### /Cert/ Returns a JSON object containing the details of the Client Certificate if one is provided in the request. ```powershell $certificate = Get-WebListenerClientCertificate -$uri = Get-WebListenerUrl -Test 'Cert' -Https +$uri = Get-WebListenerUrl -Test 'Cert' -Https Invoke-RestMethod -Uri $uri -Certificate $certificate ``` Response when certificate is provided in request: + ```json { "Status": "OK", @@ -131,13 +132,15 @@ Response when certificate is provided in request: ``` Response when certificate is not provided in request: + ```json { "Status": "FAILED" } ``` -## /Compression/Deflate/ +### /Compression/Deflate/ + Returns the same results as the Get test with deflate compression. ```powershell @@ -157,7 +160,8 @@ Invoke-RestMethod -Uri $uri } ``` -## /Compression/Gzip/ +### /Compression/Gzip/ + Returns the same results as the Get test with gzip compression. ```powershell @@ -177,7 +181,7 @@ Invoke-RestMethod -Uri $uri } ``` -## /Delay/ +### /Delay/ Returns the same results as the Get test. If a number is supplied, the server will wait that many seconds before returning a response. This can be used to test timeouts. @@ -191,7 +195,6 @@ After 5 Seconds: ```json { "args": { - }, "origin": "127.0.0.1", "headers": { @@ -202,7 +205,33 @@ After 5 Seconds: } ``` -## /Encoding/Utf8/ +### /Delete/ + +Returns the same results as the Get test. Will only accept the `DELETE` request method. + +```powershell +$uri = Get-WebListenerUrl -Test 'Delete' +$Body = @{id = 12345} | ConvertTo-Json -Compress +Invoke-RestMethod -Uri $uri -Body $body -Method 'Delete' +``` + +```json +{ + "method": "DELETE", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", + "Connection": "Keep-Alive", + "Host": "localhost:8083", + "Content-Length": "12" + }, + "origin": "127.0.0.1", + "url": "http://localhost:8083/Delete", + "args": {}, + "data": "{\"id\":12345}" +} +``` + +### /Encoding/Utf8/ Returns page containing UTF-8 data. @@ -211,8 +240,7 @@ $uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'Utf8' Invoke-RestMethod -Uri $uri ``` - -## /Get/ +### /Get/ Returns a JSON object containing the Request URL, Request Headers, GET Query Fields and Values, and Origin IP. This emulates the functionality of [HttpBin's get test](https://httpbin.org/get). @@ -223,25 +251,28 @@ Invoke-RestMethod -Uri $uri -Body @{TestField = 'TestValue'} ```json { - "url": "http://localhost:8083/Get/?TestField=TestValue", + "origin": "127.0.0.1", + "url": "http://localhost:8083/Get?TestField=TestValue", + "method": "GET", "args": { "TestField": "TestValue" }, "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", "Connection": "Keep-Alive", - "User-Agent": "Mozilla/5.0 (Windows NT; Microsoft Windows 10.0.15063 ; en-US) WindowsPowerShell/6.0.0", "Host": "localhost:8083" - }, - "origin": "127.0.0.1" + } } ``` -## /Multipart/ +### /Multipart/ + +#### GET -### GET Provides an HTML form for `multipart/form-data` submission. -### POST +#### POST + Accepts a `multipart/form-data` submission and returns a JSON object containing information about the submission including the items and files submitted. ```powershell @@ -285,7 +316,115 @@ Invoke-RestMethod -Uri $uri -Body $multipartData -Method 'POST' } ``` -## /Redirect/ +### /Patch/ + +Returns the same results as the Get test. Will only accept the `PATCH` request method. + +```powershell +$uri = Get-WebListenerUrl -Test 'Patch' +$Body = @{id = 12345} | ConvertTo-Json -Compress +Invoke-RestMethod -Uri $uri -Body $body -Method 'Patch' +``` + +```json +{ + "method": "PATCH", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", + "Connection": "Keep-Alive", + "Host": "localhost:8083", + "Content-Length": "12" + }, + "origin": "127.0.0.1", + "url": "http://localhost:8083/Patch", + "args": {}, + "data": "{\"id\":12345}" +} +``` + +### /Post/ + +Returns the same results as the Get test. Will only accept the `POST` request method. If the POST request is sent with a forms based content type the body will be interpreted as a form instead of raw data. + +```powershell +$uri = Get-WebListenerUrl -Test 'Post' +$Body = @{id = 12345} +Invoke-RestMethod -Uri $uri -Body $body -Method 'Post' +``` + +```json +{ + "method": "POST", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", + "Connection": "Keep-Alive", + "Host": "localhost:8083", + "Content-Type": "application/x-www-form-urlencoded", + "Content-Length": "8" + }, + "form": { + "id": [ + "12345" + ] + }, + "origin": "127.0.0.1", + "url": "http://localhost:8083/Post", + "args": {} +} +``` + +Otherwise, the body will be interpreted as raw data. + +```powershell +$uri = Get-WebListenerUrl -Test 'Post' +$Body = @{id = 12345} | ConvertTo-Json -Compress +Invoke-RestMethod -Uri $uri -Body $body -Method 'Post' -ContentType 'application/json' +``` + +```json +{ + "method": "POST", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", + "Connection": "Keep-Alive", + "Host": "localhost:8083", + "Content-Type": "application/json", + "Content-Length": "12" + }, + "origin": "127.0.0.1", + "url": "http://localhost:8083/Post", + "args": {}, + "data": "{\"id\":12345}" +} +``` + +### /Put/ + +Returns the same results as the Get test. Will only accept the `PUT` request method. + +```powershell +$uri = Get-WebListenerUrl -Test 'Put' +$Body = @{id = 12345} | ConvertTo-Json -Compress +Invoke-RestMethod -Uri $uri -Body $body -Method 'Put' +``` + +```json +{ + "method": "PUT", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0", + "Connection": "Keep-Alive", + "Host": "localhost:8083", + "Content-Length": "12" + }, + "origin": "127.0.0.1", + "url": "http://localhost:8083/Put", + "args": {}, + "data": "{\"id\":12345}" +} +``` + +### /Redirect/ Will 302 redirect to `/Get/`. If a number is supplied, redirect will occur that many times. Can be used to test maximum redirects. @@ -320,6 +459,7 @@ Location: /Redirect/1 ``` Request 2: + ```none GET http://localhost:8083/Redirect/1 HTTP/1.1 Connection: Keep-Alive @@ -328,6 +468,7 @@ Host: localhost:8083 ``` Response 2: + ```none HTTP/1.1 302 Found Date: Fri, 15 Sep 2017 10:46:41 GMT @@ -342,7 +483,7 @@ Location: /Get/

You should be redirected automatically to target URL: /Get/. If not click the link. ``` -## /Response/ +### /Response/ Will return a response crafted from the query string. The following four fields are supported: @@ -350,10 +491,12 @@ Will return a response crafted from the query string. The following four fields * `statuscode` - the HTTP Status Code to return * `contenttype` - The `Content-Type` response header * `headers` - a JSON string containing response headers. `Content-Type` will be ignored in `headers`. Use `contenttype` instead. +* `responsephrase` - the HTTP response phrase to return ```powershell $Query = @{ statsucode = 200 + responsephrase = 'OK' contenttype = 'application/json' body = '{"key1": "value1"}' headers = @{ @@ -377,13 +520,13 @@ Response Body: {"key1": "value1"} ``` -## /ResponseHeaders/ +### /ResponseHeaders/ Will return the response headers passed in query string. The response body will be the supplied headers as a JSON object. ```powershell $uri = Get-WebListenerUrl -Test 'ResponseHeaders' -Query @{'Content-Type' = 'custom'; 'x-header-01' = 'value01'; 'x-header-02' = 'value02'} -Invoke-RestMethod -Uri $uri +Invoke-RestMethod -Uri $uri ``` Response Headers: diff --git a/test/tools/WebListener/Startup.cs b/test/tools/WebListener/Startup.cs index 00553c5e247..1c2417a45cd 100644 --- a/test/tools/WebListener/Startup.cs +++ b/test/tools/WebListener/Startup.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Constraints; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -46,13 +48,31 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) routes.MapRoute( name: "redirect", template: "Redirect/{count?}", - defaults: new {controller = "Redirect", action = "Index"} - ); + defaults: new {controller = "Redirect", action = "Index"}); routes.MapRoute( name: "delay", template: "Delay/{seconds?}", - defaults: new {controller = "Delay", action = "Index"} - ); + defaults: new {controller = "Delay", action = "Index"}); + routes.MapRoute( + name: "post", + template: "Post", + defaults: new {controller = "Get", action = "Index"}, + constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("POST") })); + routes.MapRoute( + name: "put", + template: "Put", + defaults: new {controller = "Get", action = "Index"}, + constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("PUT") })); + routes.MapRoute( + name: "patch", + template: "Patch", + defaults: new {controller = "Get", action = "Index"}, + constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("PATCH") })); + routes.MapRoute( + name: "delete", + template: "Delete", + defaults: new {controller = "Get", action = "Index"}, + constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint("DELETE") })); }); } } diff --git a/test/tools/WebListener/Views/Home/Index.cshtml b/test/tools/WebListener/Views/Home/Index.cshtml index 253ed6879e4..a9c9a8818fd 100644 --- a/test/tools/WebListener/Views/Home/Index.cshtml +++ b/test/tools/WebListener/Views/Home/Index.cshtml @@ -8,9 +8,13 @@

  • /Compression/Deflate/ - Returns deflate compressed response
  • /Compression/Gzip/ - Returns gzip compressed response
  • /Delay/{seconds} - Delays response for seconds seconds.
  • +
  • /Delete/ - returns data from a DELETE request
  • /Encoding/Utf8/ - Returns page containing UTF-8 data.
  • /Get/ - Emulates functionality of https://httpbin.org/get by returning GET headers, Arguments, and Request URL
  • /Multipart/ - Multipart/form-data submission testing
  • +
  • /Patch/ - returns data from a PATCH request
  • +
  • /Post/ - returns data from a POST request
  • +
  • /Put/ - returns data from a PUT request
  • /Redirect/{count} - 302 redirect count times.
  • /Response/?statuscode=<StatusCode>&body=<ResponseBody>&contenttype=<ResponseContentType>&headers=<JsonHeadersObject> - Returns the given response.
  • /ResponseHeaders/?key=val - Returns given response headers.