Obsługa plików statycznych za pomocą Sinatry

139

Mam jedną stronę internetową używającą tylko HTML, CSS i JavaScript. Chcę wdrożyć aplikację w Heroku, ale nie mogę znaleźć sposobu, aby to zrobić. Teraz próbuję, aby aplikacja działała z Sinatrą.

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

A oto treść myapp.rb.

require 'rubygems'
require 'sinatra'

get "/" do
  # What should I write here to point to the `index.html`
end
TK.
źródło
1
Dowiedziałem się, że dostęp do localhost: 2345 / index.html działa.
TK.
Możesz użyć WebBrick do obsługi plików statycznych w kilku wierszach. require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start;Następnie biegnij ruby myapp.rb. Usuń port dla Heroku. Włóż web: ruby myapp.rbswój Procfile. Komentarz nie odpowiada, bo to nie jest dla Sinatry, ale myślę, że to upraszcza zależności.
Chloe

Odpowiedzi:

131

Bez dodatkowej konfiguracji Sinatra będzie obsługiwać zasoby w formacie public. W przypadku pustej trasy będziesz chciał wyrenderować dokument indeksu.

require 'rubygems'
require 'sinatra'

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

Trasy powinny zwracać a, Stringktóre stają się treścią odpowiedzi HTTP. File.readotwiera plik, czyta plik, zamyka plik i zwraca plik String.

Tate Johnson
źródło
52
Powinieneś raczej to zrobić send_file File.expand_path('index.html', settings.public).
Konstantin Haase,
32
To jest teraz nieprawidłowe. Należy wymienić settings.publicz settings.public_folderdostaćsend_file File.expand_path('index.html', settings.public_folder)
Alistair Holt
2
@zhirzh send_file, robi dla Ciebie dodatkowe rzeczy github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351
m.
1
File.readczyta cały plik do pamięci. Może to być prawidłowe lub nie, w zależności od rozmiaru plików i liczby jednoczesnych żądań.
Wayne Conrad,
@WayneConrad z drugiej strony, send_file jest w porządku? czy działa tak samo?
Ben
169

Możesz użyć send_filepomocnika do obsługi plików.

require 'sinatra'

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

Będzie to służyć index.htmlz dowolnego katalogu, który został skonfigurowany jako zawierający pliki statyczne aplikacji.

Ryan Ahearn
źródło
19
Myślę, że nowsze aplikacje Sinatra używają set :public_folder, więc settings.public_folderzamiast tegosettings.public
Andrew
4
Zaktualizowałem odpowiedź, aby użyć settings.public_folder. Starsze aplikacje mogą nadal wymagać używania settings.public.
Chad DeShon
62

Możesz po prostu hostować je z folderu publicznego i nie potrzebują tras.

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

W pliku myapp.rb

set :public_folder, 'public'

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

Link do jakiegoś publicznego podfolderu

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

Wszystko w ./public jest dostępne pod adresem „/cokolwiek/bla.html

Przykład:
./public/stylesheets/screen.css
Będzie dostępny za pośrednictwem „/stylesheets/screen.css”, trasa nie jest wymagana

Morgan
źródło
1
co się stanie, jeśli public ma wiele zagnieżdżonych folderów (dla których nie chcesz tworzyć tras) zawierających pliki index.html, które chcesz, aby były domyślne?
Derek Prior
Rozszerzyłem rozwiązanie. Mam nadzieję, że pomoże to wyjaśnić, wszystko jest dostępne publicznie, żadna trasa nie jest wymagana, wystarczy pominąć „publiczną” część ścieżki.
Morgan
1
używając rackup na Heroku, którego musiałem użyć set :public_folder, 'public'. To było kluczem do jego działania, mimo że dokumentacja Sinatry sugerowała, że ​​było to już ustawione jako domyślne.
Daniel C
12

Pamiętaj, że w środowisku produkcyjnym możesz ustawić index.htmlautomatyczne wysyłanie serwera WWW, aby żądanie nigdy nie dotarło do Sinatry. Jest to lepsze dla wydajności, ponieważ nie musisz przechodzić przez stos Sinatra / Rack tylko po to, aby wyświetlać statyczny tekst, w czym Apache / Nginx są niesamowici.

Rob Cameron
źródło
O tak, duh. Po prostu użyję Erba i lakieru, żeby to spieniężyć.
ma11hew28,
2
Jak to skonfigurujesz na produkcji? Szukałem dokumentacji na temat tego powiązania z Sinatrą i Rackiem, ale nie mogę jej znaleźć. Zasadniczo chcę, aby plik index.html został załadowany do dowolnego / publicznego folderu, który ma taki folder, jeśli użytkownik umieści tylko nazwę folderu
12

Sinatra powinien pozwolić ci udostępniać pliki statyczne z katalogu publicznego, jak wyjaśniono w dokumentacji :

Pliki statyczne

Pliki statyczne są udostępniane z katalogu ./public. Możesz określić inną lokalizację, ustawiając opcję: public:

Zauważ, że nazwa katalogu publicznego nie jest zawarta w adresie URL. Plik ./public/css/style.css jest udostępniany jako example.com/css/style.css.

imightbeinatree w Cloudspace
źródło
4
Dlaczego ma 4 głosy? Nie odpowiada na pytanie, jak przedstawić domyślny dokument, gdy żądany jest folder.
Derek Prior
4

Dodaj poniższą linię w głównym pliku rb

set :public_folder, 'public'
Muhammad Aamir Talib
źródło
2

ZAKTUALIZOWANA ODPOWIEDŹ : Wiązałem wszystko powyższe, ale nie udało mi się załadować zawartości css, js .... itd. Jedyną rzeczą, która się ładowała, jest index.html ... a reszta to = >>404 error

Moje rozwiązanie: folder aplikacji wygląda tak.

index.rb == >> Kod Sinatra idzie.

require 'rubygems'
require 'sinatra'

get '/' do
  html :index
end

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

public folder== >> zawiera wszystko inne ... css, js, blah blah..etc.

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$

Teraz uruchom serwer i będziesz mógł bez problemu poruszać się po statycznych stronach.

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
zee
źródło
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
Evan Ross
źródło
1

Możesz rozważyć przeniesienie index.htmlpliku do views/index.erbi zdefiniowanie punktu końcowego, takiego jak:

get '/' do
  erb :index
end
bonh
źródło
1

Zawsze możesz użyć Rack :: Static

https://www.rubydoc.info/gems/rack/Rack/Static

Po prostu dodaj tę linię przed poleceniem „uruchom” do „config.ru”

use Rack::Static, :urls => [""], :root => 'public', :index => 'index.html'
r0ma
źródło
0

Umieszczanie plików w publicfolderze ma pewne ograniczenia. Właściwie, gdy jesteś w katalogu głównym, '/'ścieżka działa poprawnie, ponieważ przeglądarka ustawi względną ścieżkę twojego pliku css na przykład, /css/style.cssa sinatra będzie szukał pliku w publickatalogu. Jeśli jednak Twoja lokalizacja to na przykład /user/create, przeglądarka internetowa będzie szukać pliku css w /user/create/css/style.cssi zawiedzie.

Aby obejść ten problem, dodałem następujące przekierowanie, aby poprawnie załadować plik css:

get %r{.*/css/style.css} do
    redirect('css/style.css')
end
Charmi
źródło
-7

A co z tym rozwiązaniem? :

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

więc jeśli teraz przejdziesz do (na przykład) / subdirectory / test /, załaduje się podkatalog / test / index.html

trzymane kapcie
źródło