Skip to content

Instantly share code, notes, and snippets.

@jakobii
Last active May 4, 2024 14:02
Show Gist options
  • Save jakobii/429dcef1bacacfa1da254a5353bbeac7 to your computer and use it in GitHub Desktop.
Save jakobii/429dcef1bacacfa1da254a5353bbeac7 to your computer and use it in GitHub Desktop.
A Basic Powershell Webserver
# You Should be able to Copy and Paste this into a powershell terminal and it should just work.
# To end the loop you have to kill the powershell terminal. ctrl-c wont work :/
# Http Server
$http = [System.Net.HttpListener]::new()
# Hostname and port to listen on
$http.Prefixes.Add("http://localhost:8080/")
# Start the Http Server
$http.Start()
# Log ready message to terminal
if ($http.IsListening) {
write-host " HTTP Server Ready! " -f 'black' -b 'gre'
write-host "try testing the different route examples: " -f 'y'
write-host "$($http.Prefixes)" -f 'y'
write-host "$($http.Prefixes)some/form" -f 'y'
}
# INFINTE LOOP
# Used to listen for requests
while ($http.IsListening) {
# Get Request Url
# When a request is made in a web browser the GetContext() method will return a request object
# Our route examples below will use the request object properties to decide how to respond
$context = $http.GetContext()
# ROUTE EXAMPLE 1
# http://127.0.0.1/
if ($context.Request.HttpMethod -eq 'GET' -and $context.Request.RawUrl -eq '/') {
# We can log the request to the terminal
write-host "$($context.Request.UserHostAddress) => $($context.Request.Url)" -f 'mag'
# the html/data you want to send to the browser
# you could replace this with: [string]$html = Get-Content "C:\some\path\index.html" -Raw
[string]$html = "<h1>A Powershell Webserver</h1><p>home page</p>"
#resposed to the request
$buffer = [System.Text.Encoding]::UTF8.GetBytes($html) # convert htmtl to bytes
$context.Response.ContentLength64 = $buffer.Length
$context.Response.OutputStream.Write($buffer, 0, $buffer.Length) #stream to broswer
$context.Response.OutputStream.Close() # close the response
}
# ROUTE EXAMPLE 2
# http://localhost:8080/some/form'
if ($context.Request.HttpMethod -eq 'GET' -and $context.Request.RawUrl -eq '/some/form') {
# We can log the request to the terminal
write-host "$($context.Request.UserHostAddress) => $($context.Request.Url)" -f 'mag'
[string]$html = "
<h1>A Powershell Webserver</h1>
<form action='/some/post' method='post'>
<p>A Basic Form</p>
<p>fullname</p>
<input type='text' name='fullname'>
<p>message</p>
<textarea rows='4' cols='50' name='message'></textarea>
<br>
<input type='submit' value='Submit'>
</form>
"
#resposed to the request
$buffer = [System.Text.Encoding]::UTF8.GetBytes($html)
$context.Response.ContentLength64 = $buffer.Length
$context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
$context.Response.OutputStream.Close()
}
# ROUTE EXAMPLE 3
# http://localhost:8080/some/post'
if ($context.Request.HttpMethod -eq 'POST' -and $context.Request.RawUrl -eq '/some/post') {
# decode the form post
# html form members need 'name' attributes as in the example!
$FormContent = [System.IO.StreamReader]::new($context.Request.InputStream).ReadToEnd()
# We can log the request to the terminal
write-host "$($context.Request.UserHostAddress) => $($context.Request.Url)" -f 'mag'
Write-Host $FormContent -f 'Green'
# the html/data
[string]$html = "<h1>A Powershell Webserver</h1><p>Post Successful!</p>"
#resposed to the request
$buffer = [System.Text.Encoding]::UTF8.GetBytes($html)
$context.Response.ContentLength64 = $buffer.Length
$context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
$context.Response.OutputStream.Close()
}
# powershell will continue looping and listen for new requests...
}
@jakobii
Copy link
Author

jakobii commented Jun 14, 2018

added a post example.

@phatmandrake
Copy link

Neat! very clear examples!

@danijeljw
Copy link

You can add a clean exit route by adding the following in the while ($http.IsListening) loop:

# ROUTE EXAMPLE 4
# http://localhost:8080/quit'
if ($context.Request.HttpMethod -eq 'GET' -and $context.Request.RawUrl -eq '/quit')
{
    $http.Close()
}

@ediulia
Copy link

ediulia commented Jan 7, 2021

Great example!
I would recommend replacing line 7
$http = [System.Net.HttpListener]::new()
with the next syntax:
$http = New-Object System.Net.HttpListener

Some frameworks are looking at ::new() as a non-existing method and failing

@MatMayer123
Copy link

Great example!
How do I transfer images ? E. g. in line 74

<img src="1.png" alt="btn1">

I have to add buttons with images

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment