latest log

酩酊状態で書いたエンジニアポエムです。酩酊状態で読んでください。

nginxがシンボリックリンクで403を返す

nginxが403を返す理由は様々です。

まずはこちらをざざっと参照し、気になるポイントがあったら試してみましょう:

www.1and1.com

僕は時々はシンボリックリンクを設定して403になってしまい頭を抱えてしまいます。数年に一回ぐらいのペースでやらかすので、毎回ググってるんですよね。

たとえば以下のように、your-project 以下に存在する assets ディレクトリを https://localhost/assets でアクセスできるようにしようとして、シンボリックリンクを設定すると403になったりします。

$ cd your-project
$ ln -s assets /usr/local/var/www/assets

この場合は nginx.conf に location /assets/ を追加すると良いでしょう。

  location /assets/ {
    root /usr/local/var/www/your-project/;
  }

蛇足になりますが、慣れていないと以下のように書いてしまいがちです。 このように設定すると nginx は https://localhost/assets へのアクセスを your-project/assets/assets/ として解決しようとします。 この試みは失敗し404が帰るでしょう。

# これはダメな例です
  location /assets/ {
    root /usr/local/var/www/your-project/assets/;
  }

こちらの記事も参考にしてください:

ja.stackoverflow.com

macで起動しているnginxに外部からアクセスできない? ひょっとしてファイアーウォールがONになっていませんか?

f:id:uupaa:20180623012401p:plain

気がついたらiPhoneからmac上のnginxにアクセスできなくなってて(OS入れ替えの時にONに戻ったらしい)、さらに僕はこの設定の存在自体をど忘れしてしまって、なんだかんだで2時間ほど悩みました ><

ルータの設定をみなおしたり、nginxの設定色々変えたり見直したり、ディレクトリのパーミッションを見直したり、Proxy立てたり、あと沢山ググったよね… そんでファイアーウォールの設定をOFFにしたら一発で開通したよね…


macOS Sierra などでは、コマンドライン上から socketfilterfw を使ってもうまく設定できなくなっているようですので、GUI上でOFFにしましょう。

参考リンク:

macos - 80番ポートで起動させているnginxのWebサーバーに外部からアクセスできない - スタック・オーバーフロー

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add `readlink \`which nginx\``
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp `readlink \`which nginx\``

What I feel React Native.

一度書けばどこでも動く系の技術は、 深さを犠牲に面積を取りに行く戦略(高機能性はネイティブAppには勝てないけど、そのかわりにスピードと面を取りに行く戦略)なので、 それを忘れて、銀の弾丸風に「80%はこれでカバーできる」「まだNativeでかいてるの?」「とりあえずビール」という感じのムードになると、(ちゃんと理解して使おうとしない層が大挙して押し寄せる事で) React Native もこれまでの何かのように早逝の道にルートが切り替わると思うので、過去の類似技術の失敗例を参考に、技術を育てていくのも大事だと思うのです。

過去の例だと、

  • 適材適所という言葉がいつの間にか失われてた
  • ムード先行で、実際の事例がしょぼかった
  • 成功例だけが大きく宣伝され、失敗事例となぜ失敗したかが共有されなかった

みたいな感じでしたっけ

An interesting recent browser API for me.

ethos agent tools: Add NightShift mode. it can reduce fan noise.

ethos-agent は ethOS を強化するツールです。

今日は、ethos-agent に夜間の騒音を低減する、NightShiftモードというものを追加しました。

NightShift を有効にすると、20:00〜05:00 の間は自動的にFanの回転数を一時的に下げ、静音化が可能になります。朝になると local.conf で設定している値に自動的に復帰します。

rigと同じ部屋で生活している人にとっては朗報でしょう。ほとんどrigの存在を気にせずに済むようになるはずです。

開発ログ

/etc/rc.local に設定するコマンドを以下のように、su -l -s -c ... と工夫することで、root ユーザでも、 /usr/bin/sudo /usr/bin/nvidia-settings -a [gpu:0]/GPUFanControlState=1 -a [fan:${index}]/GPUTargetFanSpeed="40" が実行可能になりました。

単純に /usr/bin/node --experimental-modules /home/ethos/ethos-agent/index.mjs だけだと、error: XDG_RUNTIME_DIR not set in the environment でコケてしまいます。

su -l ethos -s /bin/bash -c '/usr/bin/node --experimental-modules /home/ethos/ethos-agent/index.mjs

eslint の async/await サポートと rollup の dynamic import サポート

github.com を update しました。

最新の eslint が async/await に対応し、

{
  "parserOptions": {
    "ecmaVersion":  2017
  }
}

最新の rollup がフラグ付きながら import() に対応しました。

$ rollup --experimentalDynamicImport

