サーバ気象予報

概要

とある会社に勤めている、K君はサーバのお天気管理システムを開発しています。しかし、気温と湿度の情報を取得・送信することができません。原因を究明して取得・送信出来るようにして下さい。

前提条件

  • client/etc/hostsを変更しない

初期状態

  • prob4-proxyからwebとapiにリバースプロキシをしている。
  • VNCのFirefoxからhttp://web.testにアクセスし、気温と湿度を取得・送信しようとするが送信できない。
  • apiサーバの/srv/api/以下にexpressサーバの設定が記述されている。これらはnpm startで起動できる。

終了状態

  • VNCのFirefoxからhttp://web.testにアクセスし気温と湿度を取得・送信ができ、リソースが更新される。
  • prob4-apiのOSを再起動してもexpressサーバが自動で起動されているようになっている。

解説

この問題ではAPIサーバから取得する情報にCORS設定に問題があったためにブラウザ側でブロックされるのが原因でした。Proxyサーバに適切なCORSヘッダーを追加する設定を追加することで、正しくAPIサーバからリソースを取得することができる様になります。

CORS(Cross-Origin Resource Sharing)とは

自分とは異なるオリジンにリソースをリクエストするときにオリジン間リクエストが発生する。
セキュリティ上の都合のためブラウザはスクリプトから発生するオリジン間リクエストを制限しています。

同じオリジンからのリソース取得だけでは不便なので、異なるオリジンからWebサイトに対してのアクセスを可能をする仕組みがCORS設定です。今回はこの設定が間違っていました。

参考

オリジン間リソース共有 (CORS) – HTTP | MDN – Mozilla

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

Origin (オリジン) – MDN Web Docs 用語集

https://developer.mozilla.org/ja/docs/Glossary/Origin

解法

工程①

APIにてexpressサーバを起動する

cd /srv/api
npm start

> [email protected] start /srv/api
> node server.js

server is listening on port 3000...

VNCに接続する。

web.testにアクセスし取得・送信ボタンを行うがリソースが取得・送信できないことが確認できる。

デベロッパーツールで通信を確認してみるとCORS Missing Allow Originと表示されるのでCORSが原因ということが分かる

OPTIONの方をクリックし、ヘッダーを比較すると以下のようなことが確認でき、一部の設定に間違いがあることが分かる。

問題文にProxyサーバとあることからProxyサーバでヘッダーを書き換えていると予想できる。

確認してみると、間違えていることが分かるのでviなどで正しく修正し、Nginxを再起動する。

sudo vim /etc/nginx/nginx.conf


~~~~省略~~~~~~

server {
          listen 80;
          server_name api.test;

          location / {
            proxy_pass http://192.168.4.102:3000;

            add_header Access-Control-Allow-Origin '*';

            # POST を追加
            add_header Access-Control-Allow-Methods 'GET, POST';

            # Acccept から content-type に変更
            add_header Access-Control-Allow-Headers 'content-type';
          }
        }

sudo systemctl restart nginx

web.testよりリソースが送信・取得できる。

工程②

prob4-apiのOSを再起動してもexpressサーバが自動で起動されているようになっている。とあるのでこれを行う。

viなどでサービスファイルを作成し自動起動を有効化することで終了条件を満たせる。なお別解としてcronなどでも起動できました。

sudo vim /etc/systemd/system/api.service

[Unit]
Description=express server
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/usr/bin/node /srv/api/server.js
WorkingDirectory=/srv/api
KillMode=process
Restart=always
User=user
Group=user

[Install]


sudo systemctl enable weather

その他

チームによってはヘッダーが二重についていることがあったが、終了条件を満たせていれば満点にしました。