Skip to content

Commit 0fb59bc

Browse files
committed
#202: enable support for hosting as an IIS app
1 parent 7196725 commit 0fb59bc

File tree

16 files changed

+132
-59
lines changed

16 files changed

+132
-59
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
> 💝 A lot of my free time, evenings, and weekends goes into making Pode happen; please do consider sponsoring as it will really help! 😊
1313
14-
This is a web template framework for use with the [Pode](https://github.com/Badgerati/Pode) PowerShell web server (v2.2.0+).
14+
This is a web template framework for use with the [Pode](https://github.com/Badgerati/Pode) PowerShell web server (v2.5.0+).
1515

1616
It allows you to build web pages purely with PowerShell - no HTML, CSS, or JavaScript knowledge required!
1717

docs/Getting-Started/Installation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Pode.Web is a PowerShell module that works along side [Pode](https://github.com/
66

77
Before installing Pode.Web, the minimum requirements must be met:
88

9-
* Pode v2.2.0+
9+
* Pode v2.5.0+
1010

1111
Which also includes Pode's minimum requirements:
1212
* OS:

docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
> 💝 A lot of my free time, evenings, and weekends goes into making Pode happen; please do consider sponsoring as it will really help! 😊
99
10-
This is a web template framework for use with the [Pode](https://github.com/Badgerati/Pode) PowerShell web server (v2.2.0+).
10+
This is a web template framework for use with the [Pode](https://github.com/Badgerati/Pode) PowerShell web server (v2.5.0+).
1111

1212
It allows you to build web pages purely with PowerShell - no HTML, CSS, or JavaScript knowledge required!
1313

examples/web.config

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<configuration>
2+
<location path="." inheritInChildApplications="false">
3+
<system.webServer>
4+
<handlers>
5+
<remove name="WebDAV" />
6+
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
7+
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
8+
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
9+
<remove name="ExtensionlessUrl-Integrated-4.0" />
10+
<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
11+
</handlers>
12+
13+
<modules>
14+
<remove name="WebDAVModule" />
15+
</modules>
16+
17+
<aspNetCore processPath="pwsh.exe" arguments=".\full.ps1" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel="OutOfProcess"/>
18+
19+
<security>
20+
<authorization>
21+
<remove users="*" roles="" verbs="" />
22+
<add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,DELETE,DEBUG,OPTIONS" />
23+
</authorization>
24+
</security>
25+
</system.webServer>
26+
</location>
27+
</configuration>

src/Private/Helpers.ps1

+28-3
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ function Get-PodeWebAuthAvatarUrl
114114
# nothing if no property set
115115
$prop = (Get-PodeWebState -Name 'auth-props').Avatar
116116
if (![string]::IsNullOrWhiteSpace($prop) -and ![string]::IsNullOrWhiteSpace($user.$prop)) {
117-
return $user.$prop
117+
return (Add-PodeWebAppPath -Url $user.$prop)
118118
}
119119

120120
# avatar url
121121
if (![string]::IsNullOrWhiteSpace($user.AvatarUrl)) {
122-
return $user.AvatarUrl
122+
return (Add-PodeWebAppPath -Url $user.AvatarUrl)
123123
}
124124

125125
return [string]::Empty
@@ -241,9 +241,26 @@ function Write-PodeWebViewResponse
241241
$Data = @{}
242242
)
243243

244+
$Data['AppPath'] = (Get-PodeWebState -Name 'app-path')
244245
Write-PodeViewResponse -Path "$($Path).pode" -Data $Data -Folder 'pode.web.views' -FlashMessages
245246
}
246247

248+
function Add-PodeWebAppPath
249+
{
250+
param(
251+
[Parameter()]
252+
[string]
253+
$Url
254+
)
255+
256+
if (![string]::IsNullOrWhiteSpace($Url) -and $Url.StartsWith('/')) {
257+
$appPath = Get-PodeWebState -Name 'app-path'
258+
$Url = "$($appPath)$($Url)"
259+
}
260+
261+
return $Url
262+
}
263+
247264
function Use-PodeWebPartialView
248265
{
249266
param(
@@ -697,7 +714,10 @@ function Get-PodeWebPagePath
697714

698715
[Parameter(ParameterSetName='Page')]
699716
[hashtable]
700-
$Page
717+
$Page,
718+
719+
[switch]
720+
$NoAppPath
701721
)
702722

703723
$path = [string]::Empty
@@ -712,6 +732,11 @@ function Get-PodeWebPagePath
712732
}
713733

714734
$path += "/pages/$($Name)"
735+
736+
if (!$NoAppPath) {
737+
$path = (Add-PodeWebAppPath -Url $path)
738+
}
739+
715740
return $path
716741
}
717742

src/Public/Elements.ps1

+9-9
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ function New-PodeWebImage
818818
ObjectType = 'Image'
819819
Parent = $ElementData
820820
ID = $Id
821-
Source = $Source
821+
Source = (Add-PodeWebAppPath -Url $Source)
822822
Title = $Title
823823
Alignment = $Alignment.ToLowerInvariant()
824824
Height = (ConvertTo-PodeWebSize -Value $Height -Default 'auto' -Type 'px')
@@ -1037,7 +1037,7 @@ function New-PodeWebLink
10371037
ObjectType = 'Link'
10381038
Parent = $ElementData
10391039
ID = $Id
1040-
Source = $Source
1040+
Source = (Add-PodeWebAppPath -Url $Source)
10411041
Value = $Value
10421042
NewTab = $NewTab.IsPresent
10431043
CssClasses = ($CssClass -join ' ')
@@ -1501,7 +1501,7 @@ function New-PodeWebButton
15011501
ID = $Id
15021502
DataValue = $DataValue
15031503
Icon = $Icon
1504-
Url = $Url
1504+
Url = (Add-PodeWebAppPath -Url $Url)
15051505
IsDynamic = ($null -ne $ScriptBlock)
15061506
IconOnly = $IconOnly.IsPresent
15071507
Colour = $Colour
@@ -1787,7 +1787,7 @@ function New-PodeWebComment
17871787
ObjectType = 'Comment'
17881788
Parent = $ElementData
17891789
ID = $Id
1790-
Icon = $Icon
1790+
Icon = (Add-PodeWebAppPath -Url $Icon)
17911791
Username = $Username
17921792
Message = $Message
17931793
TimeStamp = $TimeStamp
@@ -2936,7 +2936,7 @@ function New-PodeWebFileStream
29362936
Name = $Name
29372937
ID = $Id
29382938
Height = $Height
2939-
Url = $Url
2939+
Url = (Add-PodeWebAppPath -Url $Url)
29402940
Interval = ($Interval * 1000)
29412941
Icon = $Icon
29422942
CssClasses = ($CssClass -join ' ')
@@ -2986,7 +2986,7 @@ function New-PodeWebIFrame
29862986
Parent = $ElementData
29872987
Name = $Name
29882988
ID = (Get-PodeWebElementId -Tag iFrame -Id $Id -Name $Name)
2989-
Url = $Url
2989+
Url = (Add-PodeWebAppPath -Url $Url)
29902990
Title = $Title
29912991
NoEvents = $true
29922992
CssClasses = ($CssClass -join ' ')
@@ -3102,7 +3102,7 @@ function New-PodeWebAudioSource
31023102
return @{
31033103
ComponentType = 'Element'
31043104
ObjectType = 'AudioSource'
3105-
Url = $Url
3105+
Url = (Add-PodeWebAppPath -Url $Url)
31063106
Type = $type
31073107
NoEvents = $true
31083108
}
@@ -3230,7 +3230,7 @@ function New-PodeWebVideoSource
32303230
return @{
32313231
ComponentType = 'Element'
32323232
ObjectType = 'VideoSource'
3233-
Url = $Url
3233+
Url = (Add-PodeWebAppPath -Url $Url)
32343234
Type = $type
32353235
NoEvents = $true
32363236
}
@@ -3272,7 +3272,7 @@ function New-PodeWebMediaTrack
32723272
return @{
32733273
ComponentType = 'Element'
32743274
ObjectType = 'MediaTrack'
3275-
Url = $Url
3275+
Url = (Add-PodeWebAppPath -Url $Url)
32763276
Language = $Language
32773277
Title = $Title
32783278
Type = $Type.ToLowerInvariant()

src/Public/Layouts.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ function New-PodeWebBreadcrumbItem
749749
ComponentType = 'Layout'
750750
ObjectType = 'BreadcrumbItem'
751751
Name = $Name
752-
Url = $Url
752+
Url = (Add-PodeWebAppPath -Url $Url)
753753
Active = $Active.IsPresent
754754
NoEvents = $true
755755
}

src/Public/Navigation.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function New-PodeWebNavLink
4646
NavType = 'Link'
4747
Name = $Name
4848
ID = $Id
49-
Url = $Url
49+
Url = (Add-PodeWebAppPath -Url $Url)
5050
Icon = $Icon
5151
IsDynamic = ($null -ne $ScriptBlock)
5252
Disabled = $Disabled.IsPresent

src/Public/Outputs.ps1

+3-3
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ function Show-PodeWebNotification
936936
ObjectType = 'Notification'
937937
Title = $Title
938938
Body = $Body
939-
Icon = $Icon
939+
Icon = (Add-PodeWebAppPath -Url $Icon)
940940
}
941941
}
942942

