使用Serveo隧道访问本地HTTP索引时遇400无效主机名错误
问题解决:Serveo隧道访问本地HTTP索引服务报400无效主机名错误
问题原因
你的本地HTTP服务器仅绑定了localhost主机地址,当通过Serveo隧道发起请求时,请求的Host头是Serveo分配的公网域名(如xxx.serveo.net),而HttpListener只接受Host为localhost的请求,因此返回HTTP Error 400. The request hostname is invalid.。
解决方案
修改Start-HttpServer函数中的监听前缀,将仅监听localhost改为监听所有网络接口,接受任意Host头的请求:
将:
$listener.Prefixes.Add("http://localhost:$Port/")
替换为:
$listener.Prefixes.Add("http://+:${Port}/")
修改后的完整代码
本地HTTP索引服务代码
function Start-HttpServer { param ( [int]$Port = 8080 ) $listener = New-Object System.Net.HttpListener # 修改监听前缀,接受所有主机的请求 $listener.Prefixes.Add("http://+:${Port}/") $listener.Start() Write-Host "HTTP-Server gestartet. Der Index wird unter http://localhost:$Port/ bereitgestellt." while ($true) { $context = $listener.GetContext() $request = $context.Request $response = $context.Response $requestedPath = $request.Url.AbsolutePath.TrimStart('/') if ([string]::IsNullOrEmpty($requestedPath)) { $localPath = "C:\" } else { $localPath = "C:\" + [System.Uri]::UnescapeDataString($requestedPath.Replace('/', '\')) } if (Test-Path $localPath) { if (Test-Path $localPath -PathType Container) { try { $items = Get-ChildItem -Path $localPath -Force $responseContent = "<html><body><h1>Index of $localPath</h1><ul>" foreach ($item in $items) { $itemPath = Join-Path -Path $localPath -ChildPath $item.Name $relativePath = "/" + ($itemPath -replace [regex]::Escape([System.IO.Path]::GetPathRoot($localPath)), "").Replace("\", "/") if ($item.PSIsContainer) { $responseContent += "<li><a href='$relativePath/'>$($item.Name)/</a></li>" } else { $responseContent += "<li><a href='$relativePath'>$($item.Name)</a></li>" } } $responseContent += "</ul></body></html>" $response.ContentType = "text/html" } catch { $responseContent = "<html><body><h1>Fehler beim Abrufen der Dateien</h1></body></html>" $response.ContentType = "text/html" } } else { try { $fileContent = [System.IO.File]::ReadAllBytes($localPath) $response.ContentType = "application/octet-stream" $fileName = [System.IO.Path]::GetFileName($localPath) $response.AddHeader("Content-Disposition", "attachment; filename=`"$fileName`"") $response.ContentLength64 = $fileContent.Length $response.OutputStream.Write($fileContent, 0, $fileContent.Length) } catch { $responseContent = "<html><body><h1>Fehler beim Abrufen der Datei</h1></body></html>" $response.ContentType = "text/html" $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseContent) $response.ContentLength64 = $buffer.Length $response.OutputStream.Write($buffer, 0, $buffer.Length) } $response.OutputStream.Close() continue } } else { $responseContent = "<html><body><h1>404 Not Found</h1></body></html>" $response.ContentType = "text/html" } $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseContent) $response.ContentLength64 = $buffer.Length $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } } # Starten des HTTP-Servers im aktuellen PowerShell-Fenster Start-HttpServer -Port 8080
Serveo隧道代码(无需修改)
function Create-ServeoTunnel { param ( [int]$LocalPort = 8080 ) # Überprüfen, ob SSH installiert ist if (-not (Get-Command ssh -ErrorAction SilentlyContinue)) { Write-Host "SSH ist nicht installiert. Bitte installieren Sie SSH mit Administratorrechten." exit 1 } # Erstellen und Starten des Serveo-Tunnels try { $processInfo = New-Object System.Diagnostics.ProcessStartInfo $processInfo.FileName = "ssh" $processInfo.Arguments = "-R 80:localhost:$LocalPort serveo.net" $processInfo.RedirectStandardOutput = $true $processInfo.UseShellExecute = $false $processInfo.CreateNoWindow = $true $serveoProcess = New-Object System.Diagnostics.Process $serveoProcess.StartInfo = $processInfo $serveoProcess.Start() | Out-Null Write-Host "Warte auf die Serveo Tunnel-URL..." $url = $null while ($serveoProcess.HasExited -eq $false) { $serveoOutput = $serveoProcess.StandardOutput.ReadLine() if ($serveoOutput -match "https://.*serveo.net") { $url = $matches[0] Write-Host "Serveo Tunnel URL: $url" break } } if ($url -eq $null) { Write-Host "Fehler: Konnte die Serveo URL nicht abrufen." } else { Write-Host "Der Tunnel wird geöffnet gehalten. Drücken Sie Strg+C, um zu beenden." # Den Tunnel geöffnet halten while ($serveoProcess.HasExited -eq $false) { Start-Sleep -Seconds 1 } } } catch { Write-Host "Fehler beim Einrichten des Serveo Tunnels: $_" } finally { if ($serveoProcess -and -not $serveoProcess.HasExited) { $serveoProcess.Kill() } } } # Aufrufen der Funktion zur Erstellung des Serveo-Tunnels Create-ServeoTunnel -LocalPort 8080
内容的提问来源于stack exchange,提问作者DxrkBlo0d
相关产品推荐
相关产品推荐

