手頃なソースコードが欲しい！RealWorld使ってみた苦労話

こんにちは、ハトです。
frontendやbackendを勉強したらある程度のソースコードが欲しいことってありませんか？色々試してみたいけど、０から作るほどやる気はないし。
かといってQiitaとかデフォルトのものは簡単すぎるし。
できれば仕事で使っているくらいのまとまったコードで試してみたかったり。
いい感じにまとまっているものないかなぁと。

そんなものを探していたら面白いもの見つけたので使ってみました！
導入にあたって苦労したところを書いてみました

# RealWorld

[RealWorld](https://codebase.show/projects/realworld?category=frontend)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/cbb57372-33ea-41a1-a75e-46235bcb5100.png)

ここに書いてあるコードで出来上がるものはサインアップ、サインイン、サインアウトの他に記事の投稿、いいね、記事の削除など基本的な操作ができるブログみたいなものです。
Frontend, Backendで自分が勉強したいソースコードをgit cloneして動作を確認できます。

例えばテストコードの勉強をしたいとき、mybatisで実用的なsqlを試してみたいときに使えそうですね。
なんですが、結構罠も多かったのでいくつか共有します。

実際に私がやろうとした組み合わせ
frontend: [vue3-realworld-example-app](https://github.com/mutoe/vue3-realworld-example-app)
backend: [spring-boot-realworld-example-app](https://github.com/gothinkster/spring-boot-realworld-example-app),
[golang-gin-realworld-example-app](https://github.com/gothinkster/golang-gin-realworld-example-app)


# ここが大変だよ、RealWorld

## backendサーバーは起動してないよ

いや、私がやった時だけであって欲しいと思っています。frontendで次のような記述があります。
```.env
VITE_API_HOST=https://api.realworld.io
```
なるほど、`https://api.realworld.io`にリクエスト飛ばせば帰ってくるのか、、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/3925a17b-1343-479c-87f4-8217107155d6.png)

と思ったか！
違います。返って来ません。。
これは、CloudflareやIBM Cloudなどのサービスで、オリジンWebサーバーのIPアドレスを解決できないときに発生するエラーらしいです。
じゃあ何が正解かというとわかんないんですが、泣く泣くlocalでbackendを立ち上げました。

curlやpingをしたところ次のような結果だったので、エッジサーバーは起動しているが本体は起動していないような感じでしょうか？

```terminal
❯ ping api.realworld.io
PING api.realworld.io (104.21.16.1): 56 data bytes
64 bytes from 104.21.16.1: icmp_seq=0 ttl=57 time=25.513 ms
64 bytes from 104.21.16.1: icmp_seq=1 ttl=57 time=44.116 ms
^C
--- api.realworld.io ping statistics ---
10 packets transmitted, 10 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 24.453/31.133/44.116/6.547 ms
❯ curl https://api.realworld.io/tags
error code: 1016%                                                                      ❯ curl https://api.realworld.io/api/tags
error code: 1016%                                                                      ❯ curl http://api.realworld.io/api/tags
error code: 1016%                
```

## CORSエラーが起きるよ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/b16df90c-6e56-49b2-8243-704444ec2dd4.png)

雑にfrontendとbackendを繋いでいるので、そりゃ起きますよね…
CORSについては例えばこの記事を読んでみてください。
https://qiita.com/higakin/items/fabe6a23d564b20ad558

雑にこの問題を解消してさっさと検証したい場合は次のツールを入れればいいです
[CORS Unblock](https://chromewebstore.google.com/detail/cors-unblock/hadoojkfknbjgoppkecpgamiajljiief?hl=ja)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/549a97d5-41b8-4654-884b-3bf4d610d20d.png)
いや使用件数が少ないので、開発専用PC以外には入れませんが…

あとは使用するサイトでon/offの設定をするだけなので簡単です。
緑色に光っていることを確認すれば、今回のCORSエラーは回避できます。

開発が終わったらちゃんと消しましょうね。

あとはbackendでCORSも大丈夫の設定を入れる必要がありますね

## 環境変数で変更しきれないapiのbaseURLがあるよ
これは、[spring-boot-realworld-example-app](https://github.com/gothinkster/spring-boot-realworld-example-app)の場合ですね。READMEにグエーってことが書いてあります。

> Try it out with a RealWorld frontend
The entry point address of the backend API is at http://localhost:8080, not http://localhost:8080/api as some of the frontend documentation suggests.

「フロントでは/api必要と書いたがあれは嘘だ、/apiはつけてはいけない」

これマジかよ…。環境変数はさっき書いた通りこれですよ…
```.env
VITE_API_HOST=https://api.realworld.io
```

`/api`を削除しろとのことです。正規表現とか使えばできるのかなぁ〜？私の技術力では厳しいところもありました。

## backendが古すぎるよ

これは[golang-gin-realworld-example-app](https://github.com/gothinkster/golang-gin-realworld-example-app)ですね。
Go 1.13　を求められていますが、最新は1.24です。
最終commit日は2021年です…

起動までは全く問題ありませんでしたが…
いざリクエストまで飛ばすと大量に500番台のエラーが出ました。`binding:"required"`はないよが主でしたね。
あとはこれが古いとか
`gopkg.in/go-playground/validator.v8`

諸々Error文に従いながら直していけばまだまだ使えます。

## アクセストークンを詰めていないfrontend
これは[vue3-realworld-example-app](https://github.com/mutoe/vue3-realworld-example-app)ですね。

いやマジかよ…ログインができても記事を投稿すると`401`が出ることがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/b7fbc4bd-f741-4423-a363-63a76ed02be0.png)

request headerを見るとトークンが入っていない、、、
マジかよ

ただ、localstorageには入っているんですよね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561216/22e1e868-bba2-4c50-9923-f4d19bc52cda.png)

ということでcurlでやってみましょうか
```curl 
curl -X GET "http://localhost:8080/api/profiles/test" \
     -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDIyMDY1MDYsImlkIjo0fQ.zhnBsuklhi1nogtyqewTgfjreJ_BE6UExlIWVRx1EPo"
{"profile":{"username":"test","bio":"","image":null,"following":false}}
```

ちゃんとtokenを渡せば返ってくる…
はい、frontに実装がないんですね

ということで次の実装をfrontendに追加すればokです

```ts:api.ts
    //  `Authorization` ヘッダーを追加する
    const user = localStorage.getItem("user");

    if (user) {
      requestParams.headers = {
        ...requestParams.headers,
        Authorization: `Token ${JSON.parse(user).token}`,
      };
    }
```

# でもなんだかんだ使える
ここまで準備するのに自分は3時間くらいかかったのですが…
とはいえ、色々調べながらまとまって動くものが用意できたのはかなり大きいですね。 __今後はこれを立ち上げれば様々な検証ができるお手頃なbackend & frontendが手に入りました！__ 検証が捗りそうです。

いけてないところばかり挙げて来ましたが、直せる範囲のことばかりだった気もします。本当に困ったら生成AIに聞けばいいですし。
きっと様々なfrontendとbackendの組み合わせに対応しないといけないから作られた方も色々悩みどころが多いのかなぁと思います。小さな修正くらいは利用者でカバーしないと…

とはいえ次選ぶとしたら、できるだけcommit日の新しいものを使いますね。。

# こういう使い方も？
これだけまとまっていて、古いバージョンもあったりすると、フレームワークのバージョン上げの練習とかできるかもしれないですね。
好きな方法でE2Eもできますよね。
deployとかもできそう。