0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravelでアンダースコアを名前に含むヘッダを扱う

0
Posted at

問題

社内のシステムが独自ヘッダをつけてリクエストを投げてくるのですが、名前にアンダースコアが含まれている(仮にfoo_barとします)のでLaravelの普通のやり方$request->headers->get('foo_bar')では取得できませんでした。

調査

最初は「_」が問題とはわかってなくて、まず切り分けということでいろいろ調べたらこんな感じでした。

対象 foo_barヘッダの有無
WireSharkでパケットダンプ ある
$_SERVER ない
getallheaders() ある
$request->headers ない

Laravelはヘッダの取得はSymfonyの\Symfony\Component\HttpFoundation\ServerBagクラスのgetHeaders()で行っていて、これは$_SERVERから取得するようになっていたので、$_SERVERに含まれていないのが問題のようです。

また試しに別の名前のヘッダを追加したりしてみたらどうやら「_」が含まれてるとダメらしいとわかってきました。

そこで「ヘッダ名」「アンダースコア」で検索してみると、HTTPヘッダ名にアンダースコアはダメよ。が見つかりました。apacheがやっているということのようです。(確かにapache+mod_php環境でした)

とはいえ、いまさら社内システム側を変えてくれという訳にもいかず、getallheaders()ではとれるからそれでなんとかする方針にしました。

対策

$request->headers->get()しているところをgetallheaders()を使うように書き換えればとりあえず動きはするのですが、phpunitでのテストがやりにくいのでひねり出したのが以下のミドルウェアを使う方法です。

getallheaders()foo_barヘッダがみつかったら、追加してやるという仕組みです。これをグローバルミドルウェアとして登録しました。

class FooBarHeader
{
    private const HEADER_NAME = 'foo_bar';

    public function handle(Request $request, \Closure $next)
    {
        if (function_exists('getallheaders')) {
            $headers = \getallheaders();
            if (isset($headers[self::HEADER_NAME])) {
                $request->headers->add([self::HEADER_NAME => $headers[self::HEADER_NAME]]);
            }
        }

        return $next($request);
    }
}

いったん追加してしまえば通常のやり方で取得できるようになるし、通常のやり方で書いてあればテストのときに$this->withHeaders()が使えます。

おわりに

ヘッダ名には英数字と「-」以外の文字は使わないようにしましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?