ラック
Home > ブログ > 記事 > 2018年9月 > サーバ上でmarkdown-pdfを動かす

サーバ上でmarkdown-pdfを動かす

カテゴリ: Web自作,タスク管理

Trello APIを使ってデータを抽出し、タスクのうち

  • 期限が設定されている
  • 期限に完了としてチェックが付けられている

の2つを満たすカードは、「作業が完了した実績」として一覧で表示するプログラムを以前作成しました。

この一覧表示はBootstrapのリストを使用してWebページ上に一覧として表示できるだけでなく、textareaタグ内にMarkdown形式でも表示します。

これは、textarea内を全選択、ローカルにmdファイルとして内容をコピペしてローカルでmarkdown-pdfコマンドでPDF化するために付けた機能なのですが、ぶっちゃけこの作業が面倒ですよね、と。なんとかPDF化までサーバ側で処理して、手作業は「PDFをダウンロード・印刷」だけにしたいということで今回の挑戦に至りました。

最初もこの構想自体はあったのですが、「サーバで色々処理させるのが大変そう」ということでMarkdown形式を吐き出すことでお茶を濁していたのでした。

今回改めて面倒に思ったので、当初の構想を実現するために試してみた次第です。手順としては以下。

  1. サーバにNode.jsをインストール
  2. markdown-pdfをインストール
  3. Webページ上に生成ボタンを実装

2までは良いのですが、3が問題です。一度Webページとして表示され、サーバ側のコントロールから外れた状態から、サーバ側でmarkdown-pdfを実行させるにはどうしたら良いのか、と。かなり無茶をしていますが、動作としては実現できたのでメモしておきます。

1. サーバにNode.jsをインストール

今回はテストサーバなので好きなように弄れます。とはいえ、一応Node.js自体のバージョン管理はしたいのでそのままインストールではなくnを入れることにします。nnpmが前提なのでnpmのインストールから。

# yum install npm
読み込んだプラグイン:fastestmirror, security
インストール処理の設定をしています

## 略

# npm -v
1.3.6

……古ッ!まあ、とりあえず動けば良いので……。

# npm install -g n
npm http GET https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n
npm ERR! Error: CERT_UNTRUSTED
npm ERR!     at SecurePair.<anonymous> (tls.js:1430:32)
npm ERR!     at SecurePair.emit (events.js:92:17)
npm ERR!     at SecurePair.maybeInitFinished (tls.js:1029:10)
npm ERR!     at CleartextStream.read [as _read] (tls.js:521:13)
npm ERR!     at CleartextStream.Readable.read (_stream_readable.js:341:10)
npm ERR!     at EncryptedStream.write [as _write] (tls.js:418:25)
npm ERR!     at doWrite (_stream_writable.js:226:10)
npm ERR!     at writeOrBuffer (_stream_writable.js:216:5)
npm ERR!     at EncryptedStream.Writable.write (_stream_writable.js:183:11)
npm ERR!     at write (_stream_readable.js:602:24)

## 略

npm ERR! command "node" "/usr/bin/npm" "install" "-g" "n"
npm ERR! cwd /root
npm ERR! node -v v0.10.48
npm ERR! npm -v 1.3.6
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /root/npm-debug.log
npm ERR! not ok code 0

怒られてしまいました。調べてみると、インストールにSSLが有効な場合に怒られるとのことなのでオフにします。

# npm config set strict-ssl false

これで再度nをインストール。

# npm install -g n
npm http GET https://registry.npmjs.org/n
npm http 200 https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n/-/n-2.1.12.tgz
npm http 200 https://registry.npmjs.org/n/-/n-2.1.12.tgz
/usr/bin/n -> /usr/lib/node_modules/n/bin/n
npm WARN unmet dependency /usr/lib/node_modules/block-stream requires inherits@'~2.0.0' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream requires inherits@'~2.0.0' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream-ignore requires inherits@'2' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream-npm requires inherits@'2' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/glob requires inherits@'2' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/npmconf requires inherits@'~2.0.0' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/tar requires inherits@'2' but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
n@2.1.12 /usr/lib/node_modules/n

警告は出ているものの、エラーではないので入ったと思われます。試しにnのヘルプを出してみましょう。

# n --help

  Usage: n [options/env] [COMMAND] [args]

  Environments:
    n [COMMAND] [args]            Uses default env (node)
    n io [COMMAND]                Sets env as io
    n project [COMMAND]           Uses custom env-variables to use non-official sources

## 略

  Aliases:

    which   bin
    use     as
    list    ls
    -       rm

OKです。試しにNode.jsのバージョンを確認してみましょう。

# node -v
v0.10.48

……古いですね。新しくしましょう。

# n --stable
10.8.0
# n stable

     install : node-v10.8.0
       mkdir : /usr/local/n/versions/node/10.8.0
       fetch : https://nodejs.org/dist/v10.8.0/node-v10.8.0-linux-x64.tar.gz
######################################################################## 100.0%
   installed : v10.8.0

# node -v
v0.10.48

あれ、変わっていない……。一度ログアウトしてから再度ログインしなおして、コマンド実行。

# node -v
v10.8.0
# npm -v
6.2.0

