Hogyan készítsünk egy egyszerű REST API végpontot PowerShell-lel

Üdvözöllek a PowerShell világában! Gondoltál már arra, hogy az automatizálási szkriptjeid ne csak helyben fussanak, hanem egy központilag elérhető szolgáltatásként, egy REST API végpontként is funkcionáljanak? Ez a cikk pontosan erről szól. Megmutatjuk, hogyan hozhatsz létre egy alapvető, de működőképes REST API-t a PowerShell erejével, anélkül, hogy bonyolult keretrendszerekre vagy külső szoftverekre lenne szükséged. Készen állsz arra, hogy a PowerShell-t a következő szintre emeld?

Miért érdemes PowerShell-lel REST API-t készíteni?

A REST API-k (Representational State Transfer Application Programming Interface) a modern webes kommunikáció alapkövei. Lehetővé teszik, hogy különböző alkalmazások szabványos módon kommunikáljanak egymással HTTP protokollon keresztül. Gondolj csak bele: egy webes felület, egy mobil app, vagy akár egy másik szkript is lekérdezhet adatokat, vagy indíthat folyamatokat a PowerShell API-don keresztül.

De miért pont PowerShell? Nos, ha már otthonosan mozogsz a Windows környezetben, ismered a PowerShell parancssorát és szkriptelési képességeit, akkor logikus lépés, hogy ezt a tudásodat API fejlesztésre is használd. Különösen hasznos lehet, ha:

  • Gyorsan szükséged van egy belső, egyszerű API-ra.
  • Már meglévő PowerShell szkriptjeidet szeretnéd elérhetővé tenni más rendszerek számára.
  • Automatizálási feladatokat szeretnél távolról, HTTP kérésekkel indítani.
  • Nincs szükséged egy komplex, nagy teljesítményű webes keretrendszerre (pl. ASP.NET Core).

Fontos megjegyezni, hogy az itt bemutatott megoldás egy egyszerű REST API, mely demonstrációs és kisebb belső célokra tökéletes. Nagyobb, éles környezetben futó rendszerekhez valószínűleg robusztusabb megoldásokra (pl. ASP.NET Core, Node.js express) lesz szükség.

Előkészületek: Amire szükséged lesz

Mielőtt belevágnánk, győződj meg róla, hogy a következő eszközök rendelkezésedre állnak:

  • PowerShell 7.x vagy újabb: Bár az elvek a Windows PowerShell-ben is működnek, a PowerShell 7+ modernabb, platformfüggetlenebb, és számos fejlesztést tartalmaz, ami megkönnyíti a munkát. Letöltheted a GitHubról vagy a Microsoft Store-ból.
  • Alapvető PowerShell ismeretek: Változók, függvények, ciklusok, feltételes utasítások használata.
  • HTTP és JSON alapismeretek: Nem kell szakértőnek lenned, de jó, ha tudod, mi az a GET, POST kérés, és hogyan néz ki egy JSON adatstruktúra.
  • Adminisztrátori jogosultságok: Az HttpListener objektumhoz, amit használni fogunk, bizonyos portokon történő figyeléshez adminisztrátori jogosultság szükséges lehet a Windows rendszereken.

A Szív: HttpListener objektum a PowerShell-ben

Ahhoz, hogy a PowerShell szkriptünk HTTP kéréseket fogadhasson, egy „hallgatóra” van szükségünk. Ezt a .NET keretrendszer beépített System.Net.HttpListener osztályával tudjuk megtenni, amelyet a PowerShell könnyedén elér. Ez az osztály lehetővé teszi, hogy a szkriptünk egy megadott URL-en és porton figyelje a bejövő kéréseket.

Íme az alapvető lépések a HttpListener használatához:

  1. Létrehozás: Példányosítjuk az HttpListener osztályt.
  2. Prefixek hozzáadása: Megadjuk, mely URL-eket figyelje a hallgató. Fontos, hogy ezek a prefixek „/” jellel végződjenek.
  3. Indítás: Elindítjuk a hallgatót.
  4. Kérések fogadása: Egy hurokban várunk a bejövő kérésekre.
  5. Válasz küldése: Feldolgozzuk a kérést, és visszaküldünk egy választ.
  6. Leállítás: Tisztességesen leállítjuk a hallgatót.

Lépésről lépésre: Egy egyszerű PowerShell REST API felépítése

1. Az API előkészítése és konfigurációja

Először is, definiáljunk néhány alapvető változót a konfigurációhoz:


# Cikk: Hogyan készítsünk egy egyszerű REST API végpontot PowerShell-lel
# API konfiguráció
$Port = 8080
$Prefix = "http://localhost:$Port/"
$Listener = New-Object System.Net.HttpListener

