为何我复制的PowerShell HTTP服务器代码无法正常运行?
解决PowerShell简易Web服务器访问index.html出现404的问题
你的问题很清晰——运行这段PowerShell代码搭建Web服务器后,访问http://localhost:8080/index.html出现404错误,核心原因是这段代码根本没处理/index.html的请求,也没有读取本地文件的逻辑,我来给你拆解问题和修复方案:
代码问题分析
原代码的核心逻辑是通过$htmlcontents哈希表硬编码匹配请求路径:
- 只预设了
GET /(根路径)和GET /services两个请求的返回内容 - 当收到的请求不在这个哈希表里时,直接返回404错误
- 完全没有读取本地
index.html文件的逻辑,哪怕你把代码放在有这个文件的目录里也无法识别
修复方案
根据你的需求,我提供两种修复思路,你可以根据场景选择:
方案1:仅支持根路径和/index.html返回本地index.html
修改$htmlcontents哈希表,添加对GET /index.html的映射,同时读取本地文件内容:
# enter this URL to reach PowerShell’s web server $url = 'http://localhost:8080/' # HTML content for some URLs entered by the user $htmlcontents = @{ 'GET /' = Get-Content index.html -Raw # 读取本地index.html文件作为根路径返回 'GET /index.html' = Get-Content index.html -Raw # 匹配/index.html请求 'GET /services' = Get-Service | ConvertTo-Html } # start web server $listener = New-Object System.Net.HttpListener $listener.Prefixes.Add($url) $listener.Start() try { while ($listener.IsListening) { # process received request $context = $listener.GetContext() $Request = $context.Request $Response = $context.Response $received = '{0} {1}' -f $Request.httpmethod, $Request.url.localpath # is there HTML content for this URL? $html = $htmlcontents[$received] if ($html -eq $null) { $Response.statuscode = 404 $html = 'Oops, the page is not available!' } # return the HTML to the caller $buffer = [Text.Encoding]::UTF8.GetBytes($html) $Response.ContentLength64 = $buffer.length $Response.OutputStream.Write($buffer, 0, $buffer.length) $Response.Close() } } finally { $listener.Stop() }
方案2:支持任意静态文件访问(更灵活)
如果想让服务器能处理更多静态文件(比如css、js、其他html),可以修改逻辑,自动识别请求路径对应的本地文件:
# enter this URL to reach PowerShell’s web server $url = 'http://localhost:8080/' $webRoot = Get-Location # 当前目录作为网站根目录 # start web server $listener = New-Object System.Net.HttpListener $listener.Prefixes.Add($url) $listener.Start() try { while ($listener.IsListening) { # process received request $context = $listener.GetContext() $Request = $context.Request $Response = $context.Response $requestPath = $Request.url.localpath # 根路径默认返回index.html if ($requestPath -eq '/') { $requestPath = '/index.html' } # 构建本地文件路径,防止路径遍历攻击 $localPath = Join-Path -Path $webRoot -ChildPath $requestPath.TrimStart('/') $localPath = [System.IO.Path]::GetFullPath($localPath) # 检查文件是否存在且在网站根目录内 if ($localPath.StartsWith($webRoot) -and (Test-Path $localPath -PathType Leaf)) { try { $content = Get-Content $localPath -Raw $buffer = [Text.Encoding]::UTF8.GetBytes($content) $Response.ContentLength64 = $buffer.length $Response.OutputStream.Write($buffer, 0, $buffer.length) } catch { $Response.statuscode = 500 $html = 'Error reading file!' $buffer = [Text.Encoding]::UTF8.GetBytes($html) $Response.ContentLength64 = $buffer.length $Response.OutputStream.Write($buffer, 0, $buffer.length) } } else { # 保留services特殊请求的处理 if ($Request.httpmethod -eq 'GET' -and $requestPath -eq '/services') { $html = Get-Service | ConvertTo-Html $buffer = [Text.Encoding]::UTF8.GetBytes($html) $Response.ContentLength64 = $buffer.length $Response.OutputStream.Write($buffer, 0, $buffer.length) } else { $Response.statuscode = 404 $html = 'Oops, the page is not available!' $buffer = [Text.Encoding]::UTF8.GetBytes($html) $Response.ContentLength64 = $buffer.length $Response.OutputStream.Write($buffer, 0, $buffer.length) } } $Response.Close() } } finally { $listener.Stop() }
这个方案不仅能返回index.html,还能处理其他静态文件,同时加入了路径遍历防护,更安全实用。
内容的提问来源于stack exchange,提问作者user310291
相关产品推荐
相关产品推荐

