S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ

S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ
เชฐเซ‚เชฌเซ‡ เช—เซ‹เชฒเซเชกเชฌเชฐเซเช— เช•เซ‹เชซเซ€ เชฎเชถเซ€เชจ

เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐ เชตเชชเชฐเชพเชคเชพ เชธเช‚เชธเชพเชงเชจเซ‹เชจเซ€ เช•เชฟเช‚เชฎเชค เช•เชพเชฐเซเชฏเช•เซเชทเชฎเชคเชพ เชตเชงเชพเชฐเซ‡ เช›เซ‡ เช•เชพเชฐเชฃ เช•เซ‡ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชซเช•เซเชค เชคเซเชฏเชพเชฐเซ‡ เชœ เชฅเชพเชฏ เช›เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชคเซ‡เชจเซ€ เชœเชฐเซ‚เชฐ เชนเซ‹เชฏ. เช†เชจเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช…เชฎเชฒเชฎเชพเช‚ เชฎเซ‚เช•เชตเซเช‚ เช…เชจเซ‡ เชตเชฐเซเช•เชฐ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเซเชธ เชคเชฐเซ€เช•เซ‡ เชตเชงเชพเชฐเชพเชจเซ€ เช•เซเชฒเชพเช‰เชก เชเชจเซเชŸเชฟเชŸเซ€ เชฌเชจเชพเชตเชตเซ€ เชจเชนเซ€เช‚ เชคเซ‡เชจเชพ เช˜เชฃเชพ เชตเชฟเช•เชฒเซเชชเซ‹ เช›เซ‡. เช…เชจเซ‡ เช†เชœเซ‡ เชนเซเช‚ FaaS เชตเชฟเชถเซ‡ เชจเชนเซ€เช‚, เชชเชฐเช‚เชคเซ เชตเซ‡เชฌเชนเซเช•เซเชธ เชตเชฟเชถเซ‡ เชตเชพเชค เช•เชฐเซ€เชถ. เชนเซเช‚ เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ เชตเซ‡เชฌเชนเซเช•เซเชธเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช‡เชตเซ‡เชจเซเชŸเซเชธเชจเซ‡ เชนเซ‡เชจเซเชกเชฒ เช•เชฐเชตเชพเชจเซเช‚ เชŸเซเชฏเซเชŸเซ‹เชฐเชฟเชฏเชฒ เช‰เชฆเชพเชนเชฐเชฃ เชฌเชคเชพเชตเซ€เชถ.

เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ เช…เชจเซ‡ เชตเซ‡เชฌเชนเซเช•เซเชธ เชตเชฟเชถเซ‡ เชฅเซ‹เชกเชพเช• เชถเชฌเซเชฆเซ‹. เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ เชคเชฎเชจเซ‡ เช‘เชฌเซเชœเซ‡เช•เซเชŸเชจเชพ เชธเซเชตเชฐเซ‚เชชเชฎเชพเช‚ เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เช•เซ‹เชˆเชชเชฃ เชกเซ‡เชŸเชพ เชธเซเชŸเซ‹เชฐ เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡, เชœเซ‡ S3 เช…เชฅเชตเชพ เช…เชจเซเชฏ API (เช…เชฎเชฒเซ€เช•เชฐเชฃ เชชเชฐ เช†เชงเชพเชฐ เชฐเชพเช–เซ€เชจเซ‡) HTTP/HTTPS เชฆเซเชตเชพเชฐเชพ เชเช•เซเชธเซ‡เชธ เช•เชฐเซ€ เชถเช•เชพเชฏ เช›เซ‡. เชตเซ‡เชฌเชนเซเช•เซเชธ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เช•เชธเซเชŸเชฎ HTTP เช•เซ‰เชฒเชฌเซ‡เช•เซเชธ เช›เซ‡. เชคเซ‡เช“ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เช•เซ‹เชˆ เช‡เชตเซ‡เชจเซเชŸ เชฆเซเชตเชพเชฐเชพ เชŸเซเชฐเชฟเช—เชฐ เชฅเชพเชฏ เช›เซ‡, เชœเซ‡เชฎ เช•เซ‡ เช•เซ‹เชกเชจเซ‡ เชฐเชฟเชชเซ‹เชเซ€เชŸเชฐเซ€เชฎเชพเช‚ เชงเช•เซ‡เชฒเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เช…เชฅเชตเชพ เช•เซ‹เชˆ เชŸเชฟเชชเซเชชเชฃเซ€ เชฌเซเชฒเซ‹เช— เชชเชฐ เชชเซ‹เชธเซเชŸ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เชœเซเชฏเชพเชฐเซ‡ เช•เซ‹เชˆ เช‡เชตเซ‡เชจเซเชŸ เชฅเชพเชฏ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชฎเซ‚เชณ เชธเชพเช‡เชŸ เชตเซ‡เชฌเชนเซ‚เช• เชฎเชพเชŸเซ‡ เช‰เชฒเซเชฒเซ‡เช–เชฟเชค URL เชชเชฐ HTTP เชตเชฟเชจเช‚เชคเซ€ เชฎเซ‹เช•เชฒเซ‡ เช›เซ‡. เชชเชฐเชฟเชฃเชพเชฎเซ‡, เชคเชฎเซ‡ เชเช• เชธเชพเช‡เชŸ เชชเชฐเชจเซ€ เช‡เชตเซ‡เชจเซเชŸเซเชธ เชฌเซ€เชœเซ€ เชธเชพเช‡เชŸ เชชเชฐ เชŸเซเชฐเชฟเช—เชฐ เช•เซเชฐเชฟเชฏเชพเช“ เชฌเชจเชพเชตเซ€ เชถเช•เซ‹ เช›เซ‹ (เชตเชฟเช•เซ€). เชเชตเชพ เช•เชฟเชธเซเชธเชพเชฎเชพเช‚ เชœเซเชฏเชพเช‚ เชธเซเชฐเซ‹เชค เชธเชพเช‡เชŸ เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ เช›เซ‡, เช‡เชตเซ‡เชจเซเชŸเซเชธ เชคเซ‡เชจเซ€ เชธเชพเชฎเช—เซเชฐเซ€เช“เชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐ เชคเชฐเซ€เช•เซ‡ เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡.