# Prefix hozzáadása a hallgatóhoz
try {
    $Listener.Prefixes.Add($Prefix)
    Write-Host "HTTP hallgató elindítva a következő címen: $($Prefix)" -ForegroundColor Green
}
catch {
    Write-Host "Hiba a prefix hozzáadásakor vagy a hallgató indításakor." -ForegroundColor Red
    Write-Host "Lehetséges okok: adminisztrátori jogosultság hiánya, vagy a port foglalt." -ForegroundColor Red
    Write-Host $_.Exception.Message -ForegroundColor Red
    exit 1
}

# Függvény a JSON adatok küldéséhez
function Send-JsonResponse {
    param(
        [Parameter(Mandatory=$true)]
        [PSObject]$Data,
        [Parameter(Mandatory=$true)]
        [System.Net.HttpListenerResponse]$Response,
        [int]$StatusCode = 200,
        [string]$ContentType = "application/json"
    )
    $Response.StatusCode = $StatusCode
    $Response.ContentType = $ContentType
    $JsonOutput = $Data | ConvertTo-Json -Compress -Depth 10
    $Buffer = [System.Text.Encoding]::UTF8.GetBytes($JsonOutput)
    $Response.ContentLength64 = $Buffer.Length
    $Response.OutputStream.Write($Buffer, 0, $Buffer.Length)
    $Response.OutputStream.Close()
}

# Függvény a hiba válasz küldéséhez
function Send-ErrorResponse {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Message,
        [Parameter(Mandatory=$true)]
        [System.Net.HttpListenerResponse]$Response,
        [int]$StatusCode = 500
    )
    $ErrorData = @{
        Error = $Message
        Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
    }
    Send-JsonResponse -Data $ErrorData -Response $Response -StatusCode $StatusCode
}

2. Példa végpontok definiálása

Most definiáljunk néhány függvényt, amelyek a különböző API végpontjaink logikáját valósítják meg. Ezek lesznek azok a „metódusok”, amiket az API hívásokkal elérhetünk.


# Függvény egy GET kérés kezelésére: Rendszerinformációk lekérése
function Handle-SystemInfoRequest {
    param(
        [System.Net.HttpListenerRequest]$Request,
        [System.Net.HttpListenerResponse]$Response
    )
    Write-Host "GET /api/systeminfo kérés érkezett." -ForegroundColor Cyan
    try {
        $SystemInfo = @{
            ComputerName = $env:COMPUTERNAME
            OSVersion = (Get-ComputerInfo | Select-Object OsName, OsVersion).OsName
            PowerShellVersion = $PSVersionTable.PSVersion.ToString()
            CurrentTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
            UpTime = (Get-CimInstance Win32_OperatingSystem | Select-Object @{N='UpTime';E={New-TimeSpan -Start $_.LastBootUpTime -End (Get-Date)}}).UpTime.ToString()
        }
        Send-JsonResponse -Data $SystemInfo -Response $Response -StatusCode 200
        Write-Host "Válasz elküldve: Rendszerinformációk." -ForegroundColor Green
    }
    catch {
        Send-ErrorResponse -Message "Hiba a rendszerinformációk lekérésekor: $($_.Exception.Message)" -Response $Response -StatusCode 500
        Write-Host "Hiba a rendszerinformációk lekérésekor." -ForegroundColor Red
    }
}

# Függvény egy POST kérés kezelésére: Üzenet fogadása
function Handle-MessageRequest {
    param(
        [System.Net.HttpListenerRequest]$Request,
        [System.Net.HttpListenerResponse]$Response
    )
    Write-Host "POST /api/message kérés érkezett." -ForegroundColor Cyan
    try {
        # Kérés törzsének olvasása
        $Reader = New-Object System.IO.StreamReader($Request.InputStream, $Request.ContentEncoding)
        $RequestBody = $Reader.ReadToEnd()
        $Reader.Close()

        if ($RequestBody) {
            Write-Host "Kérés törzse: $($RequestBody)" -ForegroundColor DarkGray
            # JSON feldolgozása
            $ReceivedData = $RequestBody | ConvertFrom-Json -ErrorAction Stop

            if ($ReceivedData.Message) {
                Write-Host "Üzenet fogadva: $($ReceivedData.Message)" -ForegroundColor Yellow
                $ResponseData = @{
                    Status = "Siker"
                    ReceivedMessage = $ReceivedData.Message
                    Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
                }
                Send-JsonResponse -Data $ResponseData -Response $Response -StatusCode 200
                Write-Host "Válasz elküldve: Üzenet sikeresen fogadva." -ForegroundColor Green
            }
            else {
                Send-ErrorResponse -Message "Érvénytelen JSON formátum vagy hiányzó 'Message' mező." -Response $Response -StatusCode 400
                Write-Host "Hiba: Hiányzó 'Message' mező." -ForegroundColor Red
            }
        }
        else {
            Send-ErrorResponse -Message "Üres kérés törzs." -Response $Response -StatusCode 400
            Write-Host "Hiba: Üres kérés törzs." -ForegroundColor Red
        }
    }
    catch {
        Send-ErrorResponse -Message "Hiba az üzenet feldolgozásakor: $($_.Exception.Message)" -Response $Response -StatusCode 400
        Write-Host "Hiba az üzenet feldolgozásakor." -ForegroundColor Red
    }
}

