4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PowerShellでHTTPサーバを書いた

Last updated at Posted at 2021-09-07

感想

functionにC#クラスなどのオブジェクトを参照渡しして値を取り出そうとしたら、
引数名.Value.メソッド名と書かないといけないことに気付き、脳を破壊された。

function 関数名([ref]$引数名) { $引数名.Value.ByeByePowerShell }

ソースコード

server.ps1
# ポート番号
$Port = "8080"
# URL
$url = "http://localhost:" + $Port + "/"
# localhostに繋げない環境への対応
# $url = "http://+:" + $Port + "/Temporary_Listen_Addresses/"
# リクエストがルート(/)の場合、呼び出されるファイル
$HomePage = "index.html"
# コンテンツタイプ辞書(ブラウザに送るデータの種類)
$ContentType = @{
    "css" = "text/css"
    "js" = "application/javascript"
    "json" = "application/json"
    "html" = "text/html"
    "pdf" = "application/pdf"
    "txt" = "text/plain"
    "jpg" = "image/jpeg"
    "png" = "image/png"
    "*" = "application/octet-stream"
}

# リクエストがなくなるまでファイル送信を行う
function fileSendToClient([ref]$response, $fileName) {
    $currentDirectory = Convert-Path .
    $fullPath = Join-Path $currentDirectory $fileName
    if ([IO.File]::Exists($fullPath)) {
        $extension = $(Get-Item $fullPath).Extension.Replace(".", "")
        if ($ContentType.ContainsKey($extension)) {
            $response.Value.ContentType = $ContentType[$extension]
        } else {
            $response.Value.ContentType = $ContentType["*"]
        }
        $response.Value.ContentType += ";charset=UTF-8"
        $content = [IO.File]::ReadAllBytes($fullPath)
        $response.Value.ContentLength64 = $content.Length
        $output = $response.Value.OutputStream
        $output.Write($content, 0, $content.Length)
        $output.Close()
    } else {
        $response.Value.StatusCode = 404
    }
}

function main {
    $listener = New-Object Net.HttpListener
    $listener.Prefixes.Add($url)
    Write-Output "* Running on $url (Press CTRL+C to quit)"

    try {
        $listener.Start()
        while ($listener.IsListening) {
            $task = $listener.GetContextAsync()
            # ブロッキングでCtrl+Cが効かなくなることへの対策
            while ($task.AsyncWaitHandle.WaitOne(500) -eq $false) {}
            $context = $task.GetAwaiter().GetResult()

            If ($page = $context.Request.Url.LocalPath -eq "/") {
                # 最初のページ送信
                $page = $HomePage
            } else {
                # CSS,Javascriptなどのファイルが要求された場合
                $page = $context.Request.RawUrl
            }
            $response = $context.Response
            If ($context.Request.IsLocal) {
                # ローカルPCからの接続の場合
                fileSendToClient ([ref]$response) $page
            }
            Write-Output $context.Request.RawUrl
            Write-Output $context.Response
            $response.Close()
        }
    } catch {
        Write-Error($_.Exception)
    } finally {
        $listener.Close()
    }
}

main
exit

参考にさせていただいた記事

  1. PowerShellでHTTPサーバー的なものを作る
  2. 管理者権限のないプレーンなWindowsでWebサーバを立てる戦い
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?