From b03d622696db6ea7a49560d2814bd766273dd220 Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:22:57 +0900 Subject: [PATCH 1/7] feat: Add enablesendfile-js-broken --- public/enablesendfile-js-broken.md | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 public/enablesendfile-js-broken.md diff --git a/public/enablesendfile-js-broken.md b/public/enablesendfile-js-broken.md new file mode 100644 index 0000000..01f7fbd --- /dev/null +++ b/public/enablesendfile-js-broken.md @@ -0,0 +1,62 @@ +--- +title: "仮想環境で開発中 JavaScript が途中で途切れて壊れる場合の対処法" +tags: + - "Programming" + - "Windows" + - "Apache" + - "Vagrant" + - "webpack" +private: false +updated_at: '' +id: null +organization_url_name: null +slide: false +ignorePublish: false +--- + +Vagrant (VirtualBox) + Apache + webpackでコンパイルされたJavaScriptやCSSが途中で途切れて壊れる場合の対処法を紹介します。 + +## gulp.js の watch モードで JS が壊れる + +フロントの開発時、gulp.jsのwatchモードを用いてwebpackコンパイルを自動で行うよう設定されているプロジェクトで開発していていました。 + +しかし、なぜか半分の割合で、生成されたJSが途中で切れてしまいます。当然ブラウザ上ではエラーで停止します。 + +ファイルを直接見るとまったく問題がなく、Apacheの再起動するとすぐに復活するため、Webサーバーのキャッシュの問題を疑いました。 + +## 原因 + +EnableSendfileというApacheの機能が影響していました。 + +https://httpd.apache.org/docs/2.4/mod/core.html#enablesendfile + +公式ドキュメントには次の記載があります。 + +> デフォルトでは、 例えば静的なファイルの配送のように、リクエストの処理にファイルの 途中のデータのアクセスを必要としないときには、Apache は OS が サポートしていればファイルを読み込むことなく sendfile を使って ファイルの内容を送ります。 + +そして、その下に次の記載があります。 + +> しかし、プラットフォームやファイルシステムの中には運用上の問題を避けるためにこの機能を使用不可にした方が良い場合があります: +> ネットワークマウントされた DocumentRoot (例えば NFS や SMB) では、カーネルは自身のキャッシュを使ってネットワークからのファイルを 送ることができないことがあります。 + +ファイルのキャッシュが中途半端なタイミングで行われてしまい、途中で途切れた状態が出力されてしまうというのが原因なようです。 + +次の記事のようにNFSを使用するように設定している場合に発生します。VirtualBox初期設定のファイル共有では発生しません。 + +https://bicstone.me/vagrant-laravel-slow/ + +## EnableSendfile を無効にする + +EnableSendfile機能を無効にします。若干の速度低下があるようですが、(VirtualBoxを用いている時点で遅いので)よっぽど大量のリクエストを行っていない場合は問題ありません。 + +httpd.confのEnableSendfileをOffにします。 + +```ini +EnableSendfile off +``` + +または、.htaccessに設定します。 + +```ini +EnableSendfile off +``` From 2b8a41e8e5bba80a5a4c7d58e4ab857f9acd2cfd Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:23:13 +0900 Subject: [PATCH 2/7] feat: Add javascript-blob-to-file --- public/javascript-blob-to-file.md | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 public/javascript-blob-to-file.md diff --git a/public/javascript-blob-to-file.md b/public/javascript-blob-to-file.md new file mode 100644 index 0000000..1b939db --- /dev/null +++ b/public/javascript-blob-to-file.md @@ -0,0 +1,64 @@ +--- +title: "オブジェクト URL を File または Blob オブジェクトに変換する方法" +tags: + - "Programming" + - "JavaScript" + - "blob" + - "XMLHttpRequest" + - "fetch" +private: false +updated_at: '' +id: null +organization_url_name: null +slide: false +ignorePublish: false +--- + +JavaScriptのオブジェクトURLをFileオブジェクトまたはBlobオブジェクトに戻す(変換する)方法を紹介します。 `URL.createObjectURL()` の逆を行います。 + +## オブジェクト URL とは + +オブジェクトURLは、JavaScriptで次のようにメゾットを呼び出すことで生成されます。 + +```js +URL.createObjectURL(object); +``` + +https://developer.mozilla.org/ja/docs/Web/API/URL/createObjectURL + +ファイルを処理したり、ユーザーからファイルを受け取るライブラリなどで、オブジェクトURLで返ってきますが、データを処理したいのでFileオブジェクトやBlobオブジェクトに戻したいケースがあります。 + +しかし、File APIには `URL.createObjectURL(object);` の逆が用意されていません。 + +例えば、 [`react-dropzone`](https://github.com/react-dropzone/react-dropzone) というReactのライブラリではオブジェクトURLで返ってきます。 + +## File オブジェクトに戻す方法 + +なんの変哲もない対処方法なのですが、URLなので、 `fetch()` または `XMLHttpRequest` を使用すればFileオブジェクトに戻すことができます。 + +### `fetch()` を用いた方法 + +ES5が動作する環境であれば `fetch()` を用いた方法がおすすめです。 + +[Can I Use](https://caniuse.com/#feat=fetch)によると、IE、古すぎるEdge、Opera mini以外であれば動作するようです。対象外のブラウザでも[polyfill](https://github.com/github/fetch)を導入したり、トランスコンパイルをすれば動作します。 + +```js +let file = await fetch(url).then((r) => r); +let blob = await fetch(url).then((r) => r.blob()); +``` + +### `XMLHttpRequest` を用いた方法 + +古き良き、`XMLHttpRequest` を用いても取得できます。 + +[Can I Use](https://caniuse.com/#feat=mdn-api_xmlhttprequest)によると、現在の主要ブラウザはすべて動作するようです。 + +```js +var xhr = new XMLHttpRequest(); +xhr.open("GET", url, true); +xhr.responseType = "blob"; +xhr.onload = function () { + var blob = this.response; +}; +xhr.send(); +``` From 3f3ac3142274beac85d0bc83f0331bd406e8c30f Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:23:32 +0900 Subject: [PATCH 3/7] feat: Add mysql-auto-increment-reset --- public/mysql-auto-increment-reset.md | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 public/mysql-auto-increment-reset.md diff --git a/public/mysql-auto-increment-reset.md b/public/mysql-auto-increment-reset.md new file mode 100644 index 0000000..b580a63 --- /dev/null +++ b/public/mysql-auto-increment-reset.md @@ -0,0 +1,65 @@ +--- +title: "MySQL で、 AUTO INCREMENT の値が時々リセットされる原因" +tags: + - "Programming" + - "MySQL" + - "InnoDB" + - "AUTOINCREMENT" + - "RDBMS" +private: false +updated_at: '' +id: null +organization_url_name: null +slide: false +ignorePublish: false +--- + +MySQL 5.6のInnoDBデータベースでAUTO INCREMENTのカウンター値が時々リセットされ、物理削除後の値が再度使用されてしまう可能性がある原因と対処法を紹介します。 + +## 現象 + +私が関わっていたプロジェクトで、AUTO INCREMENTのカラムなのに物理削除後の値が再利用されるという不具合が発生しました。 + +ユーザーテーブルとして、会員IDをプライマリキーかつAUTO INCREMENTで設定しており、削除したらテーブルから物理削除する仕様になっていました。 + +ある日、削除済みの会員IDと、登録されていた会員IDが重複するという不具合が発生しました。 + +## 原因 + +MySQL5系のInnoDBデータベースでは、再起動されるとAUTO INCREMENTカウンターがリセットされ、次のSQL結果の値に設定されると公式ドキュメントに記載されています。 + +```sql +SELECT MAX(ai_col) FROM t FOR UPDATE;` +``` + +https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html + +MySQLが再起動されると連番の一番大きい値にカウンターがリセットされるという実装になっています。 + +つまり、最大値のレコードが物理削除された後に再起動されると、その値が再度使用されてしまうということです。AUTO INCREMENTカウンターをシーケンスであると完全に信頼して設計していたので、拍子抜けしましたし、実装を理解せずに使用して恥ずかしいです。 + +## 対処方法 + +### MySQL のバージョンアップ + +MySQL8系ではこの実装が変更されています。 + +公式ドキュメントによると、カウンター値をメモリでなくディスクに保存するように変更されたので、MySQLの再起動後もカウンター値が維持されるとのことです。 + +バージョンアップできれば、バージョンアップで対処できます。 + +> In MySQL 8.0, this behavior is changed. The current maximum auto-increment counter value is written to the redo log each time it changes and is saved to an engine-private system table on each checkpoint. These changes make the current maximum auto-increment counter value persistent across server restarts. + +https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html#innodb-auto-increment-initialization + +### 論理削除にする + +論理削除にすれば、レコードが削除されないのでリセットされても影響はなくなります。 + +### 採番テーブルを使用する + +今回のプロジェクトでは、急遽古き良き採番テーブルを使用する方法を取りました。 + +## まとめ + +特定のRDBMSの機能に依存するのは手軽ですが、仕様を確認して見極めて使っていきたいです。 From d286e1032c130edf94c9caf5c962cc42a3a0ecf4 Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:23:47 +0900 Subject: [PATCH 4/7] feat: Add python-zipfile-shift-jis --- public/python-zipfile-shift-jis.md | 75 ++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 public/python-zipfile-shift-jis.md diff --git a/public/python-zipfile-shift-jis.md b/public/python-zipfile-shift-jis.md new file mode 100644 index 0000000..ed3b08d --- /dev/null +++ b/public/python-zipfile-shift-jis.md @@ -0,0 +1,75 @@ +--- +title: "PythonでアーカイブしたZIPファイル名をShift-JISにする" +tags: + - "Programming" + - "Python" + - "Windows" + - "Zip" + - "Shift-JIS" +private: false +updated_at: '' +id: null +organization_url_name: null +slide: false +ignorePublish: false +--- + +Pythonのzipfileライブラリはファイル名をUTF-8でエンコードするためWindowsのレガシーな解凍ソフトで解凍するとファイル名が文字化けします。ファイル名をShift-JISでエンコードする方法を紹介します。 + +※ これは2019-07-18に個人ブログで公開した記事を移植したものです。 + +## 世の中には UTF-8 で文字化けする解凍ソフトが残っている + +2007年9月にZIPの仕様が追加され、エンコードをUTF-8に統一するための仕組みが完成してから、ZIPファイル名はUTF-8にエンコードすることがスタンダードになりつつあります。 + +https://support.pkware.com/home/pkzip/developer-tools/appnote + +しかし、日本国内では、UTF-8に未対応の解凍ソフト(+Lhaca Lhaplusなど)を使っているユーザーが多くいます。(WindowsのエクスプローラーだけでUTF-8のZIP解凍できるのに) + +## ファイル名を Shift-JIS でエンコードできるのか + +全ユーザーを説得して各UTF-8未対応の解凍ソフトをアンインストールして回るわけにもいかないので、ファイル名をShift-JISでエンコードする方法を考えます。 + +まず、CPythonのzipfileライブラリのソースコードを見てみます。 + +https://github.com/python/cpython/blob/3.7/Lib/zipfile.py#L454 + +CPython3.7では、454行目にファイル名のエンコードの関数があります。抜粋すると次の通りです。 + +```py + def _encodeFilenameFlags(self): + try: + return self.filename.encode('ascii'), self.flag_bits + except UnicodeEncodeError: + return self.filename.encode('utf-8'), self.flag_bits | 0x800 +``` + +まずASCIIでのエンコードを施行して、 `UnicodeEncodeError` ならば(=ASCIIでなければ)「UTF-8」でエンコードするようにハードコードされていました…。 + +## 標準ライブラリをコピーして Shift-JIS に変更する + +あまりしたくないですが…。標準ライブラリをコピーしてShift-JISに対応します。 454行目の `'utf-8'` を `'cp932'` に変更します。また、フラグ `0x800` を削除します。 + +ちなみに、`0x800` は、ZIPの規格で定められた「general purpose bit flag」のBit 11を `1` にしています(16進数 `800`=2進数 `100000000000`)。これは、前述のエンコードをUTF-8に統一するための仕組みで、規格では「Language encoding flag (EFS). If this bit is set, the filename and comment fields for this file MUST be encoded using UTF-8.」と定められており、UTF-8でなければ立ててはいけないフラグなので取り除いています。 + +https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT + +zipfile.py + +https://github.com/python/cpython/blob/3.7/Lib/zipfile.py#L454 + +```diff +454-: return self.filename.encode('utf-8'), self.flag_bits | 0x800 +454+: return self.filename.encode('cp932'), self.flag_bits +``` + +`import` 先を今回作ったzipfile.pyに変更します。 + +```py +from .zipfile import ZipFile +# ... +with ZipFile(zb, mode='w') as zf: + # ... +``` + +以上の対策で、Windowsのレガシーな解凍ソフトで解凍できるようになります。逆にLinuxなどではUTF-8しか対応していない場合文字化けする可能性があります。 From f0f993d7c7b9633a00477150cb1efa298835ed67 Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:24:03 +0900 Subject: [PATCH 5/7] feat: Add xserver-pre-ssl --- public/xserver-pre-ssl.md | 105 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 public/xserver-pre-ssl.md diff --git a/public/xserver-pre-ssl.md b/public/xserver-pre-ssl.md new file mode 100644 index 0000000..b0d7dbb --- /dev/null +++ b/public/xserver-pre-ssl.md @@ -0,0 +1,105 @@ +--- +title: "エックスサーバーの無料独自SSLをサイト移転前に設定する方法" +tags: + - "Web" + - "PHP" + - "Apache" + - "Programming" + - "htaccess" +private: false +updated_at: '' +id: null +organization_url_name: null +slide: false +ignorePublish: false +--- + +エックスサーバー・スターサーバーの無料独自SSL設定をサイト移転前に設定し、SSLで接続できなくなる問題を回避する方法を紹介します。 + +※スクリーンショットはスターサーバーの管理画面ですが同じ業者であるエックスサーバーでも同様に設定可能です。 + +※ これは2019-01-01に個人ブログで公開した記事を移植したものです。 + +## サイト公開しないと無料独自 SSL 設定ができない + +当ブログはMixHostからスターサーバーへ移転しました。移転時に一番問題だと感じたのが、サイトをスターサーバーで公開しないと無料独自SSL設定ができないため、一定時間SSLが使用できないというダウンタイムが存在してしまうことでした。 + +スターサーバーにドメイン追加後、SSL設定より「無料独自SSL追加」を行ってもエラーが発生したと表示され設定ができません。 + +![スターサーバー管理画面の無料独自SSL追加時にエラーが発生](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/16fa4e63-498a-c278-c4af-fd46dbad002d.png) + +この状態でネームサーバーの設定を変え新サーバーにアクセスが行ってしまうと、SSL検証エラーとなり、SSLを設定するまでの間ダウンタイムとなってしまいます。また、HOSTSファイルを使用して新サーバーでの動作確認も行えません。 + +![Google Chrome のSSLエラー 「この接続ではプライバシーが保護されません」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/c75c1ae4-00e5-a93c-8242-be39a82ec6c1.png) + +## SSL 設定時の認証 + +エックスサーバーやスターサーバーの「無料独自SSL」は「Let's Encrypt Authority X3」を使用しています。認証はLet's Encryptが行っています。 + +Let's EncryptのWeb認証では、`http://example.com/.well-known/acme-challenge/` の直下にLet's Encryptから指示された認証用一時ファイルを設置し、存在が確認されることで行われます。 + +エックスサーバーやスターサーバーでも「無料独自SSL追加」を行うと設定するサーバーの `/.well-known/acme-challenge/` の直下に認証用一時ファイルを設置しています。 + +https://letsencrypt.readthedocs.io/en/latest/using.html + +## 移転前動作確認 URL でも認証ファイルにアクセスが可能 + +認証を通すためにはエックスサーバーやスターサーバーに設置された認証用一時ファイルへアクセスできるようにする必要があります。 + +エックスサーバーやスターサーバーには「移転前動作確認URL」という機能があり、この機能で作成されたURLでも `/.well-known/acme-challenge/` にアクセスが可能になっています。 + +https://www.xserver.ne.jp/manual/man_domain_checkproxy.php + +https://www.star.ne.jp/manual/domain_checkproxy.php + +## 対処方法 + +1. 「移転前動作確認URL」の設定から動作確認URLを入手します。 + +![「移転前動作確認URL」の設定から動作確認URLを入手します。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/63884fd3-31fd-7d1c-8ee4-b561a43fef58.png) + +2. 移転前のサーバーに `/.well-known/acme-challenge/` までのフォルダを作成します。 + +3. `/.well-known/acme-challenge/` の直下に次の `.htaccess` ファイルと `index.php` を設置します。 + +`index.php` + +`http://masshiro-blog.check-star.jp/(アクセスされたURL)` にデータを取得しに行き、そのまま返すプログラムです。 + +URLは `/.well-known/acme-challenge/(英数字-_)` 以外の場合弾くようにしています。 + +`http://masshiro-blog.check-star.jp/` の部分は移転前動作確認URLに置き換えてください。 + +```php + +``` + +`.htaccess` + +WordPressでもお馴染み、直下へのすべてのアクセスを `index.php` に転送するプログラムです。 + +```plain + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule (.*) index.php?/$1 [L] + +``` + +4. SSL設定より「無料独自SSL追加」を行う。 + +![SSL設定より「無料独自SSL追加」を行う。独自SSLを追加しましたのメッセージが表示される](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/b45d2ea7-dd51-94e2-ef33-30199a117c93.png) + +5. index.php及び.htaccessを削除する。 From 98e6b24a3b8a66485f33be91752f0599b1bc54d1 Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:27:47 +0900 Subject: [PATCH 6/7] Updated by qiita-cli --- public/enablesendfile-js-broken.md | 16 ++++++++-------- public/javascript-blob-to-file.md | 16 ++++++++-------- public/mysql-auto-increment-reset.md | 16 ++++++++-------- public/python-zipfile-shift-jis.md | 16 ++++++++-------- public/xserver-pre-ssl.md | 16 ++++++++-------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/public/enablesendfile-js-broken.md b/public/enablesendfile-js-broken.md index 01f7fbd..30d0f3b 100644 --- a/public/enablesendfile-js-broken.md +++ b/public/enablesendfile-js-broken.md @@ -1,14 +1,14 @@ --- -title: "仮想環境で開発中 JavaScript が途中で途切れて壊れる場合の対処法" +title: 仮想環境で開発中 JavaScript が途中で途切れて壊れる場合の対処法 tags: - - "Programming" - - "Windows" - - "Apache" - - "Vagrant" - - "webpack" + - Windows + - Apache + - プログラミング + - Vagrant + - webpack private: false -updated_at: '' -id: null +updated_at: "2024-03-03T20:26:37+09:00" +id: 16ccb0350a16ab6b42aa organization_url_name: null slide: false ignorePublish: false diff --git a/public/javascript-blob-to-file.md b/public/javascript-blob-to-file.md index 1b939db..5d3df1a 100644 --- a/public/javascript-blob-to-file.md +++ b/public/javascript-blob-to-file.md @@ -1,14 +1,14 @@ --- -title: "オブジェクト URL を File または Blob オブジェクトに変換する方法" +title: オブジェクト URL を File または Blob オブジェクトに変換する方法 tags: - - "Programming" - - "JavaScript" - - "blob" - - "XMLHttpRequest" - - "fetch" + - JavaScript + - プログラミング + - blob + - XMLHttpRequest + - fetch private: false -updated_at: '' -id: null +updated_at: "2024-03-03T20:26:26+09:00" +id: 5796124885a3ea92adc2 organization_url_name: null slide: false ignorePublish: false diff --git a/public/mysql-auto-increment-reset.md b/public/mysql-auto-increment-reset.md index b580a63..0a9e167 100644 --- a/public/mysql-auto-increment-reset.md +++ b/public/mysql-auto-increment-reset.md @@ -1,14 +1,14 @@ --- -title: "MySQL で、 AUTO INCREMENT の値が時々リセットされる原因" +title: MySQL で、 AUTO INCREMENT の値が時々リセットされる原因 tags: - - "Programming" - - "MySQL" - - "InnoDB" - - "AUTOINCREMENT" - - "RDBMS" + - MySQL + - プログラミング + - RDBMS + - InnoDB + - autoincrement private: false -updated_at: '' -id: null +updated_at: "2024-03-03T20:26:26+09:00" +id: 480d7a443eebd0a856e2 organization_url_name: null slide: false ignorePublish: false diff --git a/public/python-zipfile-shift-jis.md b/public/python-zipfile-shift-jis.md index ed3b08d..63da183 100644 --- a/public/python-zipfile-shift-jis.md +++ b/public/python-zipfile-shift-jis.md @@ -1,14 +1,14 @@ --- -title: "PythonでアーカイブしたZIPファイル名をShift-JISにする" +title: PythonでアーカイブしたZIPファイル名をShift-JISにする tags: - - "Programming" - - "Python" - - "Windows" - - "Zip" - - "Shift-JIS" + - Python + - Windows + - プログラミング + - zip + - Shift-JIS private: false -updated_at: '' -id: null +updated_at: "2024-03-03T20:24:24+09:00" +id: 14ef11e80cf8d36004c2 organization_url_name: null slide: false ignorePublish: false diff --git a/public/xserver-pre-ssl.md b/public/xserver-pre-ssl.md index b0d7dbb..ef09f18 100644 --- a/public/xserver-pre-ssl.md +++ b/public/xserver-pre-ssl.md @@ -1,14 +1,14 @@ --- -title: "エックスサーバーの無料独自SSLをサイト移転前に設定する方法" +title: エックスサーバーの無料独自SSLをサイト移転前に設定する方法 tags: - - "Web" - - "PHP" - - "Apache" - - "Programming" - - "htaccess" + - PHP + - Apache + - プログラミング + - Web + - htaccess private: false -updated_at: '' -id: null +updated_at: "2024-03-03T20:26:26+09:00" +id: 25f86b63880214f5c96e organization_url_name: null slide: false ignorePublish: false From 1c9dc0f2854d9ab5f1980272076a0daccd123ac7 Mon Sep 17 00:00:00 2001 From: Takanori Oishi Date: Sun, 3 Mar 2024 20:29:47 +0900 Subject: [PATCH 7/7] fix: Fix markdownlint --- .markdownlint.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index f2d969f..cf1f3c2 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,5 +1,6 @@ { - "default": true, "MD013": false, - "MD034": false + "MD029": false, + "MD034": false, + "default": true }