これで eslint + rollup な bundle 環境における ES2017 + import() 対応がほぼ出揃った感じになりました。

npm で公開されているパッケージも、徐々に ES Modules にマイグレーションしていく流れができてきました。

2018/06/28 追記

dynamic import はeslintが公式にはサポートしてないため、 .eslinttc に "parser": "babel-eslint" を追加し、$ npm i -D babel-eslint を追加することでエラーを消す事ができます。

examples

// a.js
export class Foo {
  async fetch() {
    return new Promise(async(resolve, reject) => {
      try {
        const url = `https://localhost`;
        const text = await(await fetch(url)).text();
        await import("./b.js");

        resolve(text);
      } catch(err) {
        reject(err);
      }
    });
  }
}

(async() => {
  const foo = new Foo();
  const html = await foo.fetch();
  alert(html);
})();
// b.js
alert("b.js");
<!-- index.html -->
<script type="module" src="a.js"></script>

.eslintrc

{
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaVersion":      2017,
    "sourceType":       "module"
  },
  "env": {
    "browser":          true,
    "node":             true,
    "es6":              true
  },
  "extends": [
    "eslint:recommended"
  ],
  "rules": {
    "strict":           [0],
    "no-new":           [0],
    "new-cap":          [0],
    "no-empty":         [0],
    "no-shadow":        [0],
    "camelcase":        [0],
    "key-spacing":      [0],
    "dot-notation":     [0],
    "comma-dangle":     [0],
    "no-console":       [0],
    "no-multi-str":     [0],
    "no-multi-spaces":  [0],
    "no-control-regex": [0],
    "no-unused-vars":   [1, { "vars": "all", "args": "after-used"} ],
    "no-underscore-dangle": [0],
    "no-use-before-define": [0],
    "no-inner-declarations": [0]
  },
  "globals": {
    "unescape":         false,
    "escape":           false,
    "google":           false
  }
}

package.json

{
  "name": "app",
  "version": "0.0.0",
  "description": "",
  "main": "a.js",
  "scripts": {
    "bundle": "npm run bundle:es6",
    "bundle:es6": "rollup -c .rollup.es6.js",
    "bundle:es5": "rollup -c .rollup.es5.js"
  },
  "repository": {
    "type": "git",
    "url": "..."
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "babel-eslint": "^8.2.5",
    "babel-preset-es2015-rollup": "^3.0.0",
    "eslint": "^5.0.1",
    "execa": "^0.10.0",
    "npm-run-all": "^4.1.3",
    "request": "",
    "rollup": "^0.62.0",
    "rollup-plugin-babel": "^3.0.5",
    "rollup-plugin-buble": "^0.19.2",
    "rollup-plugin-cleanup": "^3.0.0-beta.1",
    "rollup-plugin-commonjs": "^9.1.3",
    "rollup-plugin-eslint": "^4.0.0",
    "rollup-plugin-license": "^0.6.0",
    "rollup-plugin-node-resolve": "^3.3.0",
    "rollup-watch": "^4.3.1",
  }
}

.rollup.es6.js

import path from "path";
import resolve from "rollup-plugin-node-resolve"; // resolve node_modules/index.js to ES6
import commonjs from "rollup-plugin-commonjs";    // convert CommonJS -> ES6
//import buble from "rollup-plugin-buble";          // convert ES6 -> ES5
import eslint from "rollup-plugin-eslint";        // ESLint
//import cleanup from "rollup-plugin-cleanup";      // clear comments and empty lines
import license from "rollup-plugin-license";      // add License header

// --- ES5/ES6/CommonJS/ESModules -> ES6 bundle ---
export default {
  format: "es",
  entry: "a.js",
  dest: "bundle.es6.js",
  plugins: [
    resolve({ jsnext: true }),
    commonjs(),
  //buble(), // ES6 -> ES5
    eslint({ configFile: path.resolve("./.eslintrc") }),
    //cleanup(),
    license({
      banner: "",
      //thirdParty: {
      //  output: path.join(__dirname, "dependencies.txt"),
      //  includePrivate: true, // Default is false.
      //},
    }),
  ],
  intro: "",
  outro: "",
  banner: "",
  footer: "",
}

これらのファイルを用意して、 $ npm run bundle を実行すると、以下の bundle.es6.js が生成されます。

bundle.es6.js

class Foo {
  async fetch() {
    return new Promise(async(resolve, reject) => {
      try {
        const url = `https://localhost`;
        const text = await(await fetch(url)).text();
        await Promise.resolve().then(function () { return b; });

        resolve(text);
      } catch(err) {
        reject(err);
      }
    });
  }
}

(async() => {
  const foo = new Foo();
  const html = await foo.fetch();
  alert(html);
})();

alert("b.js");

var b = /*#__PURE__*/Object.freeze({

});

export { Foo };