Sirviendo archivos estáticos con Sinatra

139

Tengo un sitio web de una sola página que usa HTML, CSS y JavaScript. Quiero implementar la aplicación en Heroku, pero no puedo encontrar la manera de hacerlo. Ahora estoy tratando de hacer que la aplicación funcione con Sinatra.

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

Y el siguiente es el contenido de myapp.rb.

require 'rubygems'
require 'sinatra'

get "/" do
  # What should I write here to point to the `index.html`
end
TK
fuente
1
He aprendido que acceder a localhost: 2345 / index.html funciona.
TK.
Puede usar WebBrick para servir archivos estáticos en unas pocas líneas. require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start;Entonces corre ruby myapp.rb. Retire el puerto para Heroku. Poner web: ruby myapp.rben tu Procfile. El comentario no responde, ya que no es para Sinatra, pero creo que simplifica las dependencias.
Chloe

Respuestas:

131

Sin ninguna configuración adicional, Sinatra servirá activos en public. Para la ruta vacía, querrás representar el documento de índice.

require 'rubygems'
require 'sinatra'

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

Las rutas deben devolver un Stringque se convierta en el cuerpo de respuesta HTTP. File.readabre un archivo, lee el archivo, cierra el archivo y devuelve a String.

Tate Johnson
fuente
52
Deberías más bien hacerlo send_file File.expand_path('index.html', settings.public).
Konstantin Haase
32
Esto ahora es incorrecto. Debe reemplazar settings.publiccon settings.public_folderpara obtenersend_file File.expand_path('index.html', settings.public_folder)
Alistair Holt
2
@zhirzh send_file, hace cosas adicionales para ti github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351
desde el
1
File.readlee todo el archivo en la memoria. Esto puede estar bien o no, dependiendo del tamaño de los archivos y el número de solicitudes concurrentes.
Wayne Conrad el
@WayneConrad por el contrario, ¿send_file está bien? o actúa igual?
Ben
169

Puede usar el send_fileayudante para servir archivos.

require 'sinatra'

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

Esto servirá index.htmldesde cualquier directorio que haya sido configurado como teniendo los archivos estáticos de su aplicación.

Ryan Ahearn
fuente
19
Creo que las nuevas aplicaciones de Sinatra usan set :public_folder, por lo que usarías en settings.public_folderlugar desettings.public
Andrew
44
Actualicé la respuesta para usar settings.public_folder. Es posible que las aplicaciones más antiguas aún necesiten usar settings.public.
Chad DeShon
62

Podrías alojarlos desde la carpeta pública y no necesitan rutas.

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

En el myapp.rb

set :public_folder, 'public'

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

Enlace a alguna subcarpeta en público

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

Se puede acceder a todo en ./public desde '/whatever/bla.html

Ejemplo:
./public/stylesheets/screen.css
Se podrá acceder a través de '/stylesheets/screen.css' sin necesidad de ruta

Morgan
fuente
1
¿Qué sucede si public tiene muchas carpetas anidadas (para las cuales no desea crear rutas) que tienen archivos index.html que le gustaría que sean los predeterminados?
Derek Prior
He expandido la solución. Espero que ayude a aclarar, todo es accesible en público, no se requiere una ruta, solo omita la parte 'pública' de la ruta.
Morgan
1
usando el acumulador en Heroku que tuve que usar set :public_folder, 'public'. Eso fue clave para que funcione, a pesar de la documentación de Sinatra que implica que esto ya estaba configurado como predeterminado.
Daniel C
12

Tenga en cuenta que en producción puede hacer que su servidor web se envíe index.htmlautomáticamente para que la solicitud nunca llegue a Sinatra. Esto es mejor para el rendimiento, ya que no tiene que pasar por la pila de Sinatra / Rack solo para servir texto estático, que es lo que Apache / Nginx es increíble para hacer.

Rob Cameron
fuente
Oh si, duh. Usaré Erb entonces y usaré Varnish para cobrarlo.
ma11hew28
2
¿Cómo se configura esto en producción? He estado buscando documentación sobre esta referencia cruzada con Sinatra y Rack, pero no puedo encontrarla. Básicamente, quiero que index.html se cargue en cualquier carpeta / public que tenga una si el usuario solo pone el nombre de la carpeta
12

Sinatra debería permitirle servir archivos estáticos desde el directorio público como se explica en los documentos :

Archivos estáticos

Los archivos estáticos se sirven desde el directorio ./public. Puede especificar una ubicación diferente configurando la opción: public:

Tenga en cuenta que el nombre del directorio público no está incluido en la URL. Un archivo ./public/css/style.css está disponible como example.com/css/style.css.

imightbeinatree en Cloudspace
fuente
44
¿Por qué esto tiene 4 votos? No responde a la pregunta de cómo presentar un documento predeterminado cuando se solicita una carpeta.
Derek Prior
4

Agregue la siguiente línea en el archivo rb principal

set :public_folder, 'public'
Muhammad Aamir Talib
fuente
2

la gema sinatra-assetpack ofrece un montón de características. la sintaxis es dulce:

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

Si bien sigo teniendo problemas con la canalización de activos de rails, siento que tengo mucho más control usando sinatra-assetpack , pero la mayoría de las veces solo funciona con unas pocas líneas de código.

estar nervioso
fuente
2

RESPUESTA ACTUALIZADA : empaté todo lo anterior sin suerte de poder cargar css, js .... etc. contenido, lo único que se estaba cargando es index.html ... y el resto iban = >>404 error

Mi solución: la carpeta de la aplicación se ve así.

index.rb == >> El código de Sinatra va.

require 'rubygems'
require 'sinatra'

get '/' do
  html :index
end

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

public folder== >> contiene todo lo demás ... css, js, bla, bla, 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$

Ahora inicie el servidor y podrá navegar a través de páginas estáticas sin problemas.

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
fuente
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
fuente
1

Puede considerar mover el index.htmlarchivo views/index.erby definir un punto final como:

get '/' do
  erb :index
end
bonh
fuente
0

Poner archivos en la publiccarpeta tiene una limitación. En realidad, cuando está en la '/'ruta raíz funciona correctamente porque el navegador establecerá la ruta relativa de su archivo css, por ejemplo, /css/style.cssy sinatra buscará el archivo en el publicdirectorio. Sin embargo, si su ubicación es, por ejemplo /user/create, el navegador web buscará su archivo CSS /user/create/css/style.cssy fallará.

Como solución alternativa, agregué la siguiente redirección para cargar correctamente el archivo CSS:

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

¿Qué hay de esta solución? :

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

así que si ahora navega a (por ejemplo) / subdirectory / test / se cargará subdirectory / test / index.html

helipuerto
fuente