CORS(オリジン間リソース共有)とは?

はじめに

こんにちは、フロントエンドチームの高田(@proghallelujah)です。 webアプリケーションを開発していると、このような内容のエラーが出たことがある人は多いかもしれません

Access to XMLHttpRequest at 'https://hoge.com' from origin 'https://fuga.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

このエラーは一体どういったことを伝えているのでしょうか?また、エラー文内にあるCORSというものは一体なんでしょうか?今回はこちらについて解説していこうと思います。

CORSについて

CORSの意味

まず、このCORSというのはCross-Origin-Resource-Sharingの略で、日本語に訳すとオリジン間リソース共有と言います。

このCORSは、あるオリジンで動作しているウェブアプリケーションに、異なるオリジン内のリソースへのアクセスをオリジン間HTTPリクエストにより実行するようブラウザに指示するための仕組みです。


(補足)オリジンとは?

プロトコルドメイン、ポートによって定義されたものです。

例) http://hoge.com:80

こちらの場合、http(プロトコル)+hoge.com(ドメイン)+80(ポート)からできたオリジンです。


なぜCORSが必要か?

CORSは、webセキュリティポリシーの一つSame-Origin Policy(同一生成元ポリシー)によって定められた制限に対応しており、安全なオリジン間のリクエストやブラウザ・サーバー間のデータ転送を行うためのものです。

同一生成元ポリシーとは?

JavaScriptなどのプログラムを用いた通信において、そのプログラムが存在する同一のオリジン内でのみデータアクセスを可能にし他のオリジンへのアクセスをできないよう制限するための仕組みです。

オリジン1: http://hoge.com/dir/page.html
オリジン2: http://hoge.com/dir/shop/main.html

パスは異なっていますが、プロトコル、ドメインといったオリジンは同一のため、アクセスは可能となります
オリジン1: http://hoge.com/dir/page.html
オリジン2: https://hoge.com/dir/page.html

パスは同一ですが、プロトコルが違うため、アクセスは制限されます

なぜ制限するのか?

例えばXSS(クロスサイトスクリプティング)という攻撃手法があります。これは標的とするwebアプリに第三者が外部から悪意のあるスクリプトを埋め込み、アプリが意図をしていない動作を引き起こすようにします。

これは基本的に別のオリジンからの攻撃になるため、同一制限ポリシーがあることで防ぐことができます。

このように異なるオリジンからのアクセスを制限することにより、元オリジンのリソースに対して悪い影響を与えることを防ぐのを目的としています。

制限が適用されないケース

基本的にはJavaScriptによる非同期通信などに適用されますが、htmlベースのものでは制限されないものが多いです

  • <img>タグのsrc属性で読み込まれた画像
  • <link>タグのhref属性で読み込まれたCSS
  • <script>タグのsrc属性で読み込んだJavaScript

などなど、普段よく使っているものの中にも別のオリジンから読み込んでいるものが多くありますが、これらは同一オリジンポリシーが適用されません。

参考

MDN - オリジン間リソース共有 (CORS)

CORS(Cross-Origin Resource Sharing)

MDN - Origin (オリジン)

MDN - 同一オリジンポリシー

Wikipedia - クロスサイトスクリプティング

銀座Rails#24@リンクアンドモチベーション 勉強会の感想

こんにちは!株式会社 PREVENT の開発部門、バックエンドエンジニアチームの松原と申します。

厳しい残暑がようやく和らぎ始めましたが、いかがお過ごしでしょうか?

今回は、8月28日(金)に銀座 Rails に参加した感想と、イベント中に登場した技術、特に詳しく知らない点を学習も兼ねてまとめたいと思います!

ginza-rails.connpass.com

銀座 Rails のイベントに初めて参加したのですが、今回は Devise 、 Rails で行う Distributed Tracing 、 Rails で作る serverless CMS などを学びました。

業務で Rails を扱うようになり八ヶ月が経過しましたが、イベントでテーマとして取り上げられている技術は知らないものばかりで、 Rails に変換して考える段階まで至ることができませんでした。

Rails 的に考察できるととても面白そうなので、 Distributed Tracing について学習し直したいと思います。

Distributed Tracing (分散トレーシング)とは?

分散トレーシングとは、分散されたシステムで処理されるリクエストを追跡するためのものです。

