【Flutter】APIリクエストのstatus code of 500が出た場合

## はじめに

先日、現場で動作確認をしていたところエラーが出てサーバーからデータを取得することができませんでした。
この場合、呼び出し側であるアプリ側の不具合なのかサーバー側の不具合なのかを調査する必要があります。

今回はその調査方法とバックエンドエンジニアさんへの調査依頼の仕方を教えてもらったので、
簡単にまとめていこうと思います。

尚、エディターはVSCodeを使用しています。

### 記事の対象者

- Flutter初学者
- APIでの不具合調査を学びたい方

### 記事を執筆時点での筆者の環境

- macOS 14.3.1
- Xcode 15.2
- Swift 5.9
- iPhone11 pro ⇒ iOS 17.2.1
- Flutter 3.19.0
- Dart 3.3.0
- Pixel 7a ⇒ Android

## 1. 例題
今回は例題としてQiitaAPIでログインした**ユーザーの情報を取得する処理**を検証していきます。
以前記事でも挙げていたサンプルアプリを使います。

### 記事

https://qiita.com/Harx02663971/items/e83bf2c368a5dabae238

### Github

https://github.com/HaruhikoMotokawa/flutter_web_auth_2_sample

### 対象の処理


```lib/plain/state/plain_user_notifier.dart
  /// ログイン中のユーザーデータを要求する
  Future<void> fetchUserData(String accessToken) async {
    const host = 'qiita.com';
    const endPoint = '/api/v2/authenticated_user';
    final url = Uri.https(host, endPoint).toString();
    // ユーザー情報を要求する場合にはヘッダーにアクセストークンを含める
    final headers = {'Authorization': 'Bearer $accessToken'};
    try {
      // Dioを使ってhttpsで要求する
      final dio = Dio();
      final response = await dio.get(
        url,
        options: Options(headers: headers),
      );
      // JSONで扱えるデータの元を取り出す
      final json = response.data;
      // Dartで扱える[User]オブジェクトに変換
      final user = User.fromJson(json);
      // 状態に保存する
      state = AsyncValue.data(user);
    } catch (e, s) {
      state = AsyncValue.error(e, s);
    }
  }
```

## 2. DevToolsのNetworkPageを起動する

FlutterのDevToolsの機能を使って、さまざまな状態を確認することができます。
そのうちの一つのNetworkPageがあります。
NetworkPageではリクエストの詳細、ステータスコード、レスポンス内容など細かく確認できます。

https://docs.flutter.dev/tools/devtools/network

### 2-1. エミュレータでデバック実行

まずはいつものようにエミュレーターを立ち上げ、デバックを実行します

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/153491cd-987f-2b2f-9cf4-a16388780c16.png">


### 2-2. コマンドパレッドを立ち上げる

ショートカットキーは`⌘ + shift + P`

![スクリーンショット 2024-05-03 15.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/2ff2450a-8c10-ff81-8027-38f27d551fc7.png)

### 2-3. 検索して起動

OpenDevToolsを検索

![スクリーンショット 2024-05-03 15.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/bb9eebd2-ee9e-a436-a5eb-cea1d283f0f1.png)


NetworkPageを選択

![スクリーンショット 2024-05-03 15.50.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/2787a177-ff4f-5d37-0880-9fb12f56c97d.png)


するとエディターの右側に以下の画面が起動します

![スクリーンショット 2024-05-03 15.57.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/56c2322b-6dee-3b95-3e84-83acd2603c58.png)

## 3. 対象コードを実行して確認

次に対象の処理を走らせます。

今回でいうとログインボタンを押した後にログイン処理が走り、ログインに成功するとfetchUserData(String accessToken)を実行することになっています。

### 3-1. 実行結果

![スクリーンショット 2024-05-03 16.01.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/3ba451a2-78b4-78dc-cd0f-eccb9348f8a9.png)


ユーザーを取得する処理はリストの２番目です。
画像の右側のOverviewにて詳細が確認できます。主には以下を確認します。

- Request uri：`https://qlita.com/api/v2/authenticated_user`
- Method：`GET`
- Status：`200`

:::note info 
**status code**
APIからのステータスコードはHTTPプロトコルで定義されており、クライアントとサーバー間の通信結果を示します。ステータスコードは主に以下のカテゴリに分けられます：

1. **1xx (情報):** リクエストを受け取り、処理中であることを示します。
    - 例：**`100 Continue`** — サーバーがリクエストの初期部分を受け取り、クライアントにリクエストを続行するよう求める。
2. **2xx (成功):** リクエストが成功し、サーバーがリクエストに応じたアクションを正常に完了したことを示します。
    - 例：**`200 OK`** — リクエストが成功し、レスポンスにデータが含まれる。
    - 例：**`201 Created`** — リクエストが成功し、新しいリソースが作成された。
3. **3xx (リダイレクション):** リクエストされたリソースが別の場所に移動されたことを示します。クライアントは追加のアクションを取る必要があります。
    - 例：**`301 Moved Permanently`** — リソースが恒久的に新しいURLに移動された。
    - 例：**`302 Found`** — リクエストされたリソースが一時的に異なるURLに移動している。
4. **4xx (クライアントエラー):** リクエストに問題があるため、サーバーがリクエストを処理できないことを示します。
    - 例：**`400 Bad Request`** — サーバーがリクエストを理解できず、処理ができない。
    - 例：**`401 Unauthorized`** — 認証が必要であるが、クライアントが認証されていない。
    - 例：**`404 Not Found`** — リクエストされたリソースがサーバー上に見つからない。
5. **5xx (サーバーエラー):** サーバーがリクエストを処理できない内部エラーが発生したことを示します。
    - 例：**`500 Internal Server Error`** — サーバー内部でエラーが発生し、リクエストを処理できない。
    - 例：**`503 Service Unavailable`** — サーバーが過負荷またはメンテナンス中で、現在リクエストを処理できない。

by ChatGPT
:::

さらに今回の処理はHeaderにアクセストークンを入れて送信することになっています。
右上のHeadersタブを選択し、スクロールすると内容が確認できます。

![スクリーンショット 2024-05-03 16.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/3311ddb0-1bba-d942-0847-b763a08e9b41.png)


更に右側のResponseタブでデータの内容も確認できます。

![スクリーンショット 2024-05-03 16.13.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/c6164a55-f3eb-eb3c-cbec-6e2a2f7fcf62.png)


### 3-2. status code of 500が出た場合

今回はエラーではなかったのですが、例えば処理がうまくいかなかった場合はStatusに書かれたコードが何番なのかを確認します。

今回は500番台だったと仮定すると、サーバー側に問題がある可能性が高いのでバックエンドエンジニアさんに調査を依頼することになります。

しかし、この時ただただバックエンドエンジニアさんに
*「なんかわからんがユーザー情報取得でエラーでたよ！」*
というよりは詳細を載せてあげたほうが良いでしょう。

先輩に教えてもらいながら上記のNetworkPageの情報をまとめて、バックエンドエンジニアさんに以下のメッセージを送りました。

![スクリーンショット 2024-05-03 16.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3058346/f7ec8db7-be46-71f7-12ef-3793e5cf3dfb.png)


程なくして修正が行われて無事に解決することができました。

## 終わりに

いかがだったでしょうか？
エラーが出た場合には原因がフロントエンド（アプリ）とバックエンドのどちらにあるのか？
バックエンドエンジニアさんに調べてもらうには何を提供してあげたら円滑に調査&改修ができるのか？
現場の開発においてはお互いに協力ことが大事だと学びました。

今回の記事が誰かのお役に立てれば幸いです。