เช†เชตเชพ เช“เชŸเซ‹เชฎเซ‡เชถเชจเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เชพเชฏ เชคเซ‡เชตเชพ เชธเชฐเชณ เช•เชฟเชธเซเชธเชพเช“เชจเชพเช‚ เช‰เชฆเชพเชนเชฐเชฃเซ‹:

  1. เช…เชจเซเชฏ เช•เซเชฒเชพเช‰เชก เชธเซเชŸเซ‹เชฐเซ‡เชœเชฎเชพเช‚ เชคเชฎเชพเชฎ เช‘เชฌเซเชœเซ‡เช•เซเชŸเชจเซ€ เชจเช•เชฒเซ‹ เชฌเชจเชพเชตเชตเซ€. เชœเซเชฏเชพเชฐเซ‡ เชชเชฃ เชซเชพเช‡เชฒเซ‹ เช‰เชฎเซ‡เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช…เชฅเชตเชพ เชฌเชฆเชฒเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เชคเซเชฏเชพเชฐเซ‡ เชซเซเชฒเชพเชฏ เชชเชฐ เชจเช•เชฒเซ‹ เชฌเชจเชพเชตเชตเซ€ เช†เชตเชถเซเชฏเช• เช›เซ‡.
  2. เช—เซเชฐเชพเชซเชฟเช• เชซเชพเช‡เชฒเซ‹เชจเซ€ เชฅเช‚เชฌเชจเซ‡เชฒเซเชธเชจเซ€ เชถเซเชฐเซ‡เชฃเซ€เชจเซเช‚ เชธเซเชตเชšเชพเชฒเชฟเชค เชจเชฟเชฐเซเชฎเชพเชฃ, เชซเซ‹เชŸเซ‹เช—เซเชฐเชพเชซเซเชธเชฎเชพเช‚ เชตเซ‹เชŸเชฐเชฎเชพเชฐเซเช• เช‰เชฎเซ‡เชฐเชตเชพ เช…เชจเซ‡ เช…เชจเซเชฏ เช‡เชฎเซ‡เชœ เชซเซ‡เชฐเชซเชพเชฐเซ‹.
  3. เชจเชตเชพ เชฆเชธเซเชคเชพเชตเซ‡เชœเซ‹เชจเชพ เช†เช—เชฎเชจ เชตเชฟเชถเซ‡ เชธเซ‚เชšเชจเชพ (เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชตเชฟเชคเชฐเชฟเชค เชเช•เชพเช‰เชจเซเชŸเชฟเช‚เช— เชธเซ‡เชตเชพ เช•เซเชฒเชพเช‰เชก เชชเชฐ เช…เชนเซ‡เชตเชพเชฒเซ‹ เช…เชชเชฒเซ‹เชก เช•เชฐเซ‡ เช›เซ‡, เช…เชจเซ‡ เชจเชพเชฃเชพเช•เซ€เชฏ เชฆเซ‡เช–เชฐเซ‡เช– เชจเชตเชพ เช…เชนเซ‡เชตเชพเชฒเซ‹ เชตเชฟเชถเซ‡ เชธเซ‚เชšเชจเชพเช“ เชฎเซ‡เชณเชตเซ‡ เช›เซ‡, เชคเชชเชพเชธ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชคเซ‡เชจเซเช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเซ‡ เช›เซ‡).
  4. เชฅเซ‹เชกเชพ เชตเชงเซ เชœเชŸเชฟเชฒ เช•เซ‡เชธเซ‹เชฎเชพเช‚ เชธเชฎเชพเชตเซ‡เชถ เชฅเชพเชฏ เช›เซ‡, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช•เซเชฌเชฐเชจเซ‡เชŸเซ€เชธเชจเซ‡ เชตเชฟเชจเช‚เชคเซ€ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชตเซ€, เชœเซ‡ เชœเชฐเซ‚เชฐเซ€ เช•เชจเซเชŸเซ‡เชจเชฐ เชธเชพเชฅเซ‡ เชชเซ‹เชก เชฌเชจเชพเชตเซ‡ เช›เซ‡, เชคเซ‡เชจเซ‡ เช•เชพเชฐเซเชฏ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เชชเชธเชพเชฐ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซเชฏเชพ เชชเช›เซ€ เช•เชจเซเชŸเซ‡เชจเชฐ เชคเซ‚เชŸเซ€ เชœเชพเชฏ เช›เซ‡.

เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชœเซเชฏเชพเชฐเซ‡ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธ (MCS) เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ เชฌเช•เซ‡เชŸเชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐเซ‹ เชตเซ‡เชฌเชนเซ‚เช•เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ AWS เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœเชฎเชพเช‚ เชธเชฎเชจเซเชตเชฏเชฟเชค เชฅเชพเชฏ เชคเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เช•เชพเชฐเซเชฏ 1 เชจเซเช‚ เชเช• เชชเซเชฐเช•เชพเชฐ เชฌเชจเชพเชตเซ€เชถเซเช‚. เชตเชพเชธเซเชคเชตเชฟเช• เชฒเซ‹เชก เช•เซ‡เชธเชฎเชพเช‚, เช…เชธเซเชฎเซ‡เชณ เช•เชพเชฐเซเชฏ เช•เชคเชพเชฐเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธเชจเซ€ เชจเซ‹เช‚เชงเชฃเซ€ เช•เชฐเซ€เชจเซ‡ เชชเซเชฐเชฆเชพเชจ เช•เชฐเชตเซเช‚ เชœเซ‹เชˆเช, เชชเชฐเช‚เชคเซ เชคเชพเชฒเซ€เชฎ เช•เชพเชฐเซเชฏ เชฎเชพเชŸเซ‡ เช…เชฎเซ‡ เช†เชจเชพ เชตเชฟเชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃ เช•เชฐเซ€เชถเซเช‚.

เช•เชพเชฎ เช•เชฐเชตเชพเชจเซ€ เชฏเซ‹เชœเชจเชพ

เช† เช•เซเชฐเชฟเชฏเชพเชชเซเชฐเชคเชฟเช•เซเชฐเชฟเชฏเชพ เชชเซเชฐเซ‹เชŸเซ‹เช•เซ‹เชฒ เชตเชฟเช—เชคเชตเชพเชฐ เชตเชฐเซเชฃเชตเซ‡เชฒ เช›เซ‡ MCS เชชเชฐ S3 เชตเซ‡เชฌเชนเซเช•เซเชธ เชฎเชพเชŸเซ‡เชจเซ€ เชฎเชพเชฐเซเช—เชฆเชฐเซเชถเชฟเช•เชพ. เช•เชพเชฐเซเชฏ เชฏเซ‹เชœเชจเชพเชฎเชพเช‚ เชจเซ€เชšเซ‡เชจเชพ เช˜เชŸเช•เซ‹ เชถเชพเชฎเซ‡เชฒ เช›เซ‡:

  • เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพ, เชœเซ‡ S3 เชธเซเชŸเซ‹เชฐเซ‡เชœ เชฌเชพเชœเซ เชชเชฐ เช›เซ‡ เช…เชจเซ‡ เชœเซเชฏเชพเชฐเซ‡ webnhook เชŸเซเชฐเชฟเช—เชฐ เชฅเชพเชฏ เช›เซ‡ เชคเซเชฏเชพเชฐเซ‡ HTTP เชตเชฟเชจเช‚เชคเซ€เช“ เชชเซเชฐเช•เชพเชถเชฟเชค เช•เชฐเซ‡ เช›เซ‡.
  • เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡ เชธเชฐเซเชตเชฐ, เชœเซ‡ HTTP เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพเชจเซ€ เชตเชฟเชจเช‚เชคเซ€เช“ เชธเชพเช‚เชญเชณเซ‡ เช›เซ‡ เช…เชจเซ‡ เชฏเซ‹เช—เซเชฏ เช•เซเชฐเชฟเชฏเชพเช“ เช•เชฐเซ‡ เช›เซ‡. เชธเชฐเซเชตเชฐ เช•เซ‹เชˆเชชเชฃ เชญเชพเชทเชพเชฎเชพเช‚ เชฒเช–เซ€ เชถเช•เชพเชฏ เช›เซ‡; เช…เชฎเชพเชฐเชพ เช‰เชฆเชพเชนเชฐเชฃเชฎเชพเช‚, เช…เชฎเซ‡ เชธเชฐเซเชตเชฐเชจเซ‡ Go เชฎเชพเช‚ เชฒเช–เซ€เชถเซเช‚.

S3 API เชฎเชพเช‚ เชตเซ‡เชฌเชนเซ‚เช•เชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃเชจเซ€ เชเช• เชตเชฟเชถเซ‡เชท เชตเชฟเชถเซ‡เชทเชคเชพ เช เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพ เชชเชฐ เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเชจเซ€ เชจเซ‹เช‚เชงเชฃเซ€ เช›เซ‡. เช–เชพเชธ เช•เชฐเซ€เชจเซ‡, เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเซ‡ เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพเชจเชพ เชธเช‚เชฆเซ‡เชถเชพเช“เชจเชพ เชธเชฌเซเชธเซเช•เซเชฐเชฟเชชเซเชถเชจเชจเซ€ เชชเซเชทเซเชŸเชฟ เช•เชฐเชตเซ€ เช†เชตเชถเซเชฏเช• เช›เซ‡ (เช…เชจเซเชฏ เชตเซ‡เชฌเชนเซ‚เช• เช…เชฎเชฒเซ€เช•เชฐเชฃเชฎเชพเช‚, เชธเชฌเซเชธเซเช•เซเชฐเชฟเชชเซเชถเชจเชจเซ€ เชชเซเชทเซเชŸเชฟ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เชœเชฐเซ‚เชฐเซ€ เชจเชฅเซ€).

เชคเชฆเชจเซเชธเชพเชฐ, เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเซ‡ เชฌเซ‡ เชฎเซเช–เซเชฏ เช•เชพเชฎเช—เซ€เชฐเซ€เชจเซ‡ เชธเชฎเชฐเซเชฅเชจ เช†เชชเชตเซเช‚ เช†เชตเชถเซเชฏเช• เช›เซ‡:

  • เชจเซ‹เช‚เชงเชฃเซ€เชจเซ€ เชชเซเชทเซเชŸเชฟ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพเชจเซ€ เชตเชฟเชจเช‚เชคเซ€เชจเซ‹ เชœเชตเชพเชฌ เช†เชชเซ‹,
  • เช†เชตเชจเชพเชฐเซ€ เช˜เชŸเชจเชพเช“ เชชเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซ‹.

เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡

เชตเซ‡เชฌเชนเซเช• เชฐเซ€เชธเซ€เชตเชฟเช‚เช— เชธเชฐเซเชตเชฐเชจเซ‡ เชšเชฒเชพเชตเชตเชพ เชฎเชพเชŸเซ‡, เชคเชฎเชพเชฐเซ‡ Linux เชธเชฐเซเชตเชฐเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡. เช† เชฒเซ‡เช–เชฎเชพเช‚, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช…เชฎเซ‡ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เช‡เชจเซเชธเซเชŸเชจเซเชธเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช เชœเซ‡เชจเซ‡ เช…เชฎเซ‡ MCS เชชเชฐ เชœเชฎเชพเชตเซ€เช เช›เซ€เช.

เชšเชพเชฒเซ‹ เชœเชฐเซ‚เชฐเซ€ เชธเซ‹เชซเซเชŸเชตเซ‡เชฐ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซ€เช เช…เชจเซ‡ เชตเซ‡เชฌเชนเซเช• เชฐเซ€เชธเซ€เชตเชฟเช‚เช— เชธเชฐเซเชตเชฐ เชฒเซ‹เช‚เชš เช•เชฐเซ€เช.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  bc dns-root-data dnsmasq-base ebtables landscape-common liblxc-common 
liblxc1 libuv1 lxcfs lxd lxd-client python3-attr python3-automat 
python3-click python3-constantly python3-hyperlink
  python3-incremental python3-pam python3-pyasn1-modules 
python3-service-identity python3-twisted python3-twisted-bin 
python3-zope.interface uidmap xdelta3
Use 'sudo apt autoremove' to remove them.
Suggested packages:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui 
gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 3915 kB of archives.
After this operation, 32.3 MB of additional disk space will be used.
Get:1 http://MS1.clouds.archive.ubuntu.com/ubuntu bionic-updates/main 
amd64 git amd64 1:2.17.1-1ubuntu0.7 [3915 kB]
Fetched 3915 kB in 1s (5639 kB/s)
Selecting previously unselected package git.
(Reading database ... 53932 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.17.1-1ubuntu0.7_amd64.deb ...
Unpacking git (1:2.17.1-1ubuntu0.7) ...
Setting up git (1:2.17.1-1ubuntu0.7) ...

เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐ เชธเชพเชฅเซ‡ เชซเซ‹เชฒเซเชกเชฐเชจเซ‡ เช•เซเชฒเซ‹เชจ เช•เชฐเซ‹:

ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Cloning into 's3-webhook'...
remote: Enumerating objects: 48, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 114 (delta 20), reused 45 (delta 18), pack-reused 66
Receiving objects: 100% (114/114), 23.77 MiB | 20.25 MiB/s, done.
Resolving deltas: 100% (49/49), done.

เชšเชพเชฒเซ‹ เชธเชฐเซเชตเชฐ เชถเชฐเซ‚ เช•เชฐเซ€เช:

ubuntu@ubuntu-basic-1-2-10gb:~$ cd s3-webhook/
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80

เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพ เชชเชฐ เชธเชฌเซเชธเซเช•เซเชฐเชพเช‡เชฌ เช•เชฐเซ‹

เชคเชฎเซ‡ API เช…เชฅเชตเชพ เชตเซ‡เชฌ เช‡เชจเซเชŸเชฐเชซเซ‡เชธ เชฆเซเชตเชพเชฐเชพ เชคเชฎเชพเชฐเชพ เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเชจเซ‡ เชจเซ‹เช‚เชงเชฃเซ€ เช•เชฐเชพเชตเซ€ เชถเช•เซ‹ เช›เซ‹. เชธเชฐเชณเชคเชพ เชฎเชพเชŸเซ‡, เช…เชฎเซ‡ เชตเซ‡เชฌ เช‡เชจเซเชŸเชฐเชซเซ‡เชธ เชฆเซเชตเชพเชฐเชพ เชจเซ‹เช‚เชงเชฃเซ€ เช•เชฐเซ€เชถเซเช‚:

  1. เชšเชพเชฒเซ‹ เชฌเช•เซ‡เชŸ เชตเชฟเชญเชพเช— เชชเชฐ เชœเชˆเช เช•เช‚เชŸเซเชฐเซ‹เชฒ เชฐเซ‚เชฎเชฎเชพเช‚.
  2. เชฌเช•เซ‡เชŸ เชชเชฐ เชœเชพเช“ เชœเซ‡เชจเชพ เชฎเชพเชŸเซ‡ เช…เชฎเซ‡ เชตเซ‡เชฌเชนเซเช•เซเชธ เช—เซ‹เช เชตเซ€เชถเซเช‚ เช…เชจเซ‡ เช—เชฟเชฏเชฐ เชชเชฐ เช•เซเชฒเชฟเช• เช•เชฐเซ€เชถเซเช‚:

S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ

เชตเซ‡เชฌเชนเซเช•เซเชธ เชŸเซ‡เชฌ เชชเชฐ เชœเชพเช“ เช…เชจเซ‡ เช‰เชฎเซ‡เชฐเซ‹ เชชเชฐ เช•เซเชฒเชฟเช• เช•เชฐเซ‹:

S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ
เช•เซเชทเซ‡เชคเซเชฐเซ‹ เชญเชฐเซ‹:

S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ

ID โ€” เชตเซ‡เชฌเชนเซ‚เช•เชจเซเช‚ เชจเชพเชฎ.

เช‡เชตเซ‡เชจเซเชŸ - เช•เชˆ เช‡เชตเซ‡เชจเซเชŸเซเชธ เชŸเซเชฐเชพเชจเซเชธเชฎเชฟเชŸ เช•เชฐเชตเซ€. เช…เชฎเซ‡ เชซเชพเช‡เชฒเซ‹ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชคเซ€ เชตเช–เชคเซ‡ เชฅเชคเซ€ เชคเชฎเชพเชฎ เช‡เชตเซ‡เชจเซเชŸเซเชธเชจเซเช‚ เชŸเซเชฐเชพเชจเซเชธเชฎเชฟเชถเชจ เชธเซ‡เชŸ เช•เชฐเซเชฏเซเช‚ เช›เซ‡ (เช‰เชฎเซ‡เชฐเชตเซเช‚ เช…เชจเซ‡ เช•เชพเชขเซ€ เชจเชพเช–เชตเซเช‚).

URL โ€” เชตเซ‡เชฌเชนเซ‚เช• เชธเชฐเซเชตเชฐ เชธเชฐเชจเชพเชฎเซเช‚ เชชเซเชฐเชพเชชเซเชค เช•เชฐเซ‡ เช›เซ‡.

เชซเชฟเชฒเซเชŸเชฐ เช‰เชชเชธเชฐเซเช—/เชชเซเชฐเชคเซเชฏเชฏ เช เชเช• เชซเชฟเชฒเซเชŸเชฐ เช›เซ‡ เชœเซ‡ เชคเชฎเชจเซ‡ เชซเช•เซเชค เชเชตเชพ เช‘เชฌเซเชœเซ‡เช•เซเชŸเซเชธ เชฎเชพเชŸเซ‡ เชœ เชตเซ‡เชฌเชนเซเช•เซเชธ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡ เชœเซ‡เชจเชพ เชจเชพเชฎ เชšเซ‹เช•เซเช•เชธ เชจเชฟเชฏเชฎเซ‹ เชธเชพเชฅเซ‡ เชฎเซ‡เชณ เช–เชพเชฏ เช›เซ‡. เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชตเซ‡เชฌเชนเซ‚เช• เชฎเชพเชคเซเชฐ .png เชเช•เซเชธเซเชŸเซ‡เช‚เชถเชจ เชงเชฐเชพเชตเชคเซ€ เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชŸเซเชฐเชฟเช—เชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชฎเชพเช‚ เชซเชฟเชฒเซเชŸเชฐ เชชเซเชฐเชคเซเชฏเชฏ เชคเชฎเชพเชฐเซ‡ "png" เชฒเช–เชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡.

เชนเชพเชฒเชฎเชพเช‚, เชตเซ‡เชฌเชนเซ‚เช• เชฐเซ€เชธเซ€เชตเชฟเช‚เช— เชธเชฐเซเชตเชฐเชจเซ‡ เชเช•เซเชธเซ‡เชธ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฎเชพเชคเซเชฐ เชชเซ‹เชฐเซเชŸ 80 เช…เชจเซ‡ 443 เชธเชชเซ‹เชฐเซเชŸเซ‡เชก เช›เซ‡.

เชšเชพเชฒเซ‹ เช•เซเชฒเชฟเช• เช•เชฐเซ€เช เชนเซ‚เช• เช‰เชฎเซ‡เชฐเซ‹ เช…เชจเซ‡ เช†เชชเชฃเซ‡ เชจเซ€เชšเซ‡เชจเซ€ เชฌเชพเชฌเชคเซ‹ เชœเซ‹เชˆเชถเซเช‚:

S3 เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชธเซเชŸเซ‹เชฐเซ‡เชœ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚ เชตเซ‡เชฌเชนเซเช•เซเชธ เชชเชฐ เช†เชงเชพเชฐเชฟเชค เช‡เชตเซ‡เชจเซเชŸ-เช†เชงเชพเชฐเชฟเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ
เชนเซ‚เช• เช‰เชฎเซ‡เชฐเซเชฏเซเช‚.

เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐ เชคเซ‡เชจเชพ เชฒเซ‹เช—เชฎเชพเช‚ เชนเซ‚เช• เชจเซ‹เช‚เชงเชฃเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเชจเซ€ เชชเซเชฐเช—เชคเชฟ เชฆเชฐเซเชถเชพเชตเซ‡ เช›เซ‡:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] incoming HTTP request from 
95.163.216.92:42530
2020/06/15 12:01:14 Got timestamp: 2020-06-15T15:01:13+03:00 TopicArn: 
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token: 
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL: 
http://89.208.199.220/webhook
2020/06/15 12:01:14 Generate responce signature: 
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d

เชจเซ‹เช‚เชงเชฃเซ€ เชชเซ‚เชฐเซเชฃ เชฅเชˆ เช—เชˆ เช›เซ‡. เช†เช—เชณเชจเชพ เชตเชฟเชญเชพเช—เชฎเชพเช‚, เช…เชฎเซ‡ เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเชจเชพ เช‘เชชเชฐเซ‡เชถเชจเชจเชพ เช…เชฒเซเช—เซ‹เชฐเชฟเชงเชฎเชจเซ‡ เชจเชœเซ€เช•เชฅเซ€ เชœเซ‹เชˆเชถเซเช‚.

เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐเชจเซเช‚ เชตเชฐเซเชฃเชจ

เช…เชฎเชพเชฐเชพ เช‰เชฆเชพเชนเชฐเชฃเชฎเชพเช‚, เชธเชฐเซเชตเชฐ Go เชฎเชพเช‚ เชฒเช–เชพเชฏเซ‡เชฒเซเช‚ เช›เซ‡. เชšเชพเชฒเซ‹ เชคเซ‡เชจเชพ เช“เชชเชฐเซ‡เชถเชจเชจเชพ เชฎเซ‚เชณเชญเซ‚เชค เชธเชฟเชฆเซเชงเชพเช‚เชคเซ‹ เชœเซ‹เชˆเช.

package main

// Generate hmac_sha256_hex
func HmacSha256hex(message string, secret string) string {
}

// Generate hmac_sha256
func HmacSha256(message string, secret string) string {
}

// Send subscription confirmation
func SubscriptionConfirmation(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Send subscription confirmation
func GotRecords(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Liveness probe
func Ping(w http.ResponseWriter, req *http.Request) {
    // log request
    log.Printf("[%s] incoming HTTP Ping request from %sn", req.Method, req.RemoteAddr)
    fmt.Fprintf(w, "Pongn")
}

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
}

func main() {

    // get command line args
    bindPort := flag.Int("port", 80, "number between 1-65535")
    bindAddr := flag.String("address", "", "ip address in dot format")
    flag.StringVar(&actionScript, "script", "", "external script to execute")
    flag.Parse()

    http.HandleFunc("/ping", Ping)
    http.HandleFunc("/webhook", Webhook)

log.Fatal(http.ListenAndServe(*bindAddr+":"+strconv.Itoa(*bindPort), nil))
}

เชฎเซเช–เซเชฏ เช•เชพเชฐเซเชฏเซ‹ เชงเซเชฏเชพเชจเชฎเชพเช‚ เชฒเซ‹:

  • Ping() - เชเช• เชฐเซ‚เชŸ เช•เซ‡ เชœเซ‡ URL/ping เชฆเซเชตเชพเชฐเชพ เชชเซเชฐเชคเชฟเชธเชพเชฆ เช†เชชเซ‡ เช›เซ‡, เชœเซ€เชตเช‚เชคเชคเชพ เชšเช•เชพเชธเชฃเซ€เชจเซเช‚ เชธเชฐเชณ เช…เชฎเชฒเซ€เช•เชฐเชฃ.
  • Webhook() - เชฎเซเช–เซเชฏ เชฎเชพเชฐเซเช—, URL/webhook เชนเซ‡เชจเซเชกเชฒเชฐ:
    • เชชเซเชฐเช•เชพเชถเชจ เชธเซ‡เชตเชพ เชชเชฐ เชจเซ‹เช‚เชงเชฃเซ€เชจเซ€ เชชเซเชทเซเชŸเชฟ เช•เชฐเซ‡ เช›เซ‡ (เชธเชฌเซเชธเซเช•เซเชฐเชฟเชชเซเชถเชจ เช•เชจเซเชซเชฐเซเชฎเซ‡เชถเชจ เชซเช‚เช•เซเชถเชจ เชชเชฐ เชœเชพเช“),
    • เช‡เชจเช•เชฎเชฟเช‚เช— เชตเซ‡เชฌเชนเซเช•เซเชธเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซ‡ เช›เซ‡ (เช—เซ‹เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เช•เชพเชฐเซเชฏ).
  • เชซเช‚เช•เซเชถเชจเซเชธ HmacSha256 เช…เชจเซ‡ HmacSha256hex เช HMAC-SHA256 เช…เชจเซ‡ HMAC-SHA256 เชเชจเซเช•เซเชฐเชฟเชชเซเชถเชจ เชเชฒเซเช—เซ‹เชฐเชฟเชงเชฎเซเชธเชจเซเช‚ เช…เชฎเชฒเซ€เช•เชฐเชฃ เช›เซ‡ เชœเซ‡เชฎเชพเช‚ เชนเชธเซเชคเชพเช•เซเชทเชฐเชจเซ€ เช—เชฃเชคเชฐเซ€ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชนเซ‡เช•เซเชธเชพเชกเซ‡เชธเชฟเชฎเชฒ เชจเช‚เชฌเชฐเซ‹เชจเซ€ เชธเซเชŸเซเชฐเชฟเช‚เช— เชคเชฐเซ€เช•เซ‡ เช†เช‰เชŸเชชเซเชŸ เช›เซ‡.
  • main เช เชฎเซเช–เซเชฏ เช•เชพเชฐเซเชฏ เช›เซ‡, เช•เชฎเชพเชจเซเชก เชฒเชพเช‡เชจ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเซเชธเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ URL เชนเซ‡เชจเซเชกเชฒเชฐเซเชธเชจเซ€ เชจเซ‹เช‚เชงเชฃเซ€ เช•เชฐเซ‡ เช›เซ‡.

เชธเชฐเซเชตเชฐ เชฆเซเชตเชพเชฐเชพ เชธเซเชตเซ€เช•เซƒเชค เช†เชฆเซ‡เชถ เชตเชพเช•เซเชฏ เชชเชฐเชฟเชฎเชพเชฃเซ‹:

  • -เชชเซ‹เชฐเซเชŸ เช เชชเซ‹เชฐเซเชŸ เช›เซ‡ เชœเซ‡เชจเชพ เชชเชฐ เชธเชฐเซเชตเชฐ เชธเชพเช‚เชญเชณเชถเซ‡.
  • -เชเชกเซเชฐเซ‡เชธ - IP เชธเชฐเชจเชพเชฎเซเช‚ เชœเซ‡ เชธเชฐเซเชตเชฐ เชธเชพเช‚เชญเชณเชถเซ‡.
  • -เชธเซเช•เซเชฐเชฟเชชเซเชŸ เช เชเช• เชฌเชพเชนเซเชฏ เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎ เช›เซ‡ เชœเซ‡ เชฆเชฐเซ‡เช• เช‡เชจเช•เชฎเชฟเช‚เช— เชนเซ‚เช• เชฎเชพเชŸเซ‡ เช•เชนเซ‡เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เชšเชพเชฒเซ‹ เช•เซ‡เชŸเชฒเชพเช• เช•เชพเชฐเซเชฏเซ‹ เชชเชฐ เชจเชœเซ€เช•เชฅเซ€ เชจเชœเชฐ เช•เชฐเซ€เช:

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {

    // Read body
    body, err := ioutil.ReadAll(req.Body)
    defer req.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    // log request
    log.Printf("[%s] incoming HTTP request from %sn", req.Method, req.RemoteAddr)
    // check if we got subscription confirmation request
    if strings.Contains(string(body), 
""Type":"SubscriptionConfirmation"") {
        SubscriptionConfirmation(w, req, body)
    } else {
        GotRecords(w, req, body)
    }

}

เช† เชซเช‚เช•เซเชถเชจ เชจเช•เซเช•เซ€ เช•เชฐเซ‡ เช›เซ‡ เช•เซ‡ เชจเซ‹เช‚เชงเชฃเซ€เชจเซ€ เชชเซเชทเซเชŸเชฟ เช•เชฐเชตเชพเชจเซ€ เชตเชฟเชจเช‚เชคเซ€ เช…เชฅเชตเชพ เชตเซ‡เชฌเชนเซ‚เช• เช†เชตเซ€ เช›เซ‡. เชฅเซ€ เชจเซ€เชšเซ‡ เชฎเซเชœเชฌ เช›เซ‡ เชฆเชธเซเชคเชพเชตเซ‡เชœเซ€เช•เชฐเชฃ, เชœเซ‹ เชจเซ‹เช‚เชงเชฃเซ€เชจเซ€ เชชเซเชทเซเชŸเชฟ เชฅเชพเชฏ เช›เซ‡, เชคเซ‹ เชจเซ€เชšเซ‡เชจเซ€ Json เชฐเชšเชจเชพ เชชเซ‹เชธเซเชŸ เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เชชเซเชฐเชพเชชเซเชค เชฅเชพเชฏ เช›เซ‡:

POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json

{
    "Timestamp":"2019-12-26T19:29:12+03:00",
    "Type":"SubscriptionConfirmation",
    "Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
    "TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
    "SignatureVersion":1,
    "Token":ยซRPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tAยป
}

เช† เชชเซเชฐเชถเซเชจเชจเซ‹ เชœเชตเชพเชฌ เช†เชชเชตเซ‹ เชœเชฐเซ‚เชฐเซ€ เช›เซ‡:

content-type: application/json

{"signature":ยซea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37afยป}

เชœเซเชฏเชพเช‚ เชธเชนเซ€เชจเซ€ เช—เชฃเชคเชฐเซ€ เช† เชฐเซ€เชคเซ‡ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡:

signature = hmac_sha256(url, hmac_sha256(TopicArn, 
hmac_sha256(Timestamp, Token)))

เชœเซ‹ เชตเซ‡เชฌเชนเซ‚เช• เช†เชตเซ‡ เช›เซ‡, เชคเซ‹ เชชเซ‹เชธเซเชŸ เชตเชฟเชจเช‚เชคเซ€เชจเซเช‚ เชฎเชพเชณเช–เซเช‚ เช†เชจเชพ เชœเซ‡เชตเซเช‚ เชฆเซ‡เช–เชพเชฏ เช›เซ‡:

POST <url> HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation

{ "Records":
    [
        {
            "s3": {
                "object": {
                    "eTag":"aed563ecafb4bcc5654c597a421547b2",
                    "sequencer":1577453615,
                    "key":"some-file-to-bucket",
                    "size":100
                },
            "configurationId":"1",
            "bucket": {
                "name": "bucketA",
                "ownerIdentity": {
                    "principalId":"mcs2883541269"}
                },
                "s3SchemaVersion":"1.0"
            },
            "eventVersion":"1.0",
            "requestParameters":{
                "sourceIPAddress":"185.6.245.156"
            },
            "userIdentity": {
                "principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
            },
            "eventName":"s3:ObjectCreated:Put",
            "awsRegion":"ru-msk",
            "eventSource":"aws:s3",
            "responseElements": {
                "x-amz-request-id":"VGJR5rtJ"
            }
        }
    ]
}

เชคเชฆเชจเซเชธเชพเชฐ, เชตเชฟเชจเช‚เชคเซ€เชจเชพ เช†เชงเชพเชฐเซ‡, เชคเชฎเชพเชฐเซ‡ เชกเซ‡เชŸเชพเชจเซ€ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชฐเชตเซ€ เชคเซ‡ เชธเชฎเชœเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡. เชฎเซ‡เช‚ เชธเซ‚เชšเช• เชคเชฐเซ€เช•เซ‡ เชชเซเชฐเชตเซ‡เชถ เชชเชธเช‚เชฆ เช•เชฐเซเชฏเซ‹ "Type":"SubscriptionConfirmation", เช•เชพเชฐเชฃ เช•เซ‡ เชคเซ‡ เชธเชฌเซเชธเซเช•เซเชฐเชฟเชชเซเชถเชจ เชชเซเชทเซเชŸเชฟเช•เชฐเชฃ เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เชนเชพเชœเชฐ เช›เซ‡ เช…เชจเซ‡ เชตเซ‡เชฌเชนเซ‚เช•เชฎเชพเช‚ เชนเชพเชœเชฐ เชจเชฅเซ€. POST เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เช† เชเชจเซเชŸเซเชฐเซ€เชจเซ€ เชนเชพเชœเชฐเซ€/เช—เซ‡เชฐเชนเชพเชœเชฐเซ€เชจเชพ เช†เชงเชพเชฐเซ‡, เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎเชจเซ‹ เชตเชงเซ เช…เชฎเชฒ เช•เชพเช‚ เชคเซ‹ เชซเช‚เช•เซเชถเชจเชฎเชพเช‚ เชœเชพเชฏ เช›เซ‡. SubscriptionConfirmation, เช…เชฅเชตเชพ เช•เชพเชฐเซเชฏเชฎเชพเช‚ GotRecords.

เช…เชฎเซ‡ เชธเชฌเซเชธเซเช•เซเชฐเชฟเชชเซเชถเชจ เช•เชจเซเชซเชฐเซเชฎเซ‡เชถเชจ เชซเช‚เช•เซเชถเชจเชจเซ‡ เชตเชฟเช—เชคเชตเชพเชฐ เชงเซเชฏเชพเชจเชฎเชพเช‚ เชฒเชˆเชถเซเช‚ เชจเชนเซ€เช‚; เชคเซ‡ เช†เชฎเชพเช‚ เชจเชฟเชฐเซเชงเชพเชฐเชฟเชค เชธเชฟเชฆเซเชงเชพเช‚เชคเซ‹ เช…เชจเซเชธเชพเชฐ เชฒเชพเช—เซ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เชฆเชธเซเชคเชพเชตเซ‡เชœเซ€เช•เชฐเชฃ. เชคเชฎเซ‡ เช† เชซเช‚เช•เซเชถเชจ เชฎเชพเชŸเซ‡เชจเซ‹ เชธเซเชคเซเชฐเซ‹เชค เช•เซ‹เชก เชœเซ‹เชˆ เชถเช•เซ‹ เช›เซ‹ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸ เช—เชฟเชŸ เชฐเซ€เชชเซ‹เชเซ€เชŸเชฐเซ€เช.

GotRecords เชซเช‚เช•เซเชถเชจ เช‡เชจเช•เชฎเชฟเช‚เช— เชตเชฟเชจเช‚เชคเชฟเชจเซเช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชฆเชฐเซ‡เช• เชฐเซ‡เช•เซ‹เชฐเซเชก เช‘เชฌเซเชœเซ‡เช•เซเชŸ เชฎเชพเชŸเซ‡ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เชธเชพเชฅเซ‡ เชฌเชพเชนเซเชฏ เชธเซเช•เซเชฐเชฟเชชเซเชŸ (เชœเซ‡เชจเซเช‚ เชจเชพเชฎ -script เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชฎเชพเช‚ เชชเชธเชพเชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚) เช•เซ‰เชฒ เช•เชฐเซ‡ เช›เซ‡:

  • เชกเซ‹เชฒเชจเซเช‚ เชจเชพเชฎ
  • เช‘เชฌเซเชœเซ‡เช•เซเชŸ เช•เซ€
  • เช•เซเชฐเชฟเชฏเชพ:
    • เชจเช•เชฒ - เชœเซ‹ เชฎเซ‚เชณ เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เชนเซ‹เชฏ EventName = ObjectCreated | เชชเซเชŸเช‘เชฌเซเชœเซ‡เช•เซเชŸ | เชชเซเชŸเช“เชฌเซเชœเซ‡เช•เซเชŸ เช•เซ‹เชชเซ€
    • เช•เชพเชขเซ€ เชจเชพเช–เซ‹ - เชœเซ‹ เชฎเซ‚เชณ เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เชนเซ‹เชฏ EventName = ObjectRemoved | เช‘เชฌเซเชœเซ‡เช•เซเชŸ เช•เชพเชขเซ€ เชจเชพเช–เซ‹

เช†เชฎ, เชœเซ‹ เชนเซ‚เช• เชชเซ‹เชธเซเชŸ เชตเชฟเชจเช‚เชคเซ€ เชธเชพเชฅเซ‡ เช†เชตเซ‡ เช›เซ‡, เชคเซ‹ เชตเชฐเซเชฃเชตเซเชฏเชพ เชชเซเชฐเชฎเชพเชฃเซ‡ เช‰เชšเซเชš, เช…เชจเซ‡ เชชเชฐเชฟเชฎเชพเชฃ -script=script.sh เชชเช›เซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเซ‡ เชจเซ€เชšเซ‡ เชชเซเชฐเชฎเชพเชฃเซ‡ เช•เชนเซ‡เชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡:

script.sh  bucketA some-file-to-bucket copy

เชคเซ‡ เชธเชฎเชœเชตเซเช‚ เชœเซ‹เชˆเช เช•เซ‡ เช† เชตเซ‡เชฌเชนเซ‚เช• เชชเซเชฐเชพเชชเซเชค เช•เชฐเชจเชพเชฐ เชธเชฐเซเชตเชฐ เชธเช‚เชชเซ‚เชฐเซเชฃ เช‰เชคเซเชชเชพเชฆเชจ เช‰เช•เซ‡เชฒ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เชธเช‚เชญเชตเชฟเชค เช…เชฎเชฒเซ€เช•เชฐเชฃเชจเซเช‚ เชเช• เชธเชฐเชณ เช‰เชฆเชพเชนเชฐเชฃ เช›เซ‡.

เช•เชพเชฎเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ

เชšเชพเชฒเซ‹ MCS เชฎเชพเช‚ เชฎเซเช–เซเชฏ เชฌเช•เซ‡เชŸเชฎเชพเช‚เชฅเซ€ AWS เชฎเชพเช‚ เชฌเซ‡เช•เช…เชช เชฌเช•เซ‡เชŸเชฎเชพเช‚ เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชธเชฟเช‚เช•เซเชฐเชจเชพเช‡เช เช•เชฐเซ€เช. เชฎเซเช–เซเชฏ เชฌเช•เซ‡เชŸเชจเซ‡ myfiles-ash เช•เชนเซ‡เชตเชพเชฏ เช›เซ‡, เชฌเซ‡เช•เช…เชชเชจเซ‡ myfiles-backup เช•เชนเซ‡เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ (AWS เชฎเชพเช‚ เชฌเช•เซ‡เชŸ เช—เซ‹เช เชตเชฃเซ€ เช† เชฒเซ‡เช–เชจเชพ เช…เชตเช•เชพเชถเชจเซ€ เชฌเชนเชพเชฐ เช›เซ‡). เชคเชฆเชจเซเชธเชพเชฐ, เชœเซเชฏเชพเชฐเซ‡ เชซเชพเช‡เชฒ เชฎเซเช–เซเชฏ เชฌเช•เซ‡เชŸเชฎเชพเช‚ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡เชจเซ€ เชจเช•เชฒ เชฌเซ‡เช•เช…เชช เชเช•เชฎเชพเช‚ เชฆเซ‡เช–เชพเชตเซ€ เชœเซ‹เชˆเช, เช…เชจเซ‡ เชœเซเชฏเชพเชฐเซ‡ เชคเซ‡ เชฎเซเช–เซเชฏเชฎเชพเช‚เชฅเซ€ เช•เชพเชขเซ€ เชจเชพเช–เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡เชจเซ‡ เชฌเซ‡เช•เช…เชชเชฎเชพเช‚ เช•เชพเชขเซ€ เชจเชพเช–เชตเซ€ เชœเซ‹เชˆเช.

เช…เชฎเซ‡ awscli เช‰เชชเชฏเซ‹เช—เชฟเชคเชพเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชฌเช•เซ‡เชŸเซเชธ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเซ€เชถเซเช‚, เชœเซ‡ MCS เช•เซเชฒเชพเช‰เชก เชธเซเชŸเซ‹เชฐเซ‡เชœ เช…เชจเซ‡ AWS เช•เซเชฒเชพเช‰เชก เชธเซเชŸเซ‹เชฐเซ‡เชœ เชฌเช‚เชจเซ‡ เชธเชพเชฅเซ‡ เชธเซเชธเช‚เช—เชค เช›เซ‡.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Reading package lists... Done
Building dependency tree
Reading state information... Done
After this operation, 34.4 MB of additional disk space will be used.
Unpacking awscli (1.14.44-1ubuntu1) ...
Setting up awscli (1.14.44-1ubuntu1) ...

เชšเชพเชฒเซ‹ S3 MCS API เชจเซ€ เชเช•เซเชธเซ‡เชธ เช—เซ‹เช เชตเซ€เช:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Default region name [None]:
Default output format [None]:

เชšเชพเชฒเซ‹ AWS S3 API เชจเซ€ เชเช•เซเชธเซ‡เชธ เช—เซ‹เช เชตเซ€เช:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Default region name [None]:
Default output format [None]:

เชšเชพเชฒเซ‹ เชเช•เซเชธเซ‡เชธ เชคเชชเชพเชธเซ€เช:

AWS เชจเซ‡:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup

MCS เชฎเชพเชŸเซ‡, เช†เชฆเซ‡เชถ เชšเชฒเชพเชตเชคเซ€ เชตเช–เชคเซ‡ เชคเชฎเชพเชฐเซ‡ โ€”endpoint-url เช‰เชฎเซ‡เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile mcs --endpoint-url 
https://hb.bizmrg.com
2020-02-04 06:38:05 databasebackups-0cdaaa6402d4424e9676c75a720afa85
2020-05-27 10:08:33 myfiles-ash

เชเช•เซเชธเซ‡เชธ เช•เชฐเซเชฏเซเช‚.

เชนเชตเซ‡ เช†เชตเชจเชพเชฐเชพ เชนเซ‚เช• เชชเชฐ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชเช• เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชฒเช–เซ€เช, เชšเชพเชฒเซ‹ เชคเซ‡เชจเซ‡ s3_backup_mcs_aws.sh เช•เชนเซ€เช.

#!/bin/bash
# Require aws cli
# if file added โ€” copy it to backup bucket
# if file removed โ€” remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"

SOURCE_BUCKET=""
SOURCE_FILE=""
ACTION=""

SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"

case ${ACTION} in
    "copy")
    ${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
    ${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
    rm ${TEMP}
    ;;

    "delete")
    ${AWSCLI_AWS} rm ${TARGET}
    ;;

    *)
    echo "Usage: 
#!/bin/bash
# Require aws cli
# if file added โ€” copy it to backup bucket
# if file removed โ€” remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"
SOURCE_BUCKET="${1}"
SOURCE_FILE="${2}"
ACTION="${3}"
SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"
case ${ACTION} in
"copy")
${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
rm ${TEMP}
;;
"delete")
${AWSCLI_AWS} rm ${TARGET}
;;
*)
echo "Usage: ${0} sourcebucket sourcefile copy/delete"
exit 1
;;
esac
sourcebucket sourcefile copy/delete" exit 1 ;; esac

เชšเชพเชฒเซ‹ เชธเชฐเซเชตเชฐ เชถเชฐเซ‚ เช•เชฐเซ€เช:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80 -
script scripts/s3_backup_mcs_aws.sh

เชšเชพเชฒเซ‹ เชœเซ‹เชˆเช เช•เซ‡ เชคเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡. เชฆเซเชตเชพเชฐเชพ MCS เชตเซ‡เชฌ เชˆเชจเซเชŸเชฐเชซเซ‡เชธ test.txt เชซเชพเช‡เชฒเชจเซ‡ myfiles-ash เชฌเช•เซ‡เชŸเชฎเชพเช‚ เช‰เชฎเซ‡เชฐเซ‹. เช•เชจเซเชธเซ‹เชฒ เชฒเซ‹เช— เชฆเชฐเซเชถเชพเชตเซ‡ เช›เซ‡ เช•เซ‡ เชตเซ‡เชฌเชนเซ‚เช• เชธเชฐเซเชตเชฐเชจเซ‡ เชตเชฟเชจเช‚เชคเซ€ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชนเชคเซ€:

