🐚

PowershellでhttpServer的なモノを作る(2)

2023/05/11に公開

前の記事PowershellでhttpServer的なモノを作る(1)で作成したhttpListener01.ps1に大きな問題点が…それは終了できないんですね。無限ループです。

 while ($true) {
       ......
    }

少し直してこうします。

$continue = $true
 while ($continue){  
   ......
    }

コンソールにコントロールCで、キーを割り込めるようにします。continueにfalseを書き込んでループを抜けます。

if ([console]::KeyAvailable) {
            $key = [system.console]::readkey()
            if (($key.modifiers -band [consolemodifiers]"control") -and ($key.key -eq "C")) {
                $continue = $flase
                Write-Host "Terminating..."
            }
        }

そのままhttpListener01.ps1に割り込みを入れるだけでもいいのですが、どうせなら少し改造してみます。

htmlファイルを読み込み、htmlを表示させます。普通にGet-contentでhttpListener02.ps1と同じディレクトリに配置します。index.htmlはhtmlであればなんでもよいですがutf-8で保存します。サンプルのhtmlを用意します。

$html = Get-Content -Path "index.html" -Encoding UTF8
index.html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <p>日本語で表示します</p>
    </body>
</html>

次はindex.htmlのmime-typeの登録ですが、少し汎用性のある登録方法を使います。
mime-typeを自動的に取得します。これはアセンブリが必要になりますので
using assembly system.Webと宣言をして使います。

using assembly system.Web
[System.Web.MimeMapping]::GetMimeMapping("index.html")

そうすると$Context.Response.ContentTypeで取得するとtext/htmlを返却してくれます。
これから画像等が多くなるとmime-type登録がたいへんになるので、使えるものを使って登録を省力します。これによって、同じディレクトリにあるindex.htmlを読み、mime-typeを判定し、実体のhtmlの中身、日本語で表示しますをブラウザに表示します。そしてブラウザで表示しているところをコンソールでCTL+Cを押しサーバを停止します。やってみましょう。

httpListener02.ps1
using assembly system.Web
$listener = New-Object Net.HttpListener
$listener.Prefixes.Add("http://+:8888/")
$continue = $true
Write-Host "Server is running at port 8888"

try {  
    while ($continue){  
    if (!$listener.IsListening){
        $listener.Start() 
        $context = $listener.GetContext()
        $context.Response.StatusCode = 200 
        $html = Get-Content -Path "index.html" -Encoding UTF8
        $content = [System.Text.Encoding]::UTF8.GetBytes($html)
        $context.Response.ContentType = [System.Web.MimeMapping]::GetMimeMapping("index.html")
        Write-Host $Context.Response.ContentType
        $response = $context.Response  
        $response.ContentLength64 = $content.Length
        $response.OutputStream.Write($content, 0, $content.Length)
        $response.OutputStream.Close()
        $response.Close()

    if ([console]::KeyAvailable) {
            $key = [system.console]::readkey()
            if (($key.modifiers -band [consolemodifiers]"control") -and ($key.key -eq "C")) {
                $continue = $flase
                Write-Host "Terminating..."
            }
        }

    }  else {$listener.Stop()}
}
}
catch {
    Write-Error($_.Exception)
}
finally{
    $listener.Close()
    Write-Host "Server is Terminated"
}
PS C:\...  .\httplistener02.ps1
Server is running at port 8888

ブラウザをリロードする度に、mime-type text/htmlが表示されコンソールでCTL+Cを押すとServer is Teminatedが表示されサーバーが停止しコンソールが停止します

Server is running at port 8888
text/html
text/html
text/html
text/html
Server is Terminated

httpのサーバーの起動と停止の基本ができました。

Discussion