表題の通りです.Port forwarding などの設定ができているにもかかわらずローカルの wsl 上に Pedestal で立てたサーバだけが Windows 側からアクセスできない場合の対処法になります.
TL; DR
io.pedestal.http/create-server
の引数の map に以下の key-value を追加する:
::http/host "0.0.0.0"
環境
- OS: Windows 11 Home (version: 23H2)
- WSL: Distribution = Ubuntu 20.04 LTS
> wsl --version
WSL バージョン: 2.2.4.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.61
MSRDC バージョン: 1.2.5326
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26091.1-240325-1447.ge-release
Windows バージョン: 10.0.22631.4169
[wsl2]
localhostForwarding=True
- Clojure:
> clojure --version
Clojure CLI version 1.11.1.1413
Pedestal サーバ
プロジェクト構成
Pedestal チュートリアル に従ってプロジェクトを作成すると大体以下のようになります.
pedestal-example/
src/
hello.clj
deps.edn
(ns hello
(:require [io.pedestal.http :as http]
[io.pedestal.http.route :as route]))
(defn respond-hello [_request]
{:status 200 :body "Hello, world!"})
(def routes
(route/expand-routes
#{["/greet" :get respond-hello :route-name :greet]}))
(def service-map
{::http/routes routes
::http/type :jetty
::http/port 8080})
(defn create-server []
(http/create-server service-map))
(defn start []
(http/start (create-server)))
{:paths ["src"]
:deps {io.pedestal/pedestal.jetty {:mvn/version "0.7.0"}
org.slf4j/slf4j-simple {:mvn/version "2.0.10"}}}
実行コマンド
> clj
Clojure 1.11.1
user=> (require 'hello) (hello/start)
nil
[main] INFO org.eclipse.jetty.server.Server - jetty-11.0.20; built: 2024-01-29T21:04:22.394Z; git: 922f8dc188f7011e60d0361de585fd4ac4d63064; jvm 17.0.12+7-Ubuntu-1ubuntu220.04
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@63a875e6{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@63782ad0{HTTP/1.1, (http/1.1, h2c)}{localhost:8080}
[main] INFO org.eclipse.jetty.server.Server - Started Server@3c36f10b{STARTING}[11.0.20,sto=0] @15277ms
テスト
WSL 上で実行した場合
> curl http://localhost:8080/greet
Hello, world!
Windows 上で実行した場合(Powershell)
> curl -i -X GET "http://localhost:8080/greet"
curl: (52) Empty reply from server
エラーメッセージが Empty reply from server
となっている点に留意が必要です.
単にサーバが立ち上がっていない場合は以下のようなエラーになります.
curl: (7) Failed to connect to localhost port 8080 after 2239 ms: Couldn't connect to server
localhostForwarding が機能しているか確認
Python などで適当なサーバを立てて,Windows 側からアクセスできるか調べます.
> python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
> # powershell
> curl -i -X GET "http://localhost:8080"
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.8.10
Date: Sun, 22 Sep 2024 13:04:04 GMT
Content-type: text/html; charset=utf-8
Content-Length: 647
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".clj-kondo/">.clj-kondo/</a></li>
<li><a href=".cpcache/">.cpcache/</a></li>
<li><a href=".lsp/">.lsp/</a></li>
<li><a href="deps.edn">deps.edn</a></li>
<li><a href="hello.js">hello.js</a></li>
<li><a href="node_modules/">node_modules/</a></li>
<li><a href="package-lock.json">package-lock.json</a></li>
<li><a href="src/">src/</a></li>
</ul>
<hr>
</body>
</html>
正常にアクセスできています.
もしここで Python の方のサーバにもアクセスできないのであれば WSL の localhostForwarding が上手くいっていない可能性があり,.wslconfig
に localhostForwarding=true
と追記(したのち wsl を再起動)するなどして localhostForwarding を有効化します.
解決法
io.pedestal.http/create-service
の引数の map に ::http/host "0.0.0.0"
という key-value pair を追加することで Windows 側からもアクセスできるようになります.
(def service-map
{
+ ::http/host "0.0.0.0"
::http/routes routes
::http/type :jetty
::http/port 8080})
(defn create-server []
(http/create-server service-map))
参考: https://stackoverflow.com/questions/69034828/clojure-pedestal-windows-wsl2-browsers-not-rendering
結論
普通に localhostForwarding の問題だと思い込んで数時間スタックしたので,初めて使うフレームワークでこの手の問題が起こったときは信頼できる簡易サーバを別途立てて検証するのが大事という教訓を得ました.