http.server.psm1

function Start-HttpServer {
    param(
        [int]$Port = 8000,
        [string]$Root = (Get-Location),
        [switch]$Public,

        [Alias('if')][string]$IndexFile
    )

    if (-not (Get-Command Start-ThreadJob -ErrorAction SilentlyContinue)) {
        Write-Error "Start-ThreadJob is not available. Run: Install-Module ThreadJob"
        return
    }

    if ($Global:HttpServerJob -and ($Global:HttpServerJob.State -eq 'Running')) {
        Write-Host "[-] Server already running (Job ID: $($Global:HttpServerJob.Id)). Use Stop-HttpServer to stop it."
        return
    }

    $bind     = if ($Public) { "*" } else { "localhost" }
    $prefix   = "http://$bind`:$Port/"
    $rootFull = (Resolve-Path $Root).Path

    # Launch listener in background
    $job = Start-ThreadJob -Name 'PowerShellHttpServer' -ScriptBlock {
        param($prefix, $rootFull)

        # MIME type lookup
        $mime = @{
            '.html' = 'text/html';            '.htm'   = 'text/html'
            '.json' = 'application/json'
            '.js'   = 'application/javascript'
            '.css'  = 'text/css'
            '.png'  = 'image/png'
            '.jpg'  = 'image/jpeg';           '.jpeg'  = 'image/jpeg'
            '.svg'  = 'image/svg+xml'
            '.ico'  = 'image/x-icon'
        }

        $listener = [System.Net.HttpListener]::new()
        $listener.Prefixes.Add($prefix)
        $listener.Start()
        Write-Output "[+] Serving $rootFull at $prefix"

        try {
            while ($listener.IsListening) {
                $ctx = $listener.GetContext()
                $req = $ctx.Request
                $res = $ctx.Response

                # Determine requested path (default to index.html)
                $rel = $req.Url.LocalPath.TrimStart('/')
                if ([string]::IsNullOrWhiteSpace($rel)) { $rel = 'index.html' }
                $file = Join-Path $rootFull $rel

                Write-Output "[REQ] $($req.Url.LocalPath) → $file"

                if (Test-Path $file -PathType Leaf) {
                    # Serve the requested file
                    $bytes = [System.IO.File]::ReadAllBytes($file)
                    $ext   = [IO.Path]::GetExtension($file).ToLower()
                    $res.ContentType     = $mime[$ext] ? $mime[$ext] : 'application/octet-stream'
                    $res.ContentLength64 = $bytes.Length
                    $res.OutputStream.Write($bytes, 0, $bytes.Length)
                }
                else {
                    # 404 fallback
                    $msg = "404 – $rel"
                    $buf = [Text.Encoding]::UTF8.GetBytes($msg)
                    $res.StatusCode       = 404
                    $res.ContentType      = 'text/plain'
                    $res.ContentLength64  = $buf.Length
                    $res.OutputStream.Write($buf, 0, $buf.Length)
                }

                $res.OutputStream.Close()
            }
        }
        finally {
            $listener.Stop()
        }
    } -ArgumentList $prefix, $rootFull

    $Global:HttpServerJob = $job
    Start-Sleep -Milliseconds 500
    Receive-Job -Id $job.Id | Write-Host
    Write-Host "[*] Server running. Use Stop-HttpServer to stop it."
}






function Stop-HttpServer {
    $job = $Global:HttpServerJob

    if (-not $job -or $job.State -ne 'Running') {
        # Fallback: try to find the job by name
        $job = Get-Job -Name 'PowerShellHttpServer' -ErrorAction SilentlyContinue | Where-Object { $_.State -eq 'Running' }
    }

    if ($job) {
        try {
            Stop-Job $job.Id -ErrorAction SilentlyContinue
            while ((Get-Job -Id $job.Id).State -ne 'Stopped') {
                Start-Sleep -Milliseconds 100
            }
            Remove-Job $job.Id -ErrorAction SilentlyContinue
            Remove-Variable -Name HttpServerJob -Scope Global -ErrorAction SilentlyContinue
            Write-Host "[*] HTTP server stopped and cleaned up."
        } catch {
            Write-Host "[-] Error stopping job: $_"
        }
    } else {
        Write-Host "[-] No running HTTP server job found."
    }
}


Export-ModuleMember -Function Start-HttpServer, Stop-HttpServer