Skip to content

Commit

Permalink
Merge pull request #1265 from mdaneri/#1243
Browse files Browse the repository at this point in the history
Implement Enhancing Flexibility with Customizable Default Folder Path
  • Loading branch information
Badgerati authored Mar 31, 2024
2 parents 5b0140d + ffb6980 commit e462867
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 22 deletions.
29 changes: 15 additions & 14 deletions docs/Tutorials/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,18 @@ A "path" like `Server.Ssl.Protocols` looks like the below in the file:
}
```

| Path | Description | Docs |
| ---- | ----------- | ---- |
| Server.Ssl.Protocols | Indicates the SSL Protocols that should be used | [link](../Certificates) |
| Server.Request | Defines request timeout and maximum body size | [link](../RequestLimits) |
| Server.AutoImport | Defines the AutoImport scoping rules for Modules, SnapIns and Functions | [link](../Scoping) |
| Server.Logging | Defines extra configuration for Logging, like masking sensitive data | [link](../Logging/Overview) |
| Server.Root | Overrides root path of the server | [link](../Misc/ServerRoot) |
| Server.Restart | Defines configuration for automatically restarting the server | [link](../Restarting/Types/AutoRestarting) |
| Server.FileMonitor | Defines configuration for restarting the server based on file updates | [link](../Restarting/Types/FileMonitoring) |
| Web.TransferEncoding | Sets the Request TransferEncoding | [link](../Compression/Requests) |
| Web.Compression | Sets any compression to use on the Response | [link](../Compression/Responses) |
| Web.ContentType | Define expected Content Types for certain Routes | [link](../Routes/Utilities/ContentTypes) |
| Web.ErrorPages | Defines configuration for custom error pages | [link](../Routes/Utilities/ErrorPages) |
| Web.Static | Defines configuration for static content, such as caching | [link](../Routes/Utilities/StaticContent) |
| Path | Description | Docs |
| --------------------- | ----------------------------------------------------------------------- | ------------------------------------------ |
| Server.Ssl.Protocols | Indicates the SSL Protocols that should be used | [link](../Certificates) |
| Server.Request | Defines request timeout and maximum body size | [link](../RequestLimits) |
| Server.AutoImport | Defines the AutoImport scoping rules for Modules, SnapIns and Functions | [link](../Scoping) |
| Server.Logging | Defines extra configuration for Logging, like masking sensitive data | [link](../Logging/Overview) |
| Server.Root | Overrides root path of the server | [link](../Misc/ServerRoot) |
| Server.Restart | Defines configuration for automatically restarting the server | [link](../Restarting/Types/AutoRestarting) |
| Server.FileMonitor | Defines configuration for restarting the server based on file updates | [link](../Restarting/Types/FileMonitoring) |
| Server.DefaultFolders | Define custom default folders | [link](../Routes/Utilities/StaticContent) |
| Web.TransferEncoding | Sets the Request TransferEncoding | [link](../Compression/Requests) |
| Web.Compression | Sets any compression to use on the Response | [link](../Compression/Responses) |
| Web.ContentType | Define expected Content Types for certain Routes | [link](../Routes/Utilities/ContentTypes) |
| Web.ErrorPages | Defines configuration for custom error pages | [link](../Routes/Utilities/ErrorPages) |
| Web.Static | Defines configuration for static content, such as caching | [link](../Routes/Utilities/StaticContent) |
34 changes: 33 additions & 1 deletion docs/Tutorials/Routes/Utilities/StaticContent.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Caching is supported on static content.

## Public Directory

You can place static files within the `/public` directory, at the root of your server. If a request is made for a file, then Pode will automatically check the public directory first, and if found will return the back.
You can place static files within the `/public` directory at the root of your server, which serves as the default location for static content. When a request is made for a file, Pode will automatically check this designated static directory first, and if the file is found, it will be returned to the requester.


For example, if you have a `logic.js` at `/public/scripts/logic.js`. The the following request would return the file's content:

Expand All @@ -20,6 +21,37 @@ Or, you can reference the file in a view like:
<script type="text/javascript" src="/scripts/logic.js"></script>
```

### How to change the Default Folders

Usually, the Default Folders are located under the RootPath specified by `Start-PodeServer -RootPath <path>`.
But if you need to relocate this directory, you can do so programmatically using the `Set-PodeStaticFolder` function within your server script or specify a different location in the `server.psd1` configuration file under the `Server.DefaultFolders` property. When a file request is made, Pode will automatically check this designated static directory first, and if the file is found, it will be returned to the requester.

Here an example:

1. Using `Set-PodeStaticFolder`

```powershell
Set-PodeDefaultFolder -Type 'Public' -Path 'c:\custom\public'
Set-PodeDefaultFolder -Type 'Views' -Path 'd:\shared\views'
Set-PodeDefaultFolder -Type 'Errors' -Path 'e:\logs\errors'
```

2. Using `server.psd1` configuration file

```powershell
@{
# For more information https://badgerati.github.io/Pode/Tutorials/Configuration/
Server = @{
# Any othe properties you need in your application
DefaultFolders = @{
Public = 'c:\custom\public'
Views = 'd:\shared\views'
Errors = 'e:\logs\errors'
}
}
}
```

## Static Routes

The following is an example of using the [`Add-PodeStaticRoute`](../../../../Functions/Routes/Add-PodeStaticRoute) function to define a route to some static content directory; this tells Pode where to get static files from for certain routes. This example will define a static route for `/assets`, and will point the route at the internal directory path of `./content/assets`:
Expand Down
2 changes: 2 additions & 0 deletions src/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@
'Test-PodeIsHosted',
'New-PodeCron',
'Test-PodeInRunspace',
'Set-PodeDefaultFolder',
'Get-PodeDefaultFolder',

# routes
'Add-PodeRoute',
Expand Down
19 changes: 19 additions & 0 deletions src/Private/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ function New-PodeContext {
BodySize = 100MB
}

# default Folders
$ctx.Server.DefaultFolders = @{
'Views' = 'views'
'Public' = 'public'
'Errors' = 'errors'
}

# check if there is any global configuration
$ctx.Server.Configuration = Open-PodeConfiguration -ServerRoot $ServerRoot -Context $ctx

Expand Down Expand Up @@ -814,6 +821,18 @@ function Set-PodeServerConfiguration {
if ([long]$Configuration.Request.BodySize -gt 0) {
$Context.Server.Request.BodySize = [long]$Configuration.Request.BodySize
}

if ($Configuration.DefaultFolders) {
if ($Configuration.DefaultFolders.Public) {
$Context.Server.DefaultFolders.Public = $Configuration.DefaultFolders.Public
}
if ($Configuration.DefaultFolders.Views) {
$Context.Server.DefaultFolders.Views = $Configuration.DefaultFolders.Views
}
if ($Configuration.DefaultFolders.Errors) {
$Context.Server.DefaultFolders.Errors = $Configuration.DefaultFolders.Errors
}
}
}

function Set-PodeWebConfiguration {
Expand Down
34 changes: 28 additions & 6 deletions src/Private/Helpers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -941,23 +941,45 @@ function Import-PodeModules {
}
}

<#
.SYNOPSIS
Creates and registers inbuilt PowerShell drives for the Pode server's default folders.
.DESCRIPTION
This function sets up inbuilt PowerShell drives for the Pode web server's default directories: views, public content, and error pages. For each of these directories, if the physical path exists on the server, a new PowerShell drive is created and mapped to this path. These drives provide an easy and consistent way to access server resources like views, static files, and custom error pages within the Pode application.
The function leverages `$PodeContext` to access the server's configuration and to determine the paths for these default folders. If a folder's path exists, the function uses `New-PodePSDrive` to create a PowerShell drive for it and stores this drive in the server's `InbuiltDrives` dictionary, keyed by the folder type.
.PARAMETER None
.EXAMPLE
Add-PodePSInbuiltDrives
This example is typically called within the Pode server setup script or internally by the Pode framework to initialize the PowerShell drives for the server's default folders.
.NOTES
- The function is designed to be used within the Pode framework and relies on the global `$PodeContext` variable for configuration.
- It specifically checks for the existence of paths for views, public content, and errors before attempting to create drives for them.
- This is an internal function and may change in future releases of Pode.
#>
function Add-PodePSInbuiltDrives {

# create drive for views, if path exists
$path = (Join-PodeServerRoot 'views')
$path = (Join-PodeServerRoot -Folder $PodeContext.Server.DefaultFolders.Views)
if (Test-Path $path) {
$PodeContext.Server.InbuiltDrives['views'] = (New-PodePSDrive -Path $path)
$PodeContext.Server.InbuiltDrives[$PodeContext.Server.DefaultFolders.Views] = (New-PodePSDrive -Path $path)
}

# create drive for public content, if path exists
$path = (Join-PodeServerRoot 'public')
$path = (Join-PodeServerRoot $PodeContext.Server.DefaultFolders.Public)
if (Test-Path $path) {
$PodeContext.Server.InbuiltDrives['public'] = (New-PodePSDrive -Path $path)
$PodeContext.Server.InbuiltDrives[$PodeContext.Server.DefaultFolders.Public] = (New-PodePSDrive -Path $path)
}

# create drive for errors, if path exists
$path = (Join-PodeServerRoot 'errors')
$path = (Join-PodeServerRoot $PodeContext.Server.DefaultFolders.Errors)
if (Test-Path $path) {
$PodeContext.Server.InbuiltDrives['errors'] = (New-PodePSDrive -Path $path)
$PodeContext.Server.InbuiltDrives[$PodeContext.Server.DefaultFolders.Errors] = (New-PodePSDrive -Path $path)
}
}

Expand Down
90 changes: 89 additions & 1 deletion src/Public/Core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1246,4 +1246,92 @@ function Get-PodeEndpoint {

# return
return $endpoints
}
}

<#
.SYNOPSIS
Sets the path for a specified default folder type in the Pode server context.
.DESCRIPTION
This function configures the path for one of the Pode server's default folder types: Views, Public, or Errors.
It updates the server's configuration to reflect the new path for the specified folder type.
The function first checks if the provided path exists and is a directory;
if so, it updates the `Server.DefaultFolders` dictionary with the new path.
If the path does not exist or is not a directory, the function throws an error.
The purpose of this function is to allow dynamic configuration of the server's folder paths, which can be useful during server setup or when altering the server's directory structure at runtime.
.PARAMETER Type
The type of the default folder to set the path for. Must be one of 'Views', 'Public', or 'Errors'.
This parameter determines which default folder's path is being set.
.PARAMETER Path
The new file system path for the specified default folder type. This path must exist and be a directory; otherwise, an exception is thrown.
.EXAMPLE
Set-PodeDefaultFolder -Type 'Views' -Path 'C:\Pode\Views'
This example sets the path for the server's default 'Views' folder to 'C:\Pode\Views', assuming this path exists and is a directory.
.EXAMPLE
Set-PodeDefaultFolder -Type 'Public' -Path 'C:\Pode\Public'
This example sets the path for the server's default 'Public' folder to 'C:\Pode\Public'.
#>
function Set-PodeDefaultFolder {

[CmdletBinding()]
param (
[Parameter()]
[ValidateSet('Views', 'Public', 'Errors')]
[string]
$Type,

[Parameter()]
[string]
$Path
)
if (Test-Path -Path $Path -PathType Container) {
$PodeContext.Server.DefaultFolders[$Type] = $Path
}
else {
throw "Folder $Path doesn't exist"
}
}

<#
.SYNOPSIS
Retrieves the path of a specified default folder type from the Pode server context.
.DESCRIPTION
This function returns the path for one of the Pode server's default folder types: Views, Public, or Errors. It accesses the server's configuration stored in the `$PodeContext` variable and retrieves the path for the specified folder type from the `DefaultFolders` dictionary. This function is useful for scripts or modules that need to dynamically access server resources based on the server's current configuration.
.PARAMETER Type
The type of the default folder for which to retrieve the path. The valid options are 'Views', 'Public', or 'Errors'. This parameter determines which folder's path will be returned by the function.
.EXAMPLE
$path = Get-PodeDefaultFolder -Type 'Views'
This example retrieves the current path configured for the server's 'Views' folder and stores it in the `$path` variable.
.EXAMPLE
$path = Get-PodeDefaultFolder -Type 'Public'
This example retrieves the current path configured for the server's 'Public' folder.
.OUTPUTS
String. The file system path of the specified default folder.
#>
function Get-PodeDefaultFolder {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter()]
[ValidateSet('Views', 'Public', 'Errors')]
[string]
$Type
)

return $PodeContext.Server.DefaultFolders[$Type]
}

0 comments on commit e462867

Please sign in to comment.