# Függvény egy nem létező végpont kezelésére
function Handle-NotFoundRequest {
    param(
        [System.Net.HttpListenerRequest]$Request,
        [System.Net.HttpListenerResponse]$Response
    )
    Write-Host "Nem található végpont: $($Request.Url.AbsolutePath)" -ForegroundColor Yellow
    Send-ErrorResponse -Message "A kért végpont nem található." -Response $Response -StatusCode 404
}

# Függvény egy nem támogatott HTTP metódus kezelésére
function Handle-MethodNotAllowed {
    param(
        [System.Net.HttpListenerRequest]$Request,
        [System.Net.HttpListenerResponse]$Response
    )
    Write-Host "Nem támogatott HTTP metódus: $($Request.HttpMethod)" -ForegroundColor Yellow
    Send-ErrorResponse -Message "Ez a HTTP metódus nem engedélyezett ezen a végponton." -Response $Response -StatusCode 405
}

3. A fő ciklus: Kérések kezelése

Ez a rész a PowerShell API szívét képezi. Itt indítjuk el a hallgatót, és egy végtelen ciklusban várjuk a bejövő kéréseket. Minden kérést feldolgozunk a megfelelő függvény segítségével.


# Indítsuk el a hallgatót
$Listener.Start()
Write-Host "API hallgató sikeresen elindult. Várakozás kérésekre..." -ForegroundColor Green

# Kéréskezelő ciklus
while ($true) {
    try {
        # Kérés fogadása (blokkoló hívás)
        $Context = $Listener.GetContext()
        $Request = $Context.Request
        $Response = $Context.Response

        $AbsolutePath = $Request.Url.AbsolutePath.ToLower()
        $HttpMethod = $Request.HttpMethod.ToUpper()

        Write-Host "`n----- Új kérés érkezett -----`nURL: $($Request.Url)`nMetódus: $($HttpMethod)" -ForegroundColor White

        switch ($AbsolutePath) {
            "/api/systeminfo" {
                if ($HttpMethod -eq "GET") {
                    Handle-SystemInfoRequest -Request $Request -Response $Response
                }
                else {
                    Handle-MethodNotAllowed -Request $Request -Response $Response
                }
            }
            "/api/message" {
                if ($HttpMethod -eq "POST") {
                    Handle-MessageRequest -Request $Request -Response $Response
                }
                else {
                    Handle-MethodNotAllowed -Request $Request -Response $Response
                }
            }
            default {
                Handle-NotFoundRequest -Request $Request -Response $Response
            }
        }
    }
    catch {
        Write-Host "Hiba a kérésfeldolgozás során: $($_.Exception.Message)" -ForegroundColor Red
        # Ha a listener leállt vagy hiba történt, lépjünk ki a ciklusból
        if (-not $Listener.IsListening) {
            Write-Host "A hallgató leállt, kilépés a ciklusból." -ForegroundColor Red
            break
        }
    }
    finally {
        # Fontos: Minden esetben le kell zárni a response stream-et
        if ($Response) {
            $Response.Close()
        }
    }
}

# Hallgató leállítása kilépéskor (pl. Ctrl+C)
$Listener.Stop()
$Listener.Close()
Write-Host "HTTP hallgató leállítva." -ForegroundColor Green

Fontos megjegyzés az adminisztrátori jogosultságokról: Ha a szkriptet nem adminisztrátori jogosultsággal futtatod, és a port nem foglalt, akkor a $Listener.Prefixes.Add($Prefix) sor hibát dobhat. Ennek elkerülésére hozzáadhatod a prefixet a Windows HTTP szolgáltatáshoz a következő paranccsal (adminisztrátori PowerShell-ben):


netsh http add urlacl url=http://+:8080/ user=Everyone

Cseréld a user=Everyone részt a megfelelő felhasználónévre, ha szigorúbb jogosultságokat szeretnél. A +:8080 azt jelenti, hogy bármely IP-címen elérhető lesz a 8080-as porton.

Az API tesztelése

Most, hogy megvan a PowerShell REST API-d, teszteljük is le! Indítsd el a fenti szkriptet egy PowerShell ablakban adminisztrátori jogosultsággal.

1. GET kérés tesztelése

Nyiss meg egy másik PowerShell ablakot, vagy akár a böngésződet, és futtasd a következő parancsot:


Invoke-RestMethod -Uri http://localhost:8080/api/systeminfo -Method GET