変わりました。セッション中は変わらなかった模様。とりあえずOKです。

2. markdown-pdfをインストール

次はmarkdown-pdfを入れましょう(後でグローバルインストールしなくても良かった疑惑が浮上しましたが)。

# sudo npm install -g markdown-pdf
npm http GET https://registry.npmjs.org/markdown-pdf
npm http 200 https://registry.npmjs.org/markdown-pdf
npm http GET https://registry.npmjs.org/markdown-pdf/-/markdown-pdf-9.0.0.tgz
npm http 200 https://registry.npmjs.org/markdown-pdf/-/markdown-pdf-9.0.0.tgz

## 略

tqq remarkable@1.7.1 (autolinker@0.15.3, argparse@0.1.16)
mqq phantomjs-prebuilt@2.1.16 (progress@1.1.8, kew@0.7.0, which@1.3.1, request-progress@2.0.1, es6-promise@4.2.4, hasha@2.2.0, fs-extra@1.0.0, extract-zip@1.6.7, request@2.88.0)

OKです。ちなみにsudoを付けないと

## 略

Phantom installation failed { [Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1535605665147/phantomjs-2.1.1-linux-x86_64' -> '/usr/local/lib/node_modules/markdown-pdf/node_modules/phantomjs-prebuilt/lib/phantom']
  errno: -13,
  code: 'EACCES',
  syscall: 'link',
  path:
   '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1535605665147/phantomjs-2.1.1-linux-x86_64',
  dest:
   '/usr/local/lib/node_modules/markdown-pdf/node_modules/phantomjs-prebuilt/lib/phantom' } Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1535605665147/phantomjs-2.1.1-linux-x86_64' -> '/usr/local/lib/node_modules/markdown-pdf/node_modules/phantomjs-prebuilt/lib/phantom'
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! phantomjs-prebuilt@2.1.16 install: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the phantomjs-prebuilt@2.1.16 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2018-08-30T05_07_51_078Z-debug.log

Error: EACCES: permission deniedのエラーが出てしまいます。

3. Webページ上に生成ボタンを実装

これについては頭をひねりましたが、下記のリンクを見て1ファイルで実装できるのでは?と思ったのでこれをベースに作りました。

最終的にはpackage.json、ポート番号が変わってクロスオリジンになってしまうので.htaccessで制御……と1ファイルではなくなってしまいましたが、やりたいことの実現はできました。

今回の追加部分だけを抽出してリポジトリに収めたのが下記となります。

PDF化したいMarkdownの内容をPOSTするフォーム部分

まず、生成されたMarkdown形式のテキストがtextareaに吐き出されます。

それと同時に、input type="hidden"の中にTrelloのメンバーIDと、このMarkdownデータを生成した日時がタイムスタンプとして格納されます。このメンバーIDとタイムスタンプをファイル名に組み込むことによって、都度ユニークなファイル名となるように調整しています(前のPDFが上書きされたら困るので)。

  • Markdownのテキストデータ
  • TrelloのメンバーID
  • タイムスタンプ

の3つのデータを今回追加したindex.htmlめがけてPOSTします。

  1. フォームからサーバにPOSTされた内容で、index.htmlのNode.js部分が動作してmarkdown-pdfを実行
  2. http.createServerでWebサーバとしての動作
  3. 1.でPOSTされたメンバーIDとタイムスタンプを、レスポンスとして返す自分自身(index.html)のURLに付与してクライアントに返す
  4. クライアント側でページを表示
  5. GETパラメータから2.で生成されたPDFファイルのURLを生成、そのURLにAJAXでGETしに行ってファイル存在をチェック。成功すればaタグのダウンロードボタンを表示し、href属性にPDFファイルのURLを入れることで「PDFファイルのダウンロード」を実行するボタンとして機能させる

PDFをダウンロードするページとして表示されたindex.html

上記の動作によってダウンロードボタンが表示されます。

生成されたPDFファイルを表示

5.によりダウンロードボタンはきちんと動作し、無事PDFを表示・ダウンロードできる、という寸法です。

上記のようにざっくり動作の順序を書き綴りましたが、クロスオリジン対策とかNode.jsとWebサーバでパスが変わってしまう、といった部分を無理くり何とかしている感がするので、「動作はするけどあんまりお勧めできる環境構成ではない」という感じになりました。

一応、環境さえ整えてあげれば動作はするので「やろうと思えばできる」というサンプルとして記録しておきます。

ちなみに

今回のリポジトリの名前を「fuguruma」としましたが、これは妖怪の「文車妖妃」から(form.htmlの見出しが「Youhi」となっているのもここから)。文車は寺院や邸宅の書物を火災などの非常時に持ち出すために使う車のこと。

index.htmlの1つのファイルでサーバとクライアントの双方の処理を行き来する様子を車輪に例えました。また、PDF文書を扱うことから紙や本に関連のあるものということで、文車を連想した結果です。

参考

サーバへのNode.jsのインストール

Error: CERT_UNTRUSTED の対処

Error: EACCES: permission denied の対処

WebページからNodeコマンドを実行

タグ: javascript,サーバ環境・構築,Markdown,Trello,Node.js

 



関連する記事一覧