Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit 934d9a6

Browse files
Tiberriver256TylerLeonhardt
authored andcommitted
Fixes #134 regex routes (#173)
* Throwing a terminating error instead of using an if else statement * Added some better validation for the scriptpath parameter * Initial commit supporting regex and a much simpler matching strategy * Adjusting the get pattern * Added new tests for regular expressions * Fixes #168 - Remove classes from ScriptsToProcess * Fixes #171 - Unable to return a 204 no content response * Fixing the test case for empty route * Removed duplicate examples * Update Public/New-PolarisRoute.ps1 Co-Authored-By: Tiberriver256 <[email protected]> * Trimming new line * Update Tests/e2e/PolarisServer.Tests.ps1 Co-Authored-By: Tiberriver256 <[email protected]> * Fixed newlint and regex casing * Added an about_Routing document * Updated to use -is operator * Reverting the fix for #171 as that is in its own PR * Missed a merge comment * Update Public/Get-PolarisRoute.ps1 Co-Authored-By: Tyler James Leonhardt <[email protected]> * Update Public/Get-PolarisRoute.ps1 Co-Authored-By: Tyler James Leonhardt <[email protected]> * Modifications for code review * Put null on left side for safe comparison * fixes from merge
1 parent a85c31c commit 934d9a6

14 files changed

+475
-184
lines changed