A böngésződben egyszerűen beírhatod: http://localhost:8080/api/systeminfo. Látnod kell a rendszerinformációkat tartalmazó JSON választ.

2. POST kérés tesztelése

A POST kéréshez adatokat is kell küldenünk. Ehhez használhatjuk az Invoke-RestMethod parancsot:


$Body = @{ Message = "Hello API a PowerShell-ből!" } | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:8080/api/message -Method POST -Body $Body -ContentType "application/json"

Látnod kell egy válasz JSON-t, ami visszaküldi a fogadott üzenetet.

3. Hibás kérések tesztelése

Próbálj meg nem létező végpontot hívni, vagy rossz metódust használni:


# Nem létező végpont
Invoke-RestMethod -Uri http://localhost:8080/api/unknown -Method GET

# Rossz metódus a systeminfo végponton
Invoke-RestMethod -Uri http://localhost:8080/api/systeminfo -Method POST -Body "{}" -ContentType "application/json"

Látnod kell a 404 (Not Found) és 405 (Method Not Allowed) hibaüzeneteket.

További fejlesztési lehetőségek és best practice-ek

Ez egy egyszerű REST API példa, de számos módon továbbfejleszthető:

  • Aszinkron feldolgozás: A GetContext() blokkoló hívás. Nagyobb terhelés esetén a szkript egyidejűleg csak egy kérést tud kezelni. A BeginGetContext() és EndGetContext() metódusok, valamint a PowerShell jobok (Start-Job) segítségével aszinkron módon is kezelheted a kéréseket, így párhuzamosan több kérést is kiszolgálhatsz.
  • Útválasztás (Routing): A switch ($AbsolutePath) blokk elegendő egyszerű esetekre. Bonyolultabb API-k esetén érdemes lehet egy dedikált útválasztó mechanizmust (pl. reguláris kifejezésekkel) használni, ami rugalmasabban kezeli az URL-mintákat (pl. /api/users/{id}).
  • Hibakezelés és naplózás: Bővítsd a hibakezelést részletesebb naplózással (pl. Event Logba, fájlba) és értesítésekkel.
  • Biztonság: Ez a példa nem tartalmaz hitelesítést vagy engedélyezést. Éles környezetben elengedhetetlen az API biztonságának megerősítése. Gondolj API kulcsokra, OAuth2-re, vagy certifikát alapú hitelesítésre. A HttpListener támogatja az SSL/TLS-t, így https:// prefixet is használhatsz.
  • Szkript futtatása háttérben: Ha azt szeretnéd, hogy az API szolgáltatásként fusson, használhatsz PowerShell jobokat, vagy a szkriptet Windows szolgáltatásként konfigurálhatod (pl. NSSM – Non-Sucking Service Manager segítségével).
  • Konfiguráció külső fájlból: A portot és prefixet olvashatod egy konfigurációs fájlból (pl. JSON, XML), hogy könnyen módosítható legyen.
  • PowerShell modulok: Ha a logikád bonyolultabb, érdemes lehet külön PowerShell modulokba szervezni a függvényeket.

Alternatívák produkciós környezetben

Ahogy korábban említettem, ez a PowerShell REST API megoldás kiválóan alkalmas gyors prototípusokhoz, belső eszközökhöz vagy speciális automatizálási feladatokhoz. Produkciós környezetben, ahol nagy terhelés, magas rendelkezésre állás, skálázhatóság és robusztus biztonság a cél, érdemesebb olyan keretrendszereket használni, amelyek kifejezetten webes API-k építésére lettek tervezve:

  • ASP.NET Core (C#): A Microsoft modern, nagy teljesítményű, platformfüggetlen webes keretrendszere.
  • Azure Functions / AWS Lambda: Szerver nélküli megoldások, ahol a kódot események (pl. HTTP kérés) hatására futtatják, anélkül, hogy szervert kellene üzemeltetned. A PowerShell is támogatott nyelv az Azure Functions-ben.
  • Node.js (Express), Python (Flask/Django), Go, stb.: Más programozási nyelvek népszerű webes keretrendszerei, amelyek szintén kiváló választások lehetnek.

Összefoglalás

Gratulálok! Most már tudod, hogyan építs egy alapvető REST API végpontot PowerShell-lel a System.Net.HttpListener osztály segítségével. Láthattad, hogy a PowerShell nem csak szkriptek futtatására alkalmas, hanem egyszerű webes szolgáltatások létrehozására is. Ez a képesség hatalmas potenciált rejt magában az automatizálás, a rendszerfelügyelet és az integráció területén.

Ne feledd, a kód amit most írtál, egy remek kiindulási pont. Kísérletezz vele, bővítsd a funkcionalitást, és építs rá valami igazán hasznosat. A PowerShell API fejlesztés egy izgalmas út, ami új dimenziókat nyit meg a szkriptjeid számára!

Leave a Reply

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük