Skip to content

Commit

Permalink
Merge pull request #377 from Badgerati/pode-listener
Browse files Browse the repository at this point in the history
#376: Cross-platform support for HTTPS
  • Loading branch information
Badgerati committed Sep 25, 2019
2 parents d18a9ff + 9254946 commit 271660c
Show file tree
Hide file tree
Showing 31 changed files with 1,056 additions and 102 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ ClientBin/
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
[![PowerShell](https://img.shields.io/powershellgallery/dt/pode.svg?label=PowerShell&colorB=085298)](https://www.powershellgallery.com/packages/Pode)
[![Docker](https://img.shields.io/docker/pulls/badgerati/pode.svg?label=Docker)](https://hub.docker.com/r/badgerati/pode/)

Pode is a Cross-Platform PowerShell framework for creating web servers to host [REST APIs](https://badgerati.github.io/Pode/Tutorials/Routes/Overview/), [Web Pages](https://badgerati.github.io/Pode/Tutorials/Routes/Examples/WebPages/), and [SMTP/TCP](https://badgerati.github.io/Pode/Tutorials/SmtpServer/) Servers. Pode also allows you to render dynamic files using [`.pode`](https://badgerati.github.io/Pode/Tutorials/Views/Pode/) files, which are just embedded PowerShell, or other [Third-Party](https://badgerati.github.io/Pode/Tutorials/Views/ThirdParty/) template engines. Plus many more features, including [Azure Functions](https://badgerati.github.io/Pode/Tutorials/Serverless/Types/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Tutorials/Serverless/Types/AwsLambda/) support!
Pode is a Cross-Platform framework, *completely written in PowerShell*, for creating web servers to host [REST APIs](https://badgerati.github.io/Pode/Tutorials/Routes/Overview/), [Web Pages](https://badgerati.github.io/Pode/Tutorials/Routes/Examples/WebPages/), and [SMTP/TCP](https://badgerati.github.io/Pode/Tutorials/SmtpServer/) Servers. Pode also allows you to render dynamic files using [`.pode`](https://badgerati.github.io/Pode/Tutorials/Views/Pode/) files, which are just embedded PowerShell, or other [Third-Party](https://badgerati.github.io/Pode/Tutorials/Views/ThirdParty/) template engines. Plus many more features, including [Azure Functions](https://badgerati.github.io/Pode/Tutorials/Serverless/Types/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Tutorials/Serverless/Types/AwsLambda/) support!

<p align="center">
<img src="https://github.com/Badgerati/Pode/blob/develop/images/example_code_2.png?raw=true" />
Expand All @@ -38,7 +38,7 @@ Then navigate to `http://127.0.0.1:8000` in your browser.
* Docker support, including images for ARM/Raspberry Pi
* Azure Functions and AWS Lambda support
* Listen on a single or multiple IP address/hostnames
* Support for HTTP, HTTPS, TCP and SMTP
* Support for HTTP, HTTPS, TCP and SMTP (Experimental cross-platform support for HTTPS)
* Host REST APIs, Web Pages, and Static Content (with caching)
* Support for custom error pages
* Multi-thread support for incoming requests
Expand Down
3 changes: 2 additions & 1 deletion docs/Tutorials/Certificates.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

!!! warning
Binding existing, and generating self-signed certificates is only supported on *Windows*.
For cross-platform HTTPS support [see here](../PodeServer).

Pode has the ability to generate and bind self-signed certificates (for dev/testing), as well as the ability to bind existing - already installed - certificates for HTTPS. If Pode detects that the `IP:Port` or `Hostname:Port` binding already has a certificate bound, then Pode will re-use that certificate and will not create a new self-signed certificate, or bind a new certificate.
Pode has the ability to generate and bind self-signed certificates (for dev/testing), as well as the ability to bind existing - already installed - certificates for HTTPS on Windows, using the default Server type. If Pode detects that the `IP:Port` or `Hostname:Port` binding already has a certificate bound, then Pode will re-use that certificate and will not create a new self-signed certificate, or bind a new certificate.

## Self-Signed

Expand Down
100 changes: 100 additions & 0 deletions docs/Tutorials/PodeServer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Pode Server

!!! notice
The Pode server type uses sockets to allow cross-platform support for HTTPS. This server type is also **experimental**.

The Pode server type, as specified above, is an experimental type that uses sockets to allow for cross-platform support of HTTPS (it does also support normal HTTP!).

To start using this server type, there isn't very must you need to do. All that's really required is to set the `-Type` on [`Start-PodeServer`](../../Functions/Core/Start-PodeServer), and to supply a certificate on [`Add-PodeEndpoint`](../../Functions/Core/Add-PodeEndpoint) for HTTPS (detailed below).

## Server Type

To start using the Pode server type, you just need to set the `-Type` on [`Start-PodeServer`](../../Functions/Core/Start-PodeServer). The following example is a simple HTTP server that will use this server type:

```powershell
Start-PodeServer -Type Pode {
Add-PodeEndpoint -Address * -Port 8090 -Protocol Http
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
Write-PodeJsonResponse -Value @{ Kenobi = 'Hello, there' }
}
}
```

## HTTPS

To enable your server to use HTTPS, as well as setting the `-Type` like above, you will also need to supply a certificate on [`Add-PodeEndpoint`](../../Functions/Core/Add-PodeEndpoint). By default, on SSL3 and TLS1.2 connections are allowed - you can change this via the configuration described below.

There are 3 ways to do this:

> The `-Certificate` and `-CertificateThumbprint` parameters are not supported.
> On *nix platforms, only the latter two options are supported.
1. Supplying just the `-CertificateFile`, such as a `.cer`.
2. Supplying both the `-CertificateFile` and `-CertificatePassword`, such as for `.pfx`.
3. Supply a `-RawCertificate` of type `X509Certificate`.

The following example is like above, but this time we'll supply some `.pfx` to enable HTTPS support:

```powershell
Start-PodeServer -Type Pode {
Add-PodeEndpoint -Address * -Port 8090 -Protocol Https -CertificateFile './cert.pfx' -CertificatePassword 'Hunter2'
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
Write-PodeJsonResponse -Value @{ Kenobi = 'Hello, there' }
}
}
```

### Issues

For HTTPS, there are a few issues you may run into. To resolve them, you can use the below:

* On Windows, you may need to install the certificate into your Trusted Root on the Local Machine (mostly for self-signed certificates).
* You may be required to run the following, to force TLS1.2, before making web requests:

```powershell
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
```

* On *nix platforms, for self-signed certificates, you may need to use `-SkipCertificateCheck` on `Invoke-WebRequest` and `Invoke-RestMethod`

## Configuration

There are currently two settings you can define via your `server.psd1` configuration file. Both of these are done within the `Server` section.

### Receive Timeout

The default receive timeout is 100ms, but you can change this to any value above 0:

```powershell
@{
Server = @{
Pode = @{
ReceiveTimeout = 500
}
}
}
```

### SSL Protocols

The default allowed SSL protocols are SSL3 and TLS1.2, but you can change these to any of: SSL2, SSL3, TLS, TLS11, TLS12, TLS13:

```powershell
@{
Server = @{
Pode = @{
Ssl= @{
Protocols = @('TLS', 'TLS11', 'TLS12')
}
}
}
}
```

## Any Problems?

As quite obviously stated, this is experimental. If there are any issues please feel free to [raise them here](https://github.com/Badgerati/Pode/issues).
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![Code Coverage](https://coveralls.io/repos/github/Badgerati/Pode/badge.svg?branch=develop)](https://coveralls.io/github/Badgerati/Pode?branch=develop)
[![Gitter](https://badges.gitter.im/Badgerati/Pode.svg)](https://gitter.im/Badgerati/Pode?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

Pode is a Cross-Platform PowerShell framework to create web servers that host REST APIs, Web Sites, and TCP/SMTP Servers. It also allows you to render dynamic files using `.pode` files, which is effectively embedded PowerShell, or other Third-Party template engines. Pode also has support for middleware, sessions, authentication, and logging; as well as access and rate limiting features. There's also Azure Functions and AWS Lambda support!
Pode is a Cross-Platform framework, *completely written in PowerShell*, to create web servers that host REST APIs, Web Sites, and TCP/SMTP Servers. It also allows you to render dynamic files using `.pode` files, which is effectively embedded PowerShell, or other Third-Party template engines. Pode also has support for middleware, sessions, authentication, and logging; as well as access and rate limiting features. There's also Azure Functions and AWS Lambda support!

[![GetStarted](https://img.shields.io/badge/-Get%20Started!-green.svg?longCache=true&style=for-the-badge)](./Getting-Started/Installation)
[![QuickLook](https://img.shields.io/badge/-Quick%20Look!-blue.svg?longCache=true&style=for-the-badge)](#quick-look)
Expand All @@ -17,7 +17,7 @@ Pode is a Cross-Platform PowerShell framework to create web servers that host RE
* Docker support, including images for ARM/Raspberry Pi
* Azure Functions and AWS Lambda support
* Listen on a single or multiple IP address/hostnames
* Support for HTTP, HTTPS, TCP and SMTP
* Support for HTTP, HTTPS, TCP and SMTP (Experimental cross-platform support for HTTPS)
* Host REST APIs, Web Pages, and Static Content (with caching)
* Support for custom error pages
* Multi-thread support for incoming requests
Expand Down
Binary file added examples/certs/pode-cert.cer
Binary file not shown.
Binary file added examples/certs/pode-cert.pfx
Binary file not shown.
24 changes: 24 additions & 0 deletions examples/web-sockets.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
Import-Module "$($path)/src/Pode.psm1" -Force -ErrorAction Stop

# or just:
# Import-Module Pode

# create a server, and start listening
Start-PodeServer -Type Pode -Threads 5 {

# listen
#Add-PodeEndpoint -Address * -Port 8090 -Protocol Http
#Add-PodeEndpoint -Address * -Port 8095 -Protocol Http
Add-PodeEndpoint -Address * -Port 8090 -CertificateFile './certs/pode-cert.pfx' -CertificatePassword '1234' -Protocol Https

# log requests to the terminal
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging

# GET request for web page on "localhost:8085/"
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
Write-PodeJsonResponse -Value @{
Kenobi = 'Hello, there'
}
}
}
4 changes: 2 additions & 2 deletions packers/choco/pode.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
<owners>Badgerati</owners>
<summary>Pode is a Cross-Platform PowerShell framework for creating web servers to host REST APIs and Websites.</summary>
<description>
Pode is a Cross-Platform PowerShell framework for creating web servers to host REST APIs and Websites. Pode also has support for being used in Azure Functions and AWS Lambda.
Pode is a Cross-Platform framework, completely written in PowerShell, for creating web servers to host REST APIs and Websites. Pode also has support for being used in Azure Functions and AWS Lambda.

### Features

* Cross-platform using PowerShell Core (with support for PS5)
* Docker support, including images for ARM/Raspberry Pi
* Azure Functions and AWS Lambda support
* Listen on a single or multiple IP address/hostnames
* Support for HTTP, HTTPS, TCP and SMTP
* Support for HTTP, HTTPS, TCP and SMTP (Experimental cross-platform support for HTTPS)
* Host REST APIs, Web Pages, and Static Content (with caching)
* Support for custom error pages
* Multi-thread support for incoming requests
Expand Down
1 change: 1 addition & 0 deletions src/Misc/default-error-page.html.pode
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<head>
<title>$($data.status.code)</title>
<meta charset='utf-8'>
</head>

<body style='color: white; font-family: Helvetica,Arial,sans-serif;'>
Expand Down
2 changes: 1 addition & 1 deletion src/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
PowerShellVersion = '5.0'

# Assemblies that must be loaded prior to importing this module
RequiredAssemblies = @('System.Web')
RequiredAssemblies = @('System.Web', 'System.Net.Http')

# Functions to export from this Module
FunctionsToExport = @(
Expand Down
1 change: 1 addition & 0 deletions src/Pode.psm1
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Add-Type -AssemblyName System.Web
Add-Type -AssemblyName System.Net.Http

# import everything if in a runspace
if ($PODE_SCOPE_RUNSPACE) {
Expand Down
32 changes: 29 additions & 3 deletions src/Private/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ function New-PodeContext
Types = @{}
}

# set socket details for pode server
$ctx.Server.Sockets = @{
Listeners = @()
MaxConnections = 0
Ssl = @{
Callback = $null
Protocols = (ConvertTo-PodeSslProtocols -Protocols @('Ssl3', 'Tls12'))
}
ReceiveTimeout = 100
Queues = @{
Contexts = [System.Collections.Generic.List[hashtable]]::new(100)
Connections = [System.Collections.Concurrent.ConcurrentQueue[System.Net.Sockets.SocketAsyncEventArgs]]::new()
}
}

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

Expand All @@ -68,19 +83,21 @@ function New-PodeContext
}

# set the server default type
$ctx.Server.Type = ([string]::Empty)
$ctx.Server.Type = $ServerType.ToUpperInvariant()
if ($Interval -gt 0) {
$ctx.Server.Type = 'SERVICE'
}

if ($isServerless) {
$ctx.Server.Type = $ServerType.ToUpperInvariant()
$ctx.Server.IsServerless = $isServerless
}

# set the IP address details
$ctx.Server.Endpoints = @()

# general encoding for the server
$ctx.Server.Encoding = New-Object System.Text.UTF8Encoding

# setup gui details
$ctx.Server.Gui = @{}

Expand Down Expand Up @@ -203,7 +220,7 @@ function New-PodeRunspacePools

# setup main runspace pool
$threadsCounts = @{
Default = 1
Default = 3
Timer = 1
Log = 1
Schedule = 1
Expand Down Expand Up @@ -308,6 +325,15 @@ function Set-PodeServerConfiguration
}
Types = @{}
}

# sockets (pode)
if (!(Test-IsEmpty $Configuration.Pode.Ssl.Protocols)) {
$Context.Server.Sockets.Ssl.Protocols = (ConvertTo-PodeSslProtocols -Protocols $Configuration.Pode.Ssl.Protocols)
}

if ([int]$Configuration.Pode.ReceiveTimeout -gt 0) {
$Context.Server.Sockets.ReceiveTimeout = (Protect-PodeValue -Value $Configuration.Pode.ReceiveTimeout $Context.Server.Sockets.ReceiveTimeout)
}
}

function Set-PodeWebConfiguration
Expand Down
1 change: 1 addition & 0 deletions src/Private/FileMonitor.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ function Stop-PodeFileMonitor
function Get-PodeFileMonitorName
{
param (
[Parameter(Mandatory=$true)]
[ValidateSet('Create', 'Delete', 'Update')]
[string]
$Type
Expand Down

0 comments on commit 271660c

Please sign in to comment.