Restful Server In PowerShell

I know I have been focused on PowerShell but I have down time and wanted to play since our shop seems to love it so much. I think I am going to do some other posts, maybe Node or something, because PowerShell is boring.

I am building a dashboard so I was playing with PowerShell to see if I could get data from Squared Up that the monitoring team already alerts on. This seemed like an easy way to do it since Squared Up will do rest, but I already wrote something in Python for other things years ago and honestly I will stick with Python running on Apache to be an ass, since the admins want it to go away as it’s too scary or ‘hard’. I should rewrite all this shit in C.

For me, I just like Python and I know it will work for years, as it has, whereas Microsoft likes to change things over time breaking shit. Fuck, Microsoft breaks its own shit weekly. Maybe this code will be interesting to you? It is nice that I can just write and run it anywhere since I don’t have to beg to get things installed, just like VBScript, because hacker languages are just so trustworthy running everywhere in an environment running the least secure OS. This works on Linux but does things it shouldn’t. Who knows, who cares?

<#
Restful PowerShite Server Class
Author: C. Nichols
date: Oct. 4, 2019
 
This could easily be wrapped in a GUI that displays status and
requests with start and stop buttons.
#>
 
class RestfulServer {
 
    [string]$host = "localhost"
    [int]$port    = 8080
    [System.Net.HttpListener]$listener = $null
    [string]$status = "Stopped"
    [int]$statusCode = 200
 
    Status () {
        Write-Host $this.status $this.statusCode
    }
 
    Start() {
        if ($this.listener) {
            Write-Host "Server is running."
        } else {
            $uri = "http://{0}:{1}/" -f $this.host, $this.port
            $this.listener = New-Object System.Net.HttpListener
            $this.listener.Prefixes.Add($uri)
            $this.listener.Start()
            Write-Host "Server started."
            $this.status = "Listening on {0}" -f  $uri
        }
    }
 
    Stop() {
        if ($this.listener) {
 
            Write-Host "Server is stopping."
 
            $this.listener.Stop()
            $this.status = "Stopped"
        }
    }
 
    Watch ($watching) {
 
        while ($watching) {
 
            $requestVars = @()
            $context = $this.listener.GetContext()
 
            # Capture the details about the request and setup response.
            $request = $context.Request
            $response = $context.Response
 
            $requestVars = ([String]$request.Url).split("/")
 
            # Exit server.
            if ($request.Url -match '/stop$') {
        
                $watching = $false
                $this.Stop()
 
            } else {
 
                try {
 
                    if ($requestVars[3].Contains("app")) {
               
                        # Get the args from the URL.
                        $result = "{0}, {1}" -f $requestVars[4], $requestVars[5]
                        Write-host "Received " $result
 
                        # Actually we want to do something here for 'app' and return the data,
                        # to the caller.
 
                        # request Json.
                        if ($requestVars[5] -eq "json") {
                            $message = $result | ConvertTo-Json
                            $response.ContentType = 'application/json'
                        } else {
                            $message = $result; # Just send our args back to the browser.
                            $response.ContentType = 'text/html'
                        }
 
                    } else {
                        # Issue a 405
                        Write-host "405: Method not allowed."
                        $message = "<div><h2>405!</h2><p>Method not allowed.</p></div>";
                        $response.ContentType = 'text/html'
                        $this.statusCode = 405
                    }
               
                } catch {
 
                    # Issue a 400
                    Write-host "400: Bad request"
                    $message = "<div><h2>400!</h2><p>Bad request.</p></div>";
                    $response.ContentType = 'text/html'
                    $this.statusCode = 400
               
                }
 
                # Convert the data to UTF8 bytes
                [byte[]]$buffer = [System.Text.Encoding]::UTF8.GetBytes($message)
      
                # Set length of response
                $response.ContentLength64 = $buffer.length
      
                # Write response out and close
                $output = $response.OutputStream
                $output.Write($buffer, 0, $buffer.length)
 
                $output.Close()
 
            }
        }   
    }
}
 
# MAIN
$serv =  New-Object RestfulServer
#$serv.host = "localhost"
#$serv.port = 8080
 
$serv.Start()
 
$serv.Watch($true)
 
<#
 
Test in local browser.
 
http://localhost:8080/app/hello         # Send hello
http://localhost:8080/app/hello/world   # Send hello world
http://localhost:8080/app/hello/json    # Request json to be returned
http://localhost:8080/stop              # Stop server
 
#>