@@ -989,7 +989,7 @@ function Move-PodeWebUrl
989989
return @{
990990
Operation = 'Move'
991991
ObjectType = 'Href'
992-
Url = $Url
992+
Url = (Add-PodeWebAppPath -Url $Url)
993993
NewTab = $NewTab.IsPresent
994994
}
995995
}
@@ -1485,7 +1485,7 @@ function Update-PodeWebFileStream
14851485
ObjectType = 'FileStream'
14861486
ID = $Id
14871487
Name = $Name
1488-
Url = $Url
1488+
Url = (Add-PodeWebAppPath -Url $Url)
14891489
}
14901490
}
14911491

src/Public/Pages.ps1

+10-5
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,20 @@ function Set-PodeWebLoginPage
5353
if ([string]::IsNullOrWhiteSpace($Logo)) {
5454
$Logo = '/pode.web/images/icon.png'
5555
}
56+
$Logo = (Add-PodeWebAppPath -Url $Logo)
5657

5758
if ([string]::IsNullOrWhiteSpace($LogoUrl)) {
5859
$LogoUrl = '/'
5960
}
61+
$LogoUrl = (Add-PodeWebAppPath -Url $LogoUrl)
62+
63+
# background image
64+
$BackgroundImage = (Add-PodeWebAppPath -Url $BackgroundImage)
6065

