Nao000のぶろぐ

蝶を追っている少年になりたい

CORSを許可して JavaScript で Elixir Phoenix から自分のブログ情報を取得する

CORSを許可して JavaScript で Elixir Phoenix から自分のブログ情報を取得する

そもそも

CORS は "Cross-Origin Resource Sharing" の略です。マイクロサービスを調べたりすると出くわす単語でした。よく、「サーバーサイドは Go lang でクライアントサイドは Vue で実装」みたいな言葉を見ます。指定したクライアントのみがサーバーサイドの情報を取得するために CORS を許可する必要があります。

やったこと

https://www.nao000.com/api/blogs/ で取得できるブログ情報を https://app.netlify.com/ でホスティングする静的サイトで取得して画面に表示することをやりました。ローカルでも取得できます。

GETリクエストでブログ情報を取得

https://www.nao000.com/api/blogs/ にGETリクエストすると以下のようにブログ情報が取得できるようにします。

    {"blog_json":"[{"url_title":"elixir-phoenix-layout-in-layout","updated_at":null,"title":"elixir phoenix Layoutの中でLayoutを出力する","thumbnail_url_path":"","summary":"elixir phoenix Layoutの中でLayoutを出力する","pv":null,"keywords":null,

    ~省略~

別で静的サイトを用意する

以下が別で用意した静的サイトのプロジェクトです。単純なHTMLを表示するだけです。

    __
    |_ index.html
    |_ js
      |_ index.js

JavaScript で取得する

これを JavaScript で取得するときは以下のようにします。

    (async () => {

        // ブログ情報を取得
        const blogJson = await fetch('https://www.nao000.com/api/blogs/')
        .then(response => response.json())
        .then(data => data);

        // シリアライズされたブログ情報をデシリアライズする
        const blogObj = await JSON.parse(blogJson.blog_json);

        // 取得したブログ情報を画面表示
        for (let [key, value] of Object.entries(blogObj)) {

            const node = document.createElement("li");
            const textnode = document.createTextNode(value.title);
            node.appendChild(textnode);
            document.getElementById("blogList").appendChild(node);
        }
    })();

HTML に表示したい

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    <ul id="blogList"></ul>
    <script src="./js/index.js"></script>
    </body>
    </html>

このままだとブラウザでエラーになります

Chromeブラウザ(バージョン: 84.0.4147.135)ですと、以下のようなエラーがコンソールに表示されました。

    Access to fetch at 'https://www.nao000.com/api/blogs/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

サーバーサイド側でCORS許可する

cors_plug を https://github.com/mschae/cors_plug に従ってインストールします。

router.ex を修正します。

      pipeline :api do
        plug :accepts, ["json"]
        plug CORSPlug
      end

      # ~~~~

      scope "/api", Nao000dotcomWeb do
        pipe_through :api

        get "/blogs/", User.SampleController, :index
      end

HTMLで表示できるようになる

さきほど表示できなかった画面が表示できるようになりました。画像はローカルディレクトリをそのまま表示していますが、このプロジェクトをそのままNetlifyにデプロイしても同じ様にブログ情報を取得することが出来ます。

終わり

CORS を許可する経験というと大袈裟かもですが、業務では一切経験していませんでした。マイクロサービスを個人的に調べてるときに見かけた単語で、なんとなく概要は知っていました。実際に手を動かしてみると経験値が積まれた感覚になれました。

参考資料