Phục vụ các tệp tĩnh với Sinatra


139

Tôi có một trang web chỉ sử dụng HTML, CSS và JavaScript. Tôi muốn triển khai ứng dụng lên Heroku, nhưng tôi không thể tìm ra cách để làm điều đó. Bây giờ tôi đang cố gắng để làm cho ứng dụng hoạt động với Sinatra.

.
|-- application.css
|-- application.js
|-- index.html
|-- jquery.js
`-- myapp.rb

Và sau đây là nội dung của myapp.rb.

require 'rubygems'
require 'sinatra'

get "/" do
  # What should I write here to point to the `index.html`
end

1
Tôi đã học được rằng truy cập localhost: 2345 / index.html hoạt động.
TK.

Bạn có thể sử dụng WebBrick để phục vụ các tệp tĩnh trong một vài dòng. require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start;Sau đó chạy ruby myapp.rb. Hủy bỏ cổng cho Heroku. Đặt web: ruby myapp.rbtrong của bạn Procfile. Nhận xét không trả lời vì nó không dành cho Sinatra, nhưng tôi nghĩ nó đơn giản hóa sự phụ thuộc.
Chloe

Câu trả lời:


131

Không có bất kỳ cấu hình bổ sung, Sinatra sẽ phục vụ tài sản trong public. Đối với tuyến đường trống, bạn sẽ muốn hiển thị tài liệu chỉ mục.

require 'rubygems'
require 'sinatra'

get '/' do
  File.read(File.join('public', 'index.html'))
end

Các tuyến sẽ trả về một Stringtrở thành thân phản hồi HTTP. File.readmở tệp, đọc tệp, đóng tệp và trả về a String.


52
Bạn nên làm send_file File.expand_path('index.html', settings.public).
Konstantin Haase

32
Điều này bây giờ không chính xác. Bạn nên thay thế settings.publicbằng settings.public_folderđể có đượcsend_file File.expand_path('index.html', settings.public_folder)
Alistair Holt

2
@zhirzh send_file, nó làm thêm công cụ cho bạn github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351
iain

1
File.readđọc toàn bộ tập tin vào bộ nhớ. Điều này có thể ổn hoặc không, tùy thuộc vào kích thước của tệp và số lượng yêu cầu đồng thời.
Wayne Conrad

@WayneConrad thì ngược lại, send_file có ổn không? hoặc nó hành động giống nhau?
Ben

169

Bạn có thể sử dụng trình send_filetrợ giúp để phục vụ các tập tin.

require 'sinatra'

get '/' do
  send_file File.join(settings.public_folder, 'index.html')
end

Điều này sẽ phục vụ index.htmltừ bất kỳ thư mục nào đã được cấu hình là có tệp tĩnh của ứng dụng của bạn.


19
Tôi nghĩ các ứng dụng Sinatra mới hơn sử dụng set :public_folder, vì vậy bạn sẽ sử dụng settings.public_folderthay vìsettings.public
Andrew

4
Tôi đã cập nhật câu trả lời để sử dụng settings.public_folder. Các ứng dụng cũ hơn có thể vẫn cần sử dụng settings.public.
Chad DeShon

62

Bạn chỉ có thể lưu trữ chúng từ thư mục công cộng và chúng không cần các tuyến đường.

.
-- myapp.rb
`-- public
    |-- application.css
    |-- application.js
    |-- index.html
    `-- jquery.js

Trong myapp.rb

set :public_folder, 'public'

get "/" do
  redirect '/index.html'
end

Liên kết đến một số thư mục con ở nơi công cộng

set :public_folder, 'public'
get "/" do
  redirect '/subfolder/index.html' 
end

Mọi thứ trong ./public đều có thể truy cập được từ '/whthing/bla.html

Ví dụ:
./public/stylesheets/screen.css
Sẽ có thể truy cập thông qua '/stylesheets/screen.css' không cần tuyến đường


1
Điều gì xảy ra nếu công khai có nhiều thư mục lồng nhau (mà bạn không muốn tạo tuyến đường) có tệp index.html mà bạn muốn làm mặc định?
Derek Trước

Tôi đã mở rộng giải pháp. Tôi hy vọng nó giúp làm rõ, mọi thứ đều có thể truy cập được ở nơi công cộng, không yêu cầu tuyến đường nào chỉ cần bỏ qua phần 'công khai' của đường dẫn.
Morgan

1
Tôi sử dụng rackup trên Heroku set :public_folder, 'public'. Đó là chìa khóa để làm cho nó hoạt động, mặc dù tài liệu Sinatra ngụ ý rằng điều này đã được đặt làm mặc định.
Daniel C

12

Hãy nhớ rằng trong sản xuất, bạn có thể gửi máy chủ web của mình index.htmltự động để yêu cầu không bao giờ được gửi đến Sinatra. Điều này tốt hơn cho hiệu suất khi bạn không phải trải qua ngăn xếp Sinatra / Rack chỉ để phục vụ văn bản tĩnh, đó là điều mà Apache / Nginx rất tuyệt vời khi làm.


Ồ vâng, duh. Tôi sẽ chỉ sử dụng Erb sau đó và sử dụng Varnish để kiếm tiền.
ma11hew28

2
Làm thế nào để bạn cấu hình này trong sản xuất? Tôi đã tìm kiếm tài liệu về tham chiếu chéo này với Sinatra và Rack nhưng không thể tìm thấy nó. Về cơ bản tôi muốn index.html được tải trong bất kỳ thư mục / công khai nào có một nếu người dùng chỉ đặt tên thư mục

12

Sinatra sẽ cho phép bạn phục vụ các tệp tĩnh từ thư mục công cộng như được giải thích trong các tài liệu :

Tệp tĩnh

Các tệp tĩnh được phục vụ từ thư mục ./public. Bạn có thể chỉ định một vị trí khác bằng cách đặt tùy chọn: công khai:

Lưu ý rằng tên thư mục công cộng không được bao gồm trong URL. Một tệp ./public/css/style.css được cung cấp dưới dạng example.com/css/style.css.


4
Tại sao điều này có 4 phiếu? Nó không trả lời câu hỏi làm thế nào để trình bày một tài liệu mặc định khi một thư mục được yêu cầu.
Derek Trước


2

các Sinatra-assetpack đá quý cung cấp một bó toàn bộ các tính năng. cú pháp ngọt ngào:

serve '/js', from: '/app/javascripts'

trong khi tôi vẫn gặp vấn đề với đường ống tài sản rails, tôi cảm thấy như tôi có nhiều quyền kiểm soát hơn khi sử dụng sinatra-propertypack - nhưng hầu hết các lần nó chỉ hoạt động với một vài dòng mã.


2

CẬP NHẬT TRẢ LỜI : Tôi đã buộc tất cả những điều trên mà không may mắn được tải css, js .... vv nội dung duy nhất đang tải là index.html ... và phần còn lại sẽ diễn ra = >>404 error

Giải pháp của tôi: thư mục ứng dụng trông như thế này.

index.rb == >> Mã Sinatra đi.

require 'rubygems'
require 'sinatra'

get '/' do
  html :index
end

def html(view)
  File.read(File.join('public', "#{view.to_s}.html"))
end

public folder== >> chứa mọi thứ khác ... css, js, blah blah..v.v.

user@user-SVE1411EGXB:~/sintra1$ ls
index.rb  public
user@user-SVE1411EGXB:~/sintra1$ find public/
public/
public/index.html
public/about_us.html
public/contact.html
public/fonts
public/fonts/fontawesome-webfont.svg
public/fonts/fontawesome-webfont.ttf
public/img
public/img/drink_ZIDO.jpg
public/js
public/js/bootstrap.min.js
public/js/jquery.min.js
public/js/bootstrap.js
public/carsoul2.html
public/css
public/css/font-awesome-ie7.css
public/css/bootstrap.min.css
public/css/font-awesome.min.css
public/css/bootstrap.css
public/css/font-awesome.css
public/css/style.css
user@user-SVE1411EGXB:~/sintra1$

Bây giờ khởi động máy chủ và bạn sẽ có thể điều hướng qua các trang tĩnh mà không gặp vấn đề gì.

user@user-SVE1411EGXB:~/sintra1$ ruby index.rb 
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on localhost:4567, CTRL+C to stop

2
require 'rubygems'
require 'sinatra'

set :public_folder, File.dirname(__FILE__) + '/../client'
#client - it's folder with all your file, including myapp.rb

get "/" do
  File.read('index.html')
end


1

Bạn có thể xem xét việc di chuyển index.htmltệp đến views/index.erbvà xác định điểm cuối như:

get '/' do
  erb :index
end


0

Đưa tập tin vào publicthư mục có một hạn chế. Trên thực tế, khi bạn ở trong '/'đường dẫn gốc hoạt động chính xác vì trình duyệt sẽ đặt đường dẫn tương đối của tệp css của bạn chẳng hạn /css/style.cssvà sinatra sẽ tìm tệp trong publicthư mục. Tuy nhiên, nếu vị trí của bạn là ví dụ /user/create, thì trình duyệt web sẽ tìm tệp css của bạn /user/create/css/style.cssvà sẽ thất bại.

Như một giải pháp thay thế, tôi đã thêm chuyển hướng sau để tải chính xác tệp css:

get %r{.*/css/style.css} do
    redirect('css/style.css')
end

-7

Giải pháp này thì sao? :

get "/subdirectory/:file" do 
  file = params[:file] + "index.html"
  if File.exists?(params[:file])
    return File.open("subdirectory/" + file)
  else
   return "error"
  end
end

vì vậy nếu bây giờ bạn điều hướng đến (ví dụ) / thư mục con / test / nó sẽ tải thư mục con / test / index.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.