6166
# set default failure/success urls
6267
$auth = Get-PodeAuth -Name $Authentication
63-
$auth.Failure.Url = '/login'
64-
$auth.Success.Url = '/'
68+
$auth.Failure.Url = (Add-PodeWebAppPath -Url '/login')
69+
$auth.Success.Url = (Add-PodeWebAppPath -Url '/')
6570

6671
# is this auto-redirect oauth2?
6772
$isOAuth2 = ($auth.Scheme.Scheme -ieq 'oauth2')
@@ -345,7 +350,7 @@ function Add-PodeWebPage
345350
}
346351

347352
# add the page route
348-
$routePath = $pageMeta.Url
353+
$routePath = (Get-PodeWebPagePath -Name $Name -Group $Group -NoAppPath)
349354
Add-PodeRoute -Method Get -Path $routePath -Authentication $auth -ArgumentList @{ Data = $ArgumentList } -EndpointName $EndpointName -ScriptBlock {
350355
param($Data)
351356
$global:PageData = $using:pageMeta
@@ -524,7 +529,7 @@ function Add-PodeWebPageLink
524529
NewTab = $NewTab.IsPresent
525530
Icon = $Icon
526531
Group = $Group
527-
Url = $Url
532+
Url = (Add-PodeWebAppPath -Url $Url)
528533
Hide = $Hide.IsPresent
529534
IsDynamic = ($null -ne $ScriptBlock)
530535
Access = @{
@@ -535,7 +540,7 @@ function Add-PodeWebPageLink
535540

536541
Set-PodeWebState -Name 'pages' -Value (@(Get-PodeWebState -Name 'pages') + $pageMeta)
537542

538-
$routePath = (Get-PodeWebPagePath -Name $Name -Group $Group)
543+
$routePath = (Get-PodeWebPagePath -Name $Name -Group $Group -NoAppPath)
539544
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
540545
$auth = $null
541546
if (!$NoAuthentication) {

src/Public/Utilities.ps1

+13-7
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ function Use-PodeWebTemplates
3131
)
3232

3333
$mod = (Get-Module -Name Pode -ErrorAction Ignore | Sort-Object -Property Version -Descending | Select-Object -First 1)
34-
if (($null -eq $mod) -or ($mod.Version.Major -lt 2)) {
35-
throw "The Pode module is not loaded. You need at least Pode 2.0 to use the Pode.Web module."
34+
if (($null -eq $mod) -or ($mod.Version -lt [version]'2.5.0')) {
35+
throw "The Pode module is not loaded. You need at least Pode v2.5.0 to use this version of the Pode.Web module."
3636
}
3737

3838
if ([string]::IsNullOrWhiteSpace($FavIcon)) {
@@ -41,9 +41,15 @@ function Use-PodeWebTemplates
4141

4242
Export-PodeModule -Name Pode.Web
4343

44+
$appPath = Get-PodeIISApplicationPath
45+
if ([string]::IsNullOrWhiteSpace($appPath) -or ($appPath -eq '/')) {
46+
$appPath = [string]::Empty
47+
}
48+
Set-PodeWebState -Name 'app-path' -Value ($appPath.ToLowerInvariant())
49+
4450
Set-PodeWebState -Name 'title' -Value $Title
45-
Set-PodeWebState -Name 'logo' -Value $Logo
46-
Set-PodeWebState -Name 'favicon' -Value $FavIcon
51+
Set-PodeWebState -Name 'logo' -Value (Add-PodeWebAppPath -Url $Logo)
52+
Set-PodeWebState -Name 'favicon' -Value (Add-PodeWebAppPath -Url $FavIcon)
4753
Set-PodeWebState -Name 'no-page-filter' -Value $NoPageFilter.IsPresent
4854
Set-PodeWebState -Name 'hide-sidebar' -Value $HideSidebar.IsPresent
4955
Set-PodeWebState -Name 'social' -Value ([ordered]@{})
@@ -87,7 +93,7 @@ function Import-PodeWebStylesheet
8793
$Url
8894
)
8995

90-
Set-PodeWebState -Name 'custom-css' -Value (@(Get-PodeWebState -Name 'custom-css') + $Url)
96+
Set-PodeWebState -Name 'custom-css' -Value (@(Get-PodeWebState -Name 'custom-css') + (Add-PodeWebAppPath -Url $Url))
9197
}
9298

9399
function Import-PodeWebJavaScript
@@ -99,7 +105,7 @@ function Import-PodeWebJavaScript
99105
$Url
100106
)
101107

102-
Set-PodeWebState -Name 'custom-js' -Value (@(Get-PodeWebState -Name 'custom-js') + $Url)
108+
Set-PodeWebState -Name 'custom-js' -Value (@(Get-PodeWebState -Name 'custom-js') + (Add-PodeWebAppPath -Url $Url))
103109
}
104110

105111
function Set-PodeWebSocial
@@ -222,7 +228,7 @@ function Add-PodeWebCustomTheme
222228

223229
# add the custom theme
224230
$customThemes.Themes[$Name] = @{
225-
Url = $Url
231+
Url = (Add-PodeWebAppPath -Url $Url)
226232
}
227233

228234
# set as theme if first one

src/Templates/Public/scripts/default.js

+4
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ function sendAjaxReq(url, data, sender, useActions, successCallback, opts) {
551551
// remove validation errors
552552
removeValidationErrors(sender);
553553

554+
// add app-path to url (for the likes of IIS)
555+
var appPath = $('body').attr('pode-app-path');
556+
url = `${appPath}${url}`;
557+
554558
// add current query string
555559
if (window.location.search) {
556560
url = `${url}${window.location.search}`;

0 commit comments

Comments
 (0)