分散トレーシングには主に二つの要素があり、その要素を Span と Trace と呼びます。

Span: 1サービス内の処理を表す。

Trace: Requestのstart-endを含むSpanの集合をあらわす。

イメージは以下のようになります。

f:id:syrengr:20200909190708p:plain

<出典: 分散トレーシングシステムのZipkinを使ってみた話>

分散トレーシングでは、 Span と Trace を可視化し、問題点と処理に時間がかかっている点を確認することができます。また、解決するための手助けをするシステムを分散トレーシングシステムといいます。

Open Tracing について

Open Tracing とは、開発者にシステムトレーサーの追加、またはトレーサーの切り替えを行う仕組みを提供する、分散トレーシングの実装です。

Open Tracing 仕様を実装したトレーサーとして、 Twitter 社が開発した Zipkin や、 Uber 社の Jaeger などがあり、詳しくは以下の資料が大変参考になりました! :)

www.slideshare.net

Distributed Tracing を Rails で行う方法

ネット上の資料を調べた結果、分散トレーシングを Rails で行うには以下の記事が参考になりそうだと思いましたが、翻訳しつつ拝読しても難易度は高く感じたため、今後まとまった時間が取れたらトライしてみたいです。

medium.com

OpenCensus (分散トレーシングを行うためのライブラリ集)を使用すると、 Rails で分散トレースを簡単に採用できるというお言葉が心強いです :)

イベントに参加させていただき、ありがとうございました!

以下でも同様の記事を書いておりますので、ご紹介させていただきます。

銀座Rails#24@リンクアンドモチベーション 勉強会の感想|Sayuri Matsubara|note

季節の変わり目、くれぐれもご自愛ください。それでは、失礼致します。

半年間リモートワークを続けてみて感じたこと

はじめに

こんにちは、フロントエンドチームの高田(@proghallelujah)です。

弊社は昨今世界中で発生しているCOVID-19危機のため、2020年3月ごろから一時的にリモートでの業務が可能になりました。 それまでは全ての業務を会社のオフィス内で行っていました(業務委託などの例外はあります)ので、最低限の規約の中でのスタートで本当に大丈夫だろうか?と最初は不安でしたが、今現在でも会社は問題なく動いております。 これは開発部門も例外ではなく、2020年9月現在では全ての開発メンバーが適宜リモートワークを活用しながら業務を行っております。半年間もリモートワークをしていることに記事を書きながら気付いたのですが今ではこれが当たり前になっており、たまに会社に出社するとあまりの人の少なさに少し寂しくなったりもします。

半年間リモートワークを続けてみてどうだったか?メリットデメリットを含め僕が感じたことを書いていこうと思います。

①: 時間を有効に使えるようになった

リモートワークの魅力の一つとして通勤時間が無くなることです。時間をフルに無駄なく使えることの素晴らしさを1日目から実感することができました。 朝起きてすぐに仕事ができるというのはかなり魅力的ですし、早くはじめれる分早く仕事を終え、自分の時間を増やすこともできました。 また、休憩時間に家のことができるので、部屋が少し綺麗になったりご飯の質も少し上がりました笑

ただし、家にいると身嗜みに無頓着になりがちで、僕は髭を剃らなすぎて大変なことになっていました。定期的なビデオ会議等あるので毎日ある程度はきちんとすることが必要です。

②: 予想以上に業務で困ることがなかった

弊社はリモートワーク以前からコミュニケーションツールとしてSlackを、ドキュメント作成にはesaを使用していました。なのでリモートワーク中でも業務についての連絡は特に以前と変わらずに滞りなく行えています。急ぎの用件があっても投稿をすれば間違いなく返答があるので今のところ根本的に業務で困ったことはありません。

ビデオ会議に関してはリモートワーク前は業務で使用することはなかったのですが、これも当初から問題なく運用できています。(弊社開発部門のリーダーは会議ツールに嫌われているのか初回入室のさいは声が聞こえない確率が高いというのが喫緊の問題です)

ただ、痒いところに手が届かないようなことはよくあるのでそのためのドキュメントやルール整備は日々進めていっております。

③: 人と喋る機会が少なくなった

