jpsider / RestPS

Simple ReST Framework for Powershell
MIT License
114 stars 31 forks source link

The docs need massive work... #71

Closed abctaylor closed 1 year ago

abctaylor commented 1 year ago

Cool project with a lot of potential. Docs however are kinda bad.

For example, there's pretty much no guidance on doing a POST request and going through the example code is not clear how the JSON is structured. The routing also doesn't clearly show how to pass parameters.

Happy to help, nice project.

jpsider commented 1 year ago

Could not agree more! Do you want to create issues to address your problems individually?

abctaylor commented 1 year ago

Would love to but don't want to spam the repo with issues, what is the correct etiquette ? I can keep things succinct and to the point and commit to the ReadTheDocs as needed when issues get resolved.

So, I'll start here. How can I format a POST request to get all processes by a given name eg if I POST the following:

{"name" : "powershell"}

How does the Invoke-GetProcess get RequestArgs from the post data? This is the mystery 😀

Note to anyone reading this issue; the above does not work - it is what I am trying to get.

How could I expand this to take many different key-values for some compels custom ps1 file I eventually route POST requests to?

Thanks, Andrew

On 13 Jan 2023, at 19:49, Justin Sider @.***> wrote:

 EXTERNAL

Could not agree more! Do you want to create issues to address your problems individually?

— Reply to this email directly, view it on GitHubhttps://github.com/jpsider/RestPS/issues/71#issuecomment-1382246155, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHGMLVWHVJPF3INCERE5TKDWSGPTHANCNFSM6AAAAAAT2WUQ5U. You are receiving this because you authored the thread.Message ID: @.***>

jpsider commented 1 year ago

Just so I am clear. You are posting this as a JSON payload in the body of the request?

abctaylor commented 1 year ago

Yep correct. I thought best to set a Content-Type application/json header and then send a JSON body with some reasonable structure.

Should this be done another way?

Andrew

Sent from a mobile device

On 13 Jan 2023, at 20:41, Justin Sider @.***> wrote:

 EXTERNAL

Just so I am clear. You are posting this as a JSON payload in the body of the request?

— Reply to this email directly, view it on GitHubhttps://github.com/jpsider/RestPS/issues/71#issuecomment-1382312230, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHGMLVQ43DMHPLEKIZHDGK3WSGVVRANCNFSM6AAAAAAT2WUQ5U. You are receiving this because you authored the thread.Message ID: @.***>

jpsider commented 1 year ago

You are on the right path. Are you using an example script? or have you written your own?

abctaylor commented 1 year ago

At the moment just testing against your example /data POST endpoint from the default JSON file that is generated when you set up the project, which hits the Invoke-GetProcess script. Not sure how to structure the POST data however!

Sent from a mobile device

On 13 Jan 2023, at 20:51, Justin Sider @.***> wrote:

 EXTERNAL

You are on the right path. Are you using an example script? or have you written your own?

— Reply to this email directly, view it on GitHubhttps://github.com/jpsider/RestPS/issues/71#issuecomment-1382321626, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHGMLVWUQCFFYF4WXRH6HWDWSGW5VANCNFSM6AAAAAAT2WUQ5U. You are receiving this because you authored the thread.Message ID: @.***>

jpsider commented 1 year ago

It works for me. Here is the Routes.json file [ { "RequestType": "GET", "RequestURL": "/proc", "RequestCommand": "Get-Process -ProcessName PowerShell -ErrorAction SilentlyContinue | Select-Object -Property ProcessName,Id -ErrorAction SilentlyContinue" }, { "RequestType": "GET", "RequestURL": "/endpoint/status", "RequestCommand": "return 1" }, { "RequestType": "GET", "RequestURL": "/endpoint/routes", "RequestCommand": "c:/RestPS/endPoints/GET/Invoke-GetRoutes.ps1" }, { "RequestType": "GET", "RequestURL": "/process", "RequestCommand": "c:/RestPS/endPoints/GET/Invoke-GetProcess.ps1" }, { "RequestType": "PUT", "RequestURL": "/Service", "RequestCommand": "c:/RestPS/endPoints/PUT/Invoke-GetProcess.ps1" }, { "RequestType": "POST", "RequestURL": "/data", "RequestCommand": "c:/RestPS/endPoints/POST/Invoke-GetProcess.ps1" }, { "RequestType": "DELETE", "RequestURL": "/data", "RequestCommand": "c:/RestPS/endPoints/DELETE/Invoke-GetProcess.ps1" } ]

Here is my startup command

Start-RestPSListener -RoutesFilePath C:\RestPS\endpoints\RestPSRoutes.json -Port 8080

Here I create the JSON for the body

$RawReturn = @{ name = 'Powershell' } $body = $RawReturn | ConvertTo-Json

Here I run the command:

Invoke-RestMethod -UseBasicParsing -Uri http://localhost:8080/data -Method Post -Body $body

and get output:

`ProcessName Id MainWindowTitle


powershell 2736 powershell 8340 powershell 8588 powershell 10396 RestPS - http:// - Port: 8080 powershell 10880 powershell 13868 Administrator: Windows PowerShell powershell 14832`

This is the endpoint script:

`<# .DESCRIPTION This script will return the specified data to the Client. .EXAMPLE Invoke-GetProcess.ps1 -RequestArgs $RequestArgs -Body $Body .NOTES This will return data

>

param( $RequestArgs, $Body )

This section Parses the RequestArgs Parameter

if ($RequestArgs -like '&') {

Split the Argument Pairs by the '&' character

$ArgumentPairs = $RequestArgs.split('&')
$RequestObj = New-Object System.Object
foreach ($ArgumentPair in $ArgumentPairs) {
    # Split the Pair data by the '=' character
    $Property, $Value = $ArgumentPair.split('=')
    $RequestObj | Add-Member -MemberType NoteProperty -Name $Property -value $Value
}

# Edit the Area below to utilize the Values of the new Request Object
$ProcessName = $RequestObj.Name
$WindowTitle = $RequestObj.MainWindowTitle
if ($RequestObj.Name) {
    $Message = Get-Process -Name $ProcessName | Where-Object {$_.Name -like "*$ProcessName*"} | Select-Object ProcessName, Id, MainWindowTitle
}
else {
    $Message = Get-Process -Name $WindowTitle | Where-Object {$_.WindowTitle -like "*$WindowTitle*"} | Select-Object ProcessName, Id, MainWindowTitle
}

} else { $Property, $ProcessName = $RequestArgs.split("=") $Message = Get-Process -Name $ProcessName | Select-Object ProcessName, Id, MainWindowTitle }

This Section Parses the body Parameter

You will need to customize this section to consume the Json correctly for your application

$newbody = $body | ConvertFrom-Json

$ProcessName = $newbody.Name $MainWindowTitle = $newbody.MainWindowTitle

$Message = Get-Process -Name $ProcessName | Where-Object { $_.MainWindowTitle -like "$MainWindowTitle" } | Select-Object ProcessName, Id, MainWindowTitle

return $Message`

jpsider commented 1 year ago

That was some really terrible formatting by github! Basically I use the example endpoint script. No changes were made to get this working on my end.

abctaylor commented 1 year ago

Nice, however I have found a bug. I was posting to /data/ (note the trailing '/') which returns 404. So, we need to strip off trailing slashes in the request URI (probably something specific to routing logic, I imagine this is where the 404 comes from).

For Linux folks out there, the equivalent is:

abc@dev1-lon î‚° ~ î‚° curl -i -X POST -H 'Content-Type: application/json' -d '{"name": "powershell"}' http://psapi1-lon/data

HTTP/1.1 200 OK
Content-Length: 111
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 13 Jan 2023 21:50:53 GMT

{
    "ProcessName":  "powershell",
    "Id":  364,
    "MainWindowTitle":  "RestPS - http:// - Port: 80"
}%  
jpsider commented 1 year ago

Yeah, you can open an issue up for the trailing slash. One could argue that 404 is correct, but I'm fine with trimming that off.

jpsider commented 1 year ago

did you want to submit a separate issue for the trailing slash?