Skip to content

Commit

Permalink
Merge pull request #579 from Badgerati/Issue-573
Browse files Browse the repository at this point in the history
Drops HttpListener, and rewrites Pode's listener in .NET Core.
  • Loading branch information
Badgerati committed Jun 28, 2020
2 parents 0735405 + 2e0ebdd commit bad2272
Show file tree
Hide file tree
Showing 56 changed files with 1,984 additions and 1,671 deletions.
21 changes: 16 additions & 5 deletions .github/CONTRIBUTING.md
Expand Up @@ -13,6 +13,7 @@ The following is a set of guidelines for contributing to Pode on GitHub. These a
* [Issues](#issues)
* [Branch Names](#branch-names)
* [Pull Requests](#pull-requests)
* [Building](#building)
* [Testing](#testing)
* [Documentation](#documentation)
* [Styleguide](#styleguide)
Expand All @@ -38,7 +39,9 @@ If you have a question, feel free to either ask it on [GitHub Issues](https://gi

## About Pode

Pode is a PowerShell framework, and the aim is to make it purely PowerShell only with *no* external dependencies. This allows Pode to be very lightweight, and just work out-of-the-box when the module is installed on any platform.
Pode is a PowerShell framework/web server. The aim is to make it purely PowerShell, with *no* external dependencies - other than what is available in .NET Core. This allows Pode to be very lightweight, and just work out-of-the-box when the module is installed on any platform.

The only current exception to the "all PowerShell" rule is the socket listener Pode uses. This listener is a part of Pode, but is written in .NET Core.

## How to Contribute

Expand All @@ -65,15 +68,23 @@ When you open a new Pull Request, please ensure:

Once opened GitHub will automatically run CI on Windows, Linux and MacOS, as well as Code Coverage.

### Building

Before running any of Pode's examples, you will need to compile the Listener first. To do so you will need [`Invoke-Build`](https://github.com/nightroman/Invoke-Build). Once installed, run the following:

```powershell
Invoke-Build Build
```

### Testing

Pode has Unit Tests, there are also some Performance Tests but you do not need to worry about them. There are also currently no Integration Tests.
Pode has Unit and Integration Tests, there are also some Performance Tests but you do not need to worry about them.

Where possible, please try to create/update new Unit Tests especially for features. Don't worry too much about decreasing the Code Coverage.
Where possible, please try to create/update new Unit/Integration Tests especially for features. Don't worry too much about decreasing the Code Coverage.

The Unit Tests can be found at `/tests/unit/` from the root of the repository.
The Unit Tests can be found at `/tests/unit/` from the root of the repository, and the Integration Tests can be found at `tests/integration`.

To run the tests, you will need [`Invoke-Build`](https://github.com/nightroman/Invoke-Build). Once installed, run the following to run the tests:
To run the tests, you will need [`Invoke-Build`](https://github.com/nightroman/Invoke-Build) (running the tests will compile Pode's listener). Once installed, run the following to run the tests:

```powershell
Invoke-Build Test
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -6,6 +6,7 @@ pode_modules/
ps_modules/
docs/[Ff]unctions/
examples/state.json
pkg/


# Code Runner
Expand All @@ -31,6 +32,7 @@ bld/
[Tt]emp/
[Ll]ogs/
[Ss]ite/
[Ll]ibs/

# Packing Artifacts
*.zip
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/powershell:7.0.1-ubuntu-16.04
LABEL maintainer="Matthew Kelly (Badgerati)"
RUN mkdir -p /usr/local/share/powershell/Modules/Pode
COPY ./src/ /usr/local/share/powershell/Modules/Pode
COPY ./pkg/ /usr/local/share/powershell/Modules/Pode
12 changes: 9 additions & 3 deletions README.md
Expand Up @@ -10,7 +10,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 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/Hosting/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/Hosting/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Hosting/AwsLambda/) support!
Pode is a Cross-Platform 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/Hosting/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/Hosting/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Hosting/AwsLambda/) support!

<p align="center">
<img src="https://github.com/Badgerati/Pode/blob/develop/images/example_code_2.png?raw=true" />
Expand Down Expand Up @@ -54,7 +54,7 @@ Then navigate to `http://127.0.0.1:8000` in your browser.
* Middleware and Sessions on web servers, with Flash message and CSRF support
* Authentication on requests, such as Basic and Windows Active Directory
* Support for dynamically building Routes from Functions and Modules
* (Windows) Generate/bind self-signed certificates, and signed certificates
* Generate/bind self-signed certificates
* (Windows) Open the hosted server as a desktop application

## Install
Expand All @@ -78,10 +78,16 @@ docker pull badgerati/pode
Pull Requests, Bug Reports and Feature Requests are welcome! Feel free to help out with Issues and Projects!

To run the unit tests, run the following command from the root of the repository (this will auto-install Pester for you):
To run the unit tests, run the following command from the root of the repository (this will build Pode and, if needed, auto-install Pester/.NET Core):

```powershell
Invoke-Build Test
```

To just build Pode, before running any examples, run the following:

```powershell
Invoke-Build Build
```

To work on issues you can fork Pode, and then open a Pull Request for approval. Pull Requests should be made against the `develop` branch. Each Pull Request should also have an appropriate issue created.
2 changes: 1 addition & 1 deletion arm32.dockerfile
@@ -1,4 +1,4 @@
FROM badgerati/ps-core:7.0.1-arm32
LABEL maintainer="Matthew Kelly (Badgerati)"
RUN mkdir -p /usr/local/share/powershell/Modules/Pode
COPY ./src/ /usr/local/share/powershell/Modules/Pode
COPY ./pkg/ /usr/local/share/powershell/Modules/Pode
13 changes: 13 additions & 0 deletions docs/Getting-Started/KnownIssues.md
Expand Up @@ -76,3 +76,16 @@ function New-UnboundClassInstance([Type]$type, [object[]]$arguments = $null)
Import-Module '<path>\CreateClassInstanceHelper.psm1'
New-UnboundClassInstance([Foo], $argsForCtor)
```

## Certificates

For HTTPS there are a few issues you may run into, and 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`.
44 changes: 44 additions & 0 deletions docs/Getting-Started/Migrating/1X-to-2X.md
@@ -0,0 +1,44 @@
# From v1.X to v2.X

This is a brief guide on migrating from Pode v1.X to Pode v2.X.

In Pode v2.X the Server got the biggest overhaul with the dropping of HttpListener.

## Server

If you were previously specifying `-Type Pode` on your [`Start-PodeServer`], then you no longer need to - all servers now default to using Pode new .NET Core socket listener.

### Endpoints

With the dropping of HttpListener, the `-Certificate` parameter is now the old `-CertificateFile` parameter. The `-RawCertificate` parameter has been ranamed, and it now called `-X509Certificate`.

The `-CertificateThumbprint` parameter remains the same, and only works on Windows.
The `-Certificate` parameter is now the `-CertificateName` parameter, and also only works on Windows.

### Configuration

Settings that use to be under `Server > Pode` are now just under `Server`. For example, SSL protocols have moved from:

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

to:

```powershell
@{
Server = @{
Ssl= @{
Protocols = @('TLS', 'TLS11', 'TLS12')
}
}
}
```
3 changes: 1 addition & 2 deletions docs/Hosting/IIS.md
@@ -1,6 +1,6 @@
# IIS

Pode's all PowerShell Web Server now enables you to host your server via IIS!
Pode has support for you to host your server via IIS!

When you host your server through IIS, Pode can detect this and internally set the server type and endpoints to automatically work with IIS. This allows IIS to deal with binding, HTTPS and Certificates, as well as external traffic, etc.

Expand Down Expand Up @@ -62,7 +62,6 @@ Once done, you can setup IIS in the normal way:

Pode automatically detects that it is running via IIS, and it changes certain attributes of your Pode server so they work with IIS:

* The server type is set to `Pode` (The same as doing `Start-PodeServer -Type Pode`)
* Endpoints have their Address set to `127.0.0.1` (IIS needs Pode to be on localhost)
* Endpoints have their Port set to `ASPNETCORE_PORT`
* Endpoints have their Protocol set to `HTTP` (IIS deals with HTTPS for us)
Expand Down
78 changes: 54 additions & 24 deletions docs/Tutorials/Certificates.md
@@ -1,47 +1,77 @@
# Certificates

!!! 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 certificates for HTTPS.

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.
There are 6 ways to setup HTTPS on [`Add-PodeEndpoint`](../../Functions/Core/Add-PodeEndpoint):

## Self-Signed
1. Supplying just the `-Certificate`, such as a `.cer`.
2. Supplying both the `-Certificate` and `-CertificatePassword`, such as for `.pfx`.
3. Supplying a `-CertificateThumbprint` for a certificate installed at `Cert:\CurrentUser\My` on Windows.
4. Supplying a `-CertificateName` for a certificate installed at `Cert:\CurrentUser\My` on Windows.
5. Supplying `-X509Certificate` of type `X509Certificate`.
6. Supplying the `-SelfSigned` switch, to generate a quick self-signed `X509Certificate`.

If you are developing/testing a site on HTTPS then Pode can generate and bind quick self-signed certificates. To do this you can pass the `-SelfSigned` swicth to the [`Add-PodeEndpoint`](../../Functions/Core/Add-PodeEndpoint) functions:
## Usage

### File

To bind a certificate file, you use the `-Certificate` parameter, along with the `-CertificatePassword` parameter for `.pfx` certificates. The following example supplies some `.pfx` to enable HTTPS support:

```powershell
Start-PodeServer {
# for an IP:
Add-PodeEndpoint -Address * -Port 8443 -Protocol HTTPS -SelfSigned
# for a hostname:
Add-PodeEndpoint -Address foo.bar.com -Port 8443 -Protocol HTTPS -SelfSigned
Add-PodeEndpoint -Address * -Port 8090 -Protocol Https -Certificate './cert.pfx' -CertificatePassword 'Hunter2'
}
```

## Pre-Installed
### Thumbprint

To bind an already installed signed certificate, the certificate *must* be installed to `Cert:/LocalMachine/My`. Then you can pass the certificate name/domain to `-Certificate` parameter; an example for `*.example.com` is as follows:
On Windows only, you can use a certificate that is installed at `Cert:\CurrentUser\My` using its thumbprint:

```powershell
Start-PodeServer {
# for an IP:
Add-PodeEndpoint -Address * -Port 8443 -Protocol HTTPS -Certificate '*.example.com'
Add-PodeEndpoint -Address * -Port 8090 -Protocol Https -CertificateThumbprint '2A623A8DC46ED42A13B27DD045BFC91FDDAEB957'
}
```

### Name

# for a hostname
Add-PodeEndpoint -Address foo.example.com -Port 8443 -Protocol HTTPS -Certificate '*.example.com'
On Windows only, you can use a certificate that is installed at `Cert:\CurrentUser\My` using its subject name:

```powershell
Start-PodeServer {
Add-PodeEndpoint -Address * -Port 8090 -Protocol Https -CertificateName '*.example.com'
}
```

!!! tip
You could also supply the certificate's thumbprint instead, to the `-CertificateThumbprint` parameter.
### X509

The following will instead create an X509Certificate, and pass that to the endpoint instead:

```powershell
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new('./certs/example.cer')
Add-PodeEndpoint -Address * -Port 8443 -Protocol Https -X509Certificate $cert
```

### Self-Signed

## Clean-Up
If you are developing/testing a site on HTTPS then Pode can generate and bind quick self-signed certificates. To do this you can pass the `-SelfSigned` switch:

If you want to use a new certificate on a binding that already has one, then you'll have to clean-up the binding first. Calling either:
```powershell
Start-PodeServer {
Add-PodeEndpoint -Address * -Port 8443 -Protocol Https -SelfSigned
}
```

## SSL Protocols

* `netsh http delete sslcert ipport=<ip>:<port>`
* `netsh http delete sslcert hostnameport=<hostname>:<port>`
The default allowed SSL protocols are SSL3 and TLS1.2, but you can change these to any of: SSL2, SSL3, TLS, TLS11, TLS12, TLS13. This is specified in your `server.psd1` configuration file:

will remove the binding.
```powershell
@{
Server = @{
Ssl= @{
Protocols = @('TLS', 'TLS11', 'TLS12')
}
}
}
```
22 changes: 2 additions & 20 deletions docs/Tutorials/Compression/Requests.md
Expand Up @@ -11,17 +11,7 @@ There are a number of ways you can specify the compression type, and these are d

## Request

The most common way is to define the a request's compression type in the request's headers. The header to use depends on which web-server type you're using:

| Server Type | Header |
| ----------- | ------ |
| HttpListener | X-Transfer-Encoding |
| Pode | Transfer-Encoding |

HttpListener is the default web server, unless you specify `-Type Pode` on `Start-PodeServer`. The reason for HttpListener using a slightly different header to the normal, is because HttpListener doesn't properly support compression; it will error with a 501 if you set the `Transfer-Encoding` header to either `gzip` or `deflate`.

!!! note
The Pode server does also support `X-Transfer-Encoding`, but it will check `Transfer-Encoding` first.
The most common way is to define the a request's compression type in the request's `Transfer-Endocing` header.

An example of the header in the request is as follows:

Expand Down Expand Up @@ -110,19 +100,11 @@ $gzip.Write($bytes, 0, $bytes.Length)
$gzip.Close()
$ms.Position = 0
# Pode Server
# send request
Invoke-RestMethod `
-Method Post `
-Uri 'http://localhost:8080/ping' `
-Body $ms.ToArray() `
-TransferEncoding gzip `
-ContentType application/json
# HttpListener Server
Invoke-RestMethod `
-Method Post `
-Uri 'http://localhost:8080/ping' `
-Body $ms.ToArray() `
-ContentType application/json `
-Headers @{'X-Transfer-Encoding' = 'gzip'}
```

0 comments on commit bad2272

Please sign in to comment.