Polaris.psd1

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,31 @@
99
@{
1010

1111
# Script module or binary module file associated with this manifest.
12-
RootModule = "Polaris.psm1"
12+
RootModule = "Polaris.psm1"
1313

1414
# Version number of this module.
15-
ModuleVersion = '0.2.0'
15+
ModuleVersion = '0.2.0'
1616

1717
# Supported PSEditions
1818
CompatiblePSEditions = @('Desktop', 'Core')
1919

2020
# ID used to uniquely identify this module
21-
GUID = 'd9c86d71-cda6-431e-b297-34e0560f8e30'
21+
GUID = 'd9c86d71-cda6-431e-b297-34e0560f8e30'
2222

2323
# Author of this module
24-
Author = 'Microsoft Corporation'
24+
Author = 'Microsoft Corporation'
2525

2626
# Company or vendor of this module
27-
CompanyName = 'Microsoft Corporation'
27+
CompanyName = 'Microsoft Corporation'
2828

2929
# Copyright statement for this module
30-
Copyright = '© Microsoft Corporation. All rights reserved'
30+
Copyright = '© Microsoft Corporation. All rights reserved'
3131

3232
# Description of the functionality provided by this module
33-
Description = 'A cross-platform, minimalist web framework for PowerShell'
33+
Description = 'A cross-platform, minimalist web framework for PowerShell'
3434

3535
# Minimum version of the Windows PowerShell engine required by this module
36-
PowerShellVersion = '5.1'
36+
PowerShellVersion = '5.1'
3737

3838
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
3939
# CLRVersion = ''
@@ -44,16 +44,6 @@
4444
# Modules that must be imported into the global environment prior to importing this module
4545
# RequiredModules = @()
4646

47-
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
48-
ScriptsToProcess = @(
49-
"Public\New-ScriptblockCallback.ps1",
50-
"lib\MimeTypes.Class.ps1",
51-
"lib\PolarisRequest.Class.ps1",
52-
"lib\PolarisResponse.Class.ps1",
53-
"lib\PolarisMiddleware.Class.ps1",
54-
"lib\Polaris.Class.ps1"
55-
)
56-
5747
# Type files (.ps1xml) to be loaded when importing this module
5848
# TypesToProcess = @()
5949

@@ -64,7 +54,7 @@
6454
# NestedModules = @()
6555

6656
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
67-
FunctionsToExport = @(
57+
FunctionsToExport = @(
6858
'Get-Polaris'
6959
'Clear-Polaris'
7060
'New-PolarisRoute'
@@ -85,13 +75,13 @@
8575
'Stop-Polaris' )
8676

8777
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
88-
CmdletsToExport = @()
78+
CmdletsToExport = @()
8979

9080
# Variables to export from this module
91-
VariablesToExport = '*'
81+
VariablesToExport = '*'
9282

9383
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
94-
AliasesToExport = '*'
84+
AliasesToExport = '*'
9585

9686
# List of all modules packaged with this module
9787
# ModuleList = @()
@@ -100,19 +90,19 @@
10090
# FileList = @()
10191

10292
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
103-
PrivateData = @{
93+
PrivateData = @{
10494

10595
PSData = @{
10696

10797
# Tags applied to this module. These help with module discovery in online galleries.
108-
Tags = @('web','core','framework','REST')
98+
Tags = @('web', 'core', 'framework', 'REST')
10999

110100
# A URL to the license for this module.
111-
LicenseUri = 'https://github.com/PowerShell/Polaris/blob/master/LICENSE.txt'
101+
LicenseUri = 'https://github.com/PowerShell/Polaris/blob/master/LICENSE.txt'
112102

113103
# A URL to the main website for this project.
114-
ProjectUri = 'https://github.com/PowerShell/Polaris'
115-
104+
ProjectUri = 'https://github.com/PowerShell/Polaris'
105+
116106
# A URL to an icon representing this module.
117107
# IconUri = ''
118108

Public/Get-PolarisRoute.ps1

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,36 +44,25 @@ function Get-PolarisRoute {
4444
[Parameter( ValueFromPipeline = $True,
4545
ValueFromPipelineByPropertyName = $True )]
4646
[string[]]
47-
$Path = '*',
47+
$Path = @('*'),
4848

4949
[Parameter( ValueFromPipelineByPropertyName = $True )]
5050
[string[]]
51-
$Method = '*',
52-
51+
$Method = @('*'),
5352

5453
$Polaris = $Script:Polaris
5554
)
5655

5756
process {
5857
if ( $Polaris ) {
59-
$WebRoutes = [System.Collections.ArrayList]@()
60-
61-
ForEach ( $Route in $Polaris.ScriptblockRoutes.GetEnumerator() ) {
62-
ForEach ( $RouteMethod in $Route.Value.GetEnumerator() ) {
63-
$Null = $WebRoutes.Add( [pscustomobject]@{ Path = $Route.Key; Method = $RouteMethod.Key; Scriptblock = $RouteMethod.Value } )
64-
}
58+
$MatchingRoutes = foreach ($Pattern in $Path) {
59+
$Polaris.Routes | where { $_.Path -like $Pattern -or $_.Path -like "/$Pattern" }
60+
}
61+
$MatchMethodAndRoutes = foreach ($Pattern in $Method) {
62+
$MatchingRoutes | where { $_.Method -like $Pattern }
6563
}
6664

67-
$Filter = [scriptblock]::Create( (
68-
'( ' +
69-
( $Path.ForEach( { "`$_.Path -like `"/$($_.TrimStart("/"))`"" } ) -join ' -or ' ) +
70-
' ) -and ( ' +
71-
( $Method.ForEach( { "`$_.Method -like `"$($_)`"" } ) -join ' -or ' ) +
72-
' )' ) )
73-
74-
$WebRoutes = $WebRoutes.Where( $Filter )
75-
76-
return $WebRoutes
65+
return $MatchMethodAndRoutes | Sort-Object -Property Path, Method -Unique
7766
}
7867
}
7968
}

Public/New-PolarisRoute.ps1

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#
1+
#
22
# Copyright (c) Microsoft. All rights reserved.
33
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
#
@@ -9,7 +9,11 @@
99
.DESCRIPTION
1010
Create web route for server to serve.
1111
.PARAMETER Path
12-
Path (path/route/endpoint) of the web route to to be serviced.
12+
The path for which the given scriptblock or script is invoked; can be any of:
13+
* A string representing a path.
14+
* A path pattern.
15+
* A regular expression to match paths.
16+
For examples, see Path examples.
1317
.PARAMETER Method
1418
HTTP verb/method to be serviced.
1519
Valid values are GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE
@@ -37,7 +41,6 @@ function New-PolarisRoute {
3741
[CmdletBinding()]
3842
param(
3943
[Parameter( Mandatory = $True, Position = 0 )]
40-
[string]
4144
$Path,
4245

4346
[Parameter( Mandatory = $True, Position = 1 )]
@@ -50,6 +53,18 @@ function New-PolarisRoute {
5053
$Scriptblock,
5154

5255
[Parameter( Mandatory = $True, ParameterSetName = 'ScriptPath' )]
56+
[ValidateScript( {
57+
if (-Not ($_ | Test-Path) ) {
58+
throw "File does not exist"
59+
}
60+
if (-Not ($_ | Test-Path -PathType Leaf) ) {
61+
throw "The Path argument must be a file. Folder paths are not allowed."
62+
}
63+
if ([System.IO.Path]::GetExtension($_) -ne ".ps1") {
64+
throw "The file specified in the path argument must be of type .ps1"
65+
}
66+
return $true
67+
})]
5368
[string]
5469
$ScriptPath,
5570

@@ -61,47 +76,42 @@ function New-PolarisRoute {
6176
$Method = $Method.ToUpper()
6277
$ExistingWebRoute = Get-PolarisRoute -Path $Path -Method $Method
6378

64-
if ( $ExistingWebRoute -and $Force ) {
79+
if ( $ExistingWebRoute ) {
80+
if ( -not $Force ) {
81+
$Exception = [System.Exception]'WebRoute already exists.'
82+
$ErrorId = "Polaris.Webroute.RouteAlreadyExists"
83+
$ErrorCategory = [System.Management.Automation.ErrorCategory]::ResourceExists
84+
$TargetObject = "$Path,$Method"
85+
86+
$WebRouteExistsError = [System.Management.Automation.ErrorRecord]::new(
87+
$Exception,
88+
$ErrorId,
89+
$ErrorCategory,
90+
$TargetObject
91+
)
92+
93+
throw $WebRouteExistsError
94+
# If $Force is specified and there is an existing webroute we remove it
95+
}
6596
Remove-PolarisRoute -Path $Path -Method $Method
66-
$ExistingWebRoute = Get-PolarisRoute -Path $Path -Method $Method
6797
}
6898

69-
if ( $ExistingWebRoute ) {
70-
$PSCmdlet.WriteError( (
71-
New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList @(
72-
[System.Exception]'WebRoute already exists.'
73-
$Null
74-
[System.Management.Automation.ErrorCategory]::ResourceExists
75-
"$Path,$Method" ) ) )
99+
CreateNewPolarisIfNeeded
100+
if ( -not $Polaris) {
101+
$Polaris = $Script:Polaris
76102
}
77-
else {
78-
CreateNewPolarisIfNeeded
79-
if( -not $Polaris){
80-
$Polaris = $Script:Polaris
81-
}
82103

83-
if ( -not $Path.StartsWith( '/' ) ) {
84-
$Path = '/' + $Path
85-
}
104+
if ( $Path -is [string] -and -not $Path.StartsWith( '/' ) ) {
105+
$Path = '/' + $Path
106+
}
86107

87-
switch ( $PSCmdlet.ParameterSetName ) {
88-
'Scriptblock' {
89-
$Polaris.AddRoute( $Path, $Method, $Scriptblock )
90-
}
91-
'ScriptPath' {
92-
if ( Test-Path -Path $ScriptPath ) {
93-
$Script = Get-Content -Path $ScriptPath -Raw
94-
$Polaris.AddRoute( $Path, $Method, [scriptblock]::Create($Script) )
95-
}
96-
else {
97-
$PSCmdlet.WriteError( (
98-
New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList @(
99-
[System.Exception]'ScriptPath not found.'
100-
$Null
101-
[System.Management.Automation.ErrorCategory]::ObjectNotFound
102-
$ScriptPath ) ) )
103-
}
104-
}
108+
switch ( $PSCmdlet.ParameterSetName ) {
109+
'Scriptblock' {
110+
$Polaris.AddRoute( $Path, $Method, $Scriptblock )
111+
}
112+
'ScriptPath' {
113+
$Script = Get-Content -Path $ScriptPath -Raw
114+
$Polaris.AddRoute( $Path, $Method, [scriptblock]::Create($Script) )
105115
}
106116
}
107117
}

Public/Remove-PolarisRoute.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ function Remove-PolarisRoute {
4444
[Parameter( ValueFromPipeline = $True,
4545
ValueFromPipelineByPropertyName = $True )]
4646
[string[]]
47-
$Path = '*',
47+
$Path = @('*'),
4848

4949
[Parameter( ValueFromPipelineByPropertyName = $True )]
5050
[string[]]
51-
$Method = '*',
51+
$Method = @('*'),
5252

5353

5454
$Polaris = $Script:Polaris

Public/Use-PolarisJsonBodyParserMiddleware.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#
1+
#
22
# Copyright (c) Microsoft. All rights reserved.
33
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
#
@@ -21,7 +21,7 @@ function Use-PolarisJsonBodyParserMiddleware {
2121
)
2222

2323
New-PolarisRouteMiddleware -Name JsonBodyParser -Scriptblock {
24-
if ( $Request.BodyString -ne $Null ) {
24+
if ( $Null -ne $Request.BodyString ) {
2525
$Request.Body = $Request.BodyString | ConvertFrom-Json
2626
}
2727
} -Force -Polaris $Polaris

Tests/e2e/PolarisServer.Tests.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ Describe "Test webserver use (E2E)" {
106106
$Result.StatusCode | Should Be 200
107107
}
108108

109-
110109
It "test /header router" {
111110
$Result = Invoke-WebRequest -Uri "http://localhost:$Port/header" -UseBasicParsing
112111
$Result.Content | Should Be 'Header test'

Tests/e2e/Routes.Tests.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Describe "Polaris Routing (e2e)" {
3232
$Response.Send(($Request.Parameters | ConvertTo-JSON))
3333
}
3434

35+
New-PolarisRoute -Path ([Regex]::new("/userRegex/(?<userId>\d+)")) -Method "GET" -Scriptblock {
36+
$Response.Send(($Request.Parameters | ConvertTo-JSON))
37+
}
38+
3539
New-PolarisRoute -Path "/" -Method "GET" -Scriptblock {
3640
$Response.Send("root")
3741
}
@@ -94,6 +98,11 @@ Describe "Polaris Routing (e2e)" {
9498
$Result.userId | Should Be '42'
9599
}
96100

101+
It "should allow custom named capture regular expressions of RegEx type" {
102+
$Result = Invoke-RestMethod -Uri "http://localhost:$Port/userRegex/42" -UseBasicParsing -TimeoutSec 2
103+
$Result.userId | Should Be '42'
104+
}
105+
97106
It "should provide matches with basic strings" {
98107
$Result = Invoke-WebRequest -Uri "http://localhost:$Port/" -UseBasicParsing -TimeoutSec 2
99108
$Result.Content | Should Be 'root'

0 commit comments

Comments
 (0)