僕は一人暮らしでペット等も飼っていないので丸一日中人と接することがない日もあります。ビデオ会議はもちろんありますが毎日しているわけでもないので、その日した唯一の会話が「袋はいりません」ということもあったり笑。

集中したいときに周りに雑音がなく自分の事に取り組めるのでコーディングにブーストをかけたりはできますが、たまにはみんなでワイワイしたいという気持ちもあります。 上記の通り業務に関するコミュニケーションは問題なく行えてますが、雑談となるとなかなか難しく、discordなどのもくもく・雑談用のコミュニケーションツールやチャンネルなどを用いたりもしましたがなかなかうまくいっていないのが現状です。

④: 家で良い作業をするためには設備投資が必要

僕は1SK(リビング1つとロフト1つ)のアパートに住んでいて、仕事やプライベートも全てリビングで行っているのですが(ロフトは寝室)そのせいか、仕事とプライベートの境界が少し曖昧になってしまっています。ただあまり大きい部屋でもないのでのでこれ以上机を増やすこともできず、こればかりは引っ越すくらいしか手がないのが難点ですね。

また、作業環境も座椅子とこたつテーブルなのですがあまり体にあってないのでだんだん腰が痛くなってきます。一日中同じ場所にいるということを考えると、やはり良い作業環境は必須だなと思います。最近は小さいスタンディングデスクなら置けるかなと試行中です。

⑤: 外に出る頻度が減った・日にあたることや運動の大切さ

通勤が無くなったことで平日に外に出る用事が少なくなり、最初は買い物などの用事をまとめて済ませて3日くらい家にこもりっぱなしという日もありました。必要なこと以外は家から出なくていいのはなかなか楽だなと思ったのですが、流石に不健康すぎると思って毎朝散歩やランニングをするようになりました。

軽い運動をしているということもありますが、日光に直接当たることで体内時計が補正されたのか、家にこもりっぱなしの時より体の調子がよくなった気がします。リモートワークを続けていると普段より体重が増えたという声もよく聞きますが、やはり意識的に運動する機会を作る機会が必要だと感じました。

最後に

リモートワークというのはとても魅力的なものですが、いざ実施するとなると大小様々な問題が発生すると思います。弊社では緊急で始まった施策ではありますがこれを機に正式な形としてのリモートワーク制度を実施するため、様々な施策や環境の整備が弊社では進められています。

現在でも日本中で広がり続けているCOVID-19ですが、PREVENTは病気予防・ヘルスケアに携わる企業としてこれに負けることなく、一人でも多くの方に健康的な生活を送り続けていただけるよう業務に取り組んでおります。

moment.jsで単位を日に指定してdiffを使う時、時間を考えず日が変わったかどうかだけで比較する

結論: startOf('days')で時間をまるめる

const dayOne = moment('2020-01-01 10:00:00').startOf('days');
const dayTwo = moment('2020-01-02 09:00:00').startOf('days');
console.log('dayOne', dayOne.format());
console.log('dayTwo', dayTwo.format());
console.log('diff', dayTwo.diff(dayOne, 'days'));

スクリーンショット 2020-03-22 22.51.26.png

はじめに

こんにちは、フロントエンドチームの高田(@proghallelujah)です。

moment.jsには指定した二つの日時を比較し、出力するdiffという機能があります。

この機能は、2つの日付の差分を時間単位まで観測し、デフォルトでは秒数で出力されます。 diffは第二引数で測定する時間単位を指定することが可能です。しかしその時、内部では秒数を任意の単位に再計算した値を返しています。 また、その時小数点以下は切り捨てられてしまいます

const dayOne = moment('2020-01-01 10:00:00');
const dayTwo = moment('2020-01-02 11:00:00');
const dayThree = moment('2020-01-02 09:00:00');
const dayFour = moment('2020-01-02 10:00:00');

console.log("dayTwo", dayTwo.diff(dayOne, 'days')); // dayTwoはdayOneの時間を過ぎているので1
console.log("dayTwo asFloat", dayTwo.diff(dayOne, 'days', true));
console.log("dayThree", dayThree.diff(dayOne, 'days')); // dayThreeはdayOneの時間を過ぎてないので0
console.log("dayThree asFloat", dayThree.diff(dayOne, 'days', true));
console.log("dayFour", dayFour.diff(dayOne, 'days')); // dayFourはdayOneと同じ時間なので1
console.log("dayFour asFloat", dayFour.diff(dayOne, 'days', true));

スクリーンショット 2020-03-22 22.49.55.png

(tips: 第三引数にtrueを渡すことで値から小数点を切り捨てず返されます)

以下はmomentjsでdiffを行なっている箇所です。 GitHub - moment.js/moment/src/lib/moment/diff.js


厳密な日付を計算するのであればこれが最良ですが、時間を考えず単純に日にちが変わったかどうかを計算したい、といった場合も多いと思います。 startOfを使えば、そのような機能を簡単に実装することができます。

startOfとは

momentの機能の一つで、指定した時間単位の始まりの値を出力します。 スクリーンショット 2020-03-22 23.02.30.png startOfでdayを指定すると、日のはじまり0:00:00に時刻を変換して出力されます。

参考: moment.js - Start of Time

ではstartOfを用いでdiffを使ってみます。

const dayOne = moment('2020-01-01 10:00:00').startOf('days');
const dayTwo = moment('2020-01-02 09:00:00').startOf('days');
console.log('dayOne', dayOne.format());
console.log('dayTwo', dayTwo.format());
console.log('diff', dayTwo.diff(dayOne, 'days'));

スクリーンショット 2020-03-22 22.51.26.png

diffは単位以下の値が同値の場合は1になるので、これで日にちが変わったかどうか計算することができます。

アンチパターンMath.roundを使う

小数点以下が切り捨てられるなら、Math.roundで繰り上げるようにすればよい、という案もあります。 しかし、Math.roundは意図せぬ値まで繰り上げてしまいます。

1. 第三引数にtrueを渡し、Math.roundを使う

const dayOne = moment('2020-01-01 01:00:00');
const dayTw0 = moment('2020-01-02 00:00:00');
const dayThree = moment('2020-01-01 17:00:00');
console.log(Math.round(dayTwo.diff(dayOne, 'days', true)), dayTwo.diff(dayOne, 'days', true));
console.log(Math.round(dayThree.diff(dayOne, 'days', true)), dayThree.diff(dayOne, 'days', true));

スクリーンショット 2020-03-22 23.10.12.png この場合、ある程度時間がたってしまった値だと、日付が同じでも繰り上げてしまいますので使用することができません。 なので、startOfが現状最良の手段だと思われます。


いかがでしたでしょうか?時間単位のはあくまで例に使っただけなので、その他の単位でも使用することができると思います。momentはドキュメントが丁寧でわかりやすく、自動翻訳でもそれなりに見ることができるので、皆さんもよかったらご一読ください。

moment.js - Docs

PREVENTの事業内容について

みなさんはじめまして。株式会社PREVENTの開発部門、フロントエンドエンジニアチームの高田(@proghallelujah)と申します。

こちらのブログでは、わたしたちが社内でどのようなプロダクトの開発を行なっているかや、普段用いている技術や運用方法について、また社内でどのような業務を行なっているかを紹介していこうと思います。

まずPREVENTがどのような会社かを簡単に紹介したいと思います。

PREVENTとは?

PREVENTは一病息災の健康づくり支援モデルを社会にという事業ミッションを掲げる名古屋大学医学部発のデジタルヘルススタートアップの一社です。 主に二つのプロダクトを軸に、生活習慣病の重症化を予防することによって医療費の削減、適正化を目指しています。

プロダクトについて

Myscope

健康保険組合保有する健康診断およびレセプトから独自アルゴリズム生活習慣病などの疾病発生を予測し発症リスクを算出、誰がどの程度発症の危険性があるかリスト層別化したデータを作成、ハイリスク者をターゲットに対象者の抽出を行う医療データ解析事業です。

Mystar

登録された利用者様がモニタリング機器を用いながらアプリに情報を登録し、社内のメンターと呼ばれる医療資格を持った専門スタッフがその情報を元に健康づくりのための個別指導を電話やチャット等のオンラインで提供するオンライン完結型での重症化予防⽀援事業です。

かなりざっくりとした説明ですので、もっと詳しく知りたいという方は以下の記事をご覧いただけたらと思います!

最後に

今後ともさまざまな情報発信をしていきたいと考えております!どうぞよろしくお願いします。

PREVENT