WordPress.org の Plugin API は、request[slug]= のように、URL のクエリに角かっこを使います。この URL を curl にそのまま渡すと、シェルと curl のどちらかが角かっこを読んでしまい、リクエストが届かないか、届いても中身が足りなくなります。
curl 8.5.0、zsh 5.9、bash 5.2 で、手元に立てた HTTP サーバーに向けて試しました。サーバーのログで、実際に届いたリクエストも見ています。
| 書き方 | zsh | bash |
|---|---|---|
| URL を引用符で囲まない |
no matches found で、curl が動かない |
curl が bad range in URL で止まる |
引用符で囲まない、& を含む URL |
上と同じ | & から後ろが届かない。エラーも出ない |
| 引用符で囲む | curl が bad range in URL で止まる |
同じ |
引用符で囲み、curl -g
|
届く | 届く |
角かっこを %5B %5D にする |
届く | 届く |
引用符で囲むと、シェルの問題は消えます。それでも curl が角かっこを読むので、-g か、角かっこのエンコードが要ります。
先に断っておくと、zsh が一致するファイルのないグロブをエラーにすること(NOMATCH)も、curl が URL の [ ] と { } を範囲指定として読み、-g(--globoff)で止められることも、それぞれのマニュアルに書かれています。ここで書くのは、WordPress.org の API の URL で、その2つが重なったときに何が起きるかを、1つずつ確かめた結果です。
zsh:curl が動く前に止まる
zsh は、? と [slug] をファイル名のパターンとして読みます。一致するファイルがないので、curl を動かす前にエラーにします。
$ curl -s http://127.0.0.1:18900/x?request[slug]=a
zsh:1: no matches found: http://127.0.0.1:18900/x?request[slug]=a
URL に & が入っていると、そこでコマンドが切れて、後ろの request[slug]=rapls-sitemap を変数への代入として読もうとし、もう1つエラーが出ました。
zsh:1: no matches found: http://127.0.0.1:18900/plugins/info/1.2/?action=plugin_information
zsh:1: request: assignment to invalid subscript range
bash:エラーなしで、半分だけ届く
bash は、一致するファイルがないパターンを、そのまま残して渡します。& を含まない URL なら、curl まで届いて、curl のほうで止まります(次の節)。
困るのは、& を含む URL です。
curl -sS -o /dev/null http://127.0.0.1:18902/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap
bash は & でコマンドを切り、curl を後ろで動かします。サーバーに届いたのは、& の手前まででした。
"GET /plugins/info/1.2/?action=plugin_information HTTP/1.1"
request[slug]=rapls-sitemap のほうは、bash の配列への代入として、黙って実行されていました。
$ declare -p request
declare -a request=([0]="rapls-sitemap")
エラーは1行も出ません。API には、どのプラグインかを伝える slug が届いていないので、返ってくる中身は、頼んだものとは別物になります。
curl:引用符で囲んでも止まる
URL を引用符で囲めば、シェルは角かっこにも & にも触りません。それでも、今度は curl が [slug] を範囲指定([1-10] のような)として読み、止まります。
$ curl -sS -o /dev/null 'http://127.0.0.1:18900/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap'
curl: (3) bad range in URL position 76:
http://127.0.0.1:18900/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap
^
-s だけを付けていると、このエラーも表示されず、終了コード 3 で終わるだけです。-sS にしておくと、エラーだけは表示されます。
zsh の noglob を前に付けても、シェルの展開が止まるだけで、curl のほうは同じエラーでした。
届く書き方
引用符で囲んで、-g を付けます。
curl -g -sS 'https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap'
角かっこをエンコードしても届きます。
curl -sS 'https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request%5Bslug%5D=rapls-sitemap'
-G と --data-urlencode でクエリを組み立てる方法もあります。この場合、curl は渡したデータを範囲指定として読まないので、角かっこはそのまま届きました。
curl -sS -G https://api.wordpress.org/plugins/info/1.2/ \
--data-urlencode 'action=plugin_information' \
--data-urlencode 'request[slug]=rapls-sitemap'
サーバーのログでは、-g を付けた書き方で、&request[slug]=rapls-sitemap まで届いていました。
"GET /plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap HTTP/1.1"
角かっこの入った URL を curl に渡すとき
- URL は、必ず引用符で囲む。zsh はエラーで止まり、bash は
&で黙って切る - 引用符で囲んでも、curl が
[ ]を範囲指定として読む。-gを付けるか、%5B%5Dにする -
-sだけだと、curl のエラーが見えない。-sSにする - クエリが長いなら、
-Gと--data-urlencodeで組み立てる
あなたのスクリプトの curl は、角かっこの入った URL を、どの書き方で渡していますか。
手元で試すコマンド
Python の HTTP サーバーを立てて、届いたリクエストをログで見ます。
python3 -m http.server 18902 > hs.log 2>&1 &
bash -c 'curl -sS -o /dev/null http://127.0.0.1:18902/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap; sleep 1'
curl -g -sS -o /dev/null 'http://127.0.0.1:18902/plugins/info/1.2/?action=plugin_information&request[slug]=rapls-sitemap'
grep GET hs.log
ふだんはraplsworks.comで、WordPressプラグイン開発やClaude Codeまわりのことを書いています。
https://raplsworks.com/