LoginSignup
4
4

More than 5 years have passed since last update.

[Rails5] Rails5から外部htmlを読み込む方法

Posted at

Rails5から外部HTMLを読み込む方法

既にHTMLでページが出来上がっているけど、
その完成した静的HTMLをRails5から出力する方法を考えてみました。

これが出来れば静的なHTMLなどに対してアクセスした際の追加処理をRails5上で加える事が可能です。

やり方概要

  1. routesファイルで全てのパスへのアクセスを1つのアクションにまとめる。
  2. action上ではファイルの存在チェックやHTTPレスポンスを返す。

これだけでRails5上から静的HTMLを返す事が可能です。
実際に具体的な処理を見ていきます。

事前準備

Railsアプリケーションルートディレクトリ配下にprivateディレクトリを作成し、その中に下記ファイルを格納します。
通常静的ページはRailsアプリケーションルート/publicディレクトリにHTMLを格納しますが、
今回はpublicディレクトリ配下ではなく別ディレクトリに格納した前提で進めていきます。

  • a.html
  • a.css
  • a.js
  • a.png

それぞれのファイルの内容を見ていきます。

a.html
<!DOCTYPE html>
<html>
  <head>
    <title>title</title>
    <meta charset="utf-8">
    <script type="text/javascript" src="a.js" charset="UTF-8" ></script>
    <link rel="stylesheet" type="text/css" href="a.css"></link>
  </head>
  <body>
    <h1>abcddefghlj</h1>
    <img src="a.png" />
  </body>
</html>
a.js
window.onload = function() { window.alert('aaaa') }
a.css
h1 {
  border-bottom: solid 2px red;
}

a.pngは好きなpngファイルを格納してください。

Routesファイルを一つのアクションを参照するように修正

下のコードのように処理を修正します。
具体的にはルートディレクトリやその他全体のパスに対して、
static#show を動作させるようにしています。

config/routes.rb
Rails.application.routes.draw do
  root 'static#show'
  get '*path', to: 'static#show'
end

上記は こちらを参考にしました。

静的HTMLを返すアクションの作成

app/controllers/static_controller.rb
class StaticController < ApplicationController
  def show
    # request pathを取得
    private_root_path = "#{Rails.root}/private/"
    file_path = File.expand_path( File.join( "#{private_root_path}" , "#{request.path_info}" ) )

    # railsルート以外のディレクトリやファイルが存在しない場合
    if !file_path.start_with?( "#{private_root_path}" ) || !File.exist?(file_path) || File.directory?(file_path)
      render file: "#{Rails.root}/public/404.html", layout: false, status: 404, content_type: 'text/html'
      return
    end

    # ファイルが存在する場合
    respond_to do |format|
      format.js { send_data File.read(file_path), :type => "application/javascript" , :disposition => "inline" }
      format.css { send_data File.read(file_path), :type => "text/css" }
      format.png { send_data File.read(file_path), :type => "image/png", :disposition => "inline" }
      format.json { render json:"json" }
      format.html { 
        # render html: File.read(path).html_safe 
        render file: "#{file_path}", layout: false, status: 200
      }
    end
  end
end

このコードで少なくとも js,css,png,htmlはブラウザ上に返すことが出来ます。

以上が静的HTMLを返すRailsのサンプルです。

実際に試してみた。

rails_static.png

htmlの表示やJavascriptの動作などが行えている事が確認できます。

おまけ

アクションを追加したい場合

上で記載したコードだと全てのパスに対して1つのアクションが呼び出されますので、特定URLにアクセスしたい場合のアクションを追加する方法を記載しておきます。

具体的には下記コードの追加です。

config/routes.rb
Rails.application.routes.draw do
  get '/special', to: 'static#special' # add line
  root 'static#show'
  get '*path', to: 'static#show'
end
app/controllers/static_controller.rb
  # 下記アクションをStaticController内に追加
  def special
    render html: "special html!!"
  end

これで URL/specialというようにアクセスした場合は、
StaticController#Specialというアクションが実行されます。

CVE-2019-5418 問題

どうも render fileを使用した場合に発生するセキュリティホールがあるようです。
上記コードを使用する際は各々使用しているRailsVersionを確認してください。
こちら が参考になると思います。

読んでいただきありがとうございました。

Railsを学び始めたところですので、
誤りや問題点・指摘などがある記事になっているかもしれません。
もし何かありましたらご指摘お願いします。
またコメントやこうしたら良いよみたいなアドバイスがあればコメントいただけると嬉しいです。
特に上記Rubyのアクションコードを記載していますが、行数が長くもう少し短くしたいです。

参考URL

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4