2020/07/06 09:43:08 [POST] incoming HTTP request from 
95.163.216.92:56612
download: s3://myfiles-ash/test.txt to ../../../tmp/myfiles-ash/test.txt
upload: ../../../tmp/myfiles-ash/test.txt to 
s3://myfiles-backup/test.txt

เชšเชพเชฒเซ‹ AWS เชฎเชพเช‚ เชฎเชพเชฏเชซเชพเชˆเชฒเซเชธ-เชฌเซ‡เช•เช…เชช เชฌเช•เซ‡เชŸเชจเซ€ เชธเชพเชฎเช—เซเชฐเซ€เช“ เชคเชชเชพเชธเซ€เช:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
2020-07-06 09:43:10       1104 test.txt

เชนเชตเซ‡, เชตเซ‡เชฌ เชˆเชจเซเชŸเชฐเชซเซ‡เชธ เชฆเซเชตเชพเชฐเชพ, เช…เชฎเซ‡ myfiles-ash bucket เชฎเชพเช‚เชฅเซ€ เชซเชพเชˆเชฒ เช•เชพเชขเซ€ เชจเชพเช–เซ€เชถเซเช‚.

เชธเชฐเซเชตเชฐ เชฒเซ‹เช—เซเชธ:

2020/07/06 09:44:46 [POST] incoming HTTP request from 
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt

เชฌเช•เซ‡เชŸ เชธเชพเชฎเช—เซเชฐเซ€:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$

เชซเชพเช‡เชฒ เช•เชพเชขเซ€ เชจเชพเช–เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เชธเชฎเชธเซเชฏเชพ เชนเชฒ เชฅเชพเชฏ เช›เซ‡.

เชจเชฟเชทเซเช•เชฐเซเชท เช…เชจเซ‡ ToDo

เช† เชฒเซ‡เช–เชฎเชพเช‚ เชตเชชเชฐเชพเชฏเซ‡เชฒ เชคเชฎเชพเชฎ เช•เซ‹เชก เช›เซ‡ เชฎเชพเชฐเชพ เชญเช‚เชกเชพเชฐเชฎเชพเช‚. เชตเซ‡เชฌเชนเซ‚เช•เชจเซ€ เชจเซ‹เช‚เชงเชฃเซ€ เชฎเชพเชŸเซ‡ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเชพ เช‰เชฆเชพเชนเชฐเชฃเซ‹ เช…เชจเซ‡ เช—เชฃเชคเชฐเซ€ เชธเชนเซ€เช“เชจเชพ เช‰เชฆเชพเชนเชฐเชฃเซ‹ เชชเชฃ เช›เซ‡.

เช† เช•เซ‹เชก เชคเชฎเซ‡ เชคเชฎเชพเชฐเซ€ เชชเซเชฐเชตเซƒเชคเซเชคเชฟเช“เชฎเชพเช‚ S3 เชตเซ‡เชฌเชนเซเช•เซเชธเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เชคเซ‡เชจเชพ เช‰เชฆเชพเชนเชฐเชฃ เชธเชฟเชตเชพเชฏ เชฌเซ€เชœเซเช‚ เช•เช‚เชˆ เชจเชฅเซ€. เชฎเซ‡เช‚ เชถเชฐเซ‚เช†เชคเชฎเชพเช‚ เช•เชนเซเชฏเซเช‚ เชคเซ‡เชฎ, เชœเซ‹ เชคเชฎเซ‡ เช‰เชคเซเชชเชพเชฆเชจเชฎเชพเช‚ เช†เชตเชพ เชธเชฐเซเชตเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซ€ เชฏเซ‹เชœเชจเชพ เช˜เชกเซ€ เชฐเชนเซเชฏเชพ เชนเซ‹, เชคเซ‹ เชคเชฎเชพเชฐเซ‡ เช“เช›เชพเชฎเชพเช‚ เช“เช›เชพ เช…เชธเซเชฎเซ‡เชณ เช•เชพเชฐเซเชฏ เชฎเชพเชŸเซ‡ เชธเชฐเซเชตเชฐเชจเซ‡ เชซเชฐเซ€เชฅเซ€ เชฒเช–เชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡: เช‡เชจเช•เชฎเชฟเช‚เช— เชตเซ‡เชฌเชนเซเช•เซเชธเชจเซ‡ เช•เชคเชพเชฐเชฎเชพเช‚ เชฐเชœเซ€เชธเซเชŸเชฐ เช•เชฐเซ‹ (เชฐเซ‡เชฌเชฟเชŸเชเชฎเช•เซเชฏเซ เช…เชฅเชตเชพ เชเชจเชเชŸเซ€เชเชธ), เช…เชจเซ‡ เชคเซเชฏเชพเช‚เชฅเซ€ เชคเซ‡เชจเซเช‚ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเซ‹ เช…เชจเซ‡ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเซ‹. เช•เชพเชฎเชฆเชพเชฐ เช…เชฐเชœเซ€เช“ เชธเชพเชฅเซ‡. เชจเชนเชฟเช‚เชคเชฐ, เชœเซเชฏเชพเชฐเซ‡ เชตเซ‡เชฌเชนเซเช•เซเชธ เชฎเซ‹เชŸเชพ เชชเชพเชฏเซ‡ เช†เชตเซ‡ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เชคเชฎเชจเซ‡ เช•เชพเชฐเซเชฏเซ‹ เชชเซ‚เชฐเซเชฃ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชธเชฐเซเชตเชฐ เชธเช‚เชธเชพเชงเชจเซ‹เชจเซ€ เช…เช›เชคเชจเซ‹ เชธเชพเชฎเชจเซ‹ เช•เชฐเชตเซ‹ เชชเชกเซ€ เชถเช•เซ‡ เช›เซ‡. เช•เชคเชพเชฐเซ‹เชจเซ€ เชนเชพเชœเชฐเซ€ เชคเชฎเชจเซ‡ เชธเชฐเซเชตเชฐ เช…เชจเซ‡ เช•เชพเชฎเชฆเชพเชฐเซ‹เชจเซ‡ เชตเชฟเชคเชฐเชฟเชค เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡, เชคเซ‡เชฎเชœ เชจเชฟเชทเซเชซเชณเชคเชพเชจเชพ เช•เชฟเชธเซเชธเชพเชฎเชพเช‚ เชชเซเชจเชฐเชพเชตเชฐเซเชคเชฟเชค เช•เชพเชฐเซเชฏเซ‹ เชธเชพเชฅเซ‡ เชธเชฎเชธเซเชฏเชพเช“ เชนเชฒ เช•เชฐเซ‡ เช›เซ‡. เชฒเซ‹เช—เซ€เช‚เช—เชจเซ‡ เชตเชงเซ เชตเชฟเช—เชคเชตเชพเชฐ เช…เชจเซ‡ เชตเชงเซ เชชเซเชฐเชฎเชพเชฃเชฟเชคเชฎเชพเช‚ เชฌเชฆเชฒเชตเชพเชจเซ€ เชชเชฃ เชธเชฒเชพเชน เช†เชชเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เชธเชซเชณเชคเชพ!

เชตเชฟเชทเชฏ เชชเชฐ เชตเชงเซ เชตเชพเช‚เชšเชจ:

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