それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

laravel の api ルートを叩いてもloginページやHTMLが帰ってきてjson以外になってしまう場合

TL;DR

HTTPリクエストのヘッダに、 Accept: text/json が抜けている可能性が高い。

Laravelのレスポンスが login になる場合。

api で auth を入れているところへリクエスト投げつける。

HTMLのログインが帰ってくる。

実例

curl -H 'Content-Type: application/json' -F file='@/Users/takuya/Pictures/Dh6PcyQUYAEzhKp.jpg' http://127.0.0.1:8000/api/user/1/images/ 

* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> POST /api/user/1/images/ HTTP/1.1
> Host: 127.0.0.1:8000
> Accept: */*
> Accept-Encoding: gzip, deflate, sdch
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36
> X-Config-File: ~/.curlrc
> Content-Length: 37112
> Content-Type: application/json; boundary=------------------------f7fa3a50954906f3
> Expect: 100-continue
>
* Done waiting for 100-continue
  0 37112    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0} [37112 bytes data]
* We are completely uploaded and fine
< HTTP/1.1 302 Found
< Host: 127.0.0.1:8000
< Date: Tue, 28 May 2019 14:57:15 +0000
< Connection: close
< X-Powered-By: PHP/7.3.4
< Cache-Control: no-cache, private
< Date: Tue, 28 May 2019 14:57:15 GMT
< Location: http://127.0.0.1:8000/login
< X-RateLimit-Limit: 60
< X-RateLimit-Remaining: 59
< Content-Type: text/html; charset=UTF-8
<
{ [352 bytes data]
100 37464    0   352  100 37112    272  28724  0:00:01  0:00:01 --:--:-- 28996
* Closing connection 0
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url=http://127.0.0.1:8000/login" />

        <title>Redirecting to http://127.0.0.1:8000/login</title>
    </head>
    <body>
        Redirecting to <a href="http://127.0.0.1:8000/login">http://127.0.0.1:8000/login</a>.

同一ページに Accept-JSONを併せて送りつけた場合。

HTTPのヘッダにAcceptを入れると、401 がとJSONが返ってくる。

takuya@$ curl-json -H 'Content-Type: application/json' -F file='@/Users/takuya/Pictures/Dh6PcyQUYAEzhKp.jpg' http://127.0.0.1:8000/api/user/1/images/ 

> POST /api/user/1/images/ HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/7.65.0-DEV
> Accept: text/json
> X-Config-File: ~/.curlrc-json
> Content-Length: 37112
> Content-Type: text/json; boundary=------------------------4610ff915435cd7f
> Expect: 100-continue
>
* Done waiting for 100-continue
} [37112 bytes data]
* We are completely uploaded and fine
< HTTP/1.1 401 Unauthorized
< Host: 127.0.0.1:8000
< Date: Tue, 28 May 2019 14:54:59 +0000
< Connection: close
< X-Powered-By: PHP/7.3.4
< Cache-Control: no-cache, private
< Date: Tue, 28 May 2019 14:54:59 GMT
< Content-Type: application/json
< X-RateLimit-Limit: 60
< X-RateLimit-Remaining: 58
<
{ [30 bytes data]
* Closing connection 0
{"message":"Unauthenticated."}

laravel のAPIにリクエストを送付するときは

リクエストヘッダのAccept(クライアントが受け取りたいMIME形式の指定)でJSONを指定する必要がある。

Accept: text/json

これは、どこで定義されているのか

Accept をみてMIMEや認証は、どこのメソッドで定義されているのか。

vendor/laravel/framework/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php#expectsJson
<?php
public function expectsJson()
    {
        return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
    }

ここでリクエストのヘッダを見ている。HTTP/Requestで使える。

参考資料

https://github.com/laravel/framework/blob/5.8//src/Illuminate/Http/Concerns/InteractsWithContentTypes.php#L42