You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:59:50