Servindo arquivos estáticos com o Sinatra

139

Eu tenho um site de página única usando HTML, CSS e JavaScript. Quero implantar o aplicativo no Heroku, mas não consigo encontrar uma maneira de fazê-lo. Agora estou tentando fazer o aplicativo funcionar com Sinatra.

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

E o seguinte é o conteúdo de myapp.rb.

require 'rubygems'
require 'sinatra'

get "/" do
  # What should I write here to point to the `index.html`
end
TK.
fonte
1
Aprendi que o acesso ao localhost: 2345 / index.html funciona.
TK.
Você pode usar o WebBrick para veicular arquivos estáticos em poucas linhas. require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start;Então corra ruby myapp.rb. Remova a porta para o Heroku. Coloque web: ruby myapp.rbno seu Procfile. O comentário não responde, pois não é para o Sinatra, mas acho que simplifica as dependências.
Chloe

Respostas:

131

Sem nenhuma configuração adicional, o Sinatra servirá ativos public. Para a rota vazia, você deseja renderizar o documento de índice.

require 'rubygems'
require 'sinatra'

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

As rotas devem retornar um Stringque se torne o corpo da resposta HTTP. File.readabre um arquivo, lê o arquivo, fecha o arquivo e retorna a String.

Tate Johnson
fonte
52
Você deveria preferir send_file File.expand_path('index.html', settings.public).
Konstantin Haase
32
Agora isso está incorreto. Você deve substituir settings.publicpor settings.public_folderpara obtersend_file File.expand_path('index.html', settings.public_folder)
Alistair Holt
2
@zhirzh send_file, ele faz coisas extras para você github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351
iain
1
File.readlê o arquivo inteiro na memória. Isso pode ser bom ou não, dependendo do tamanho dos arquivos e do número de solicitações simultâneas.
Wayne Conrad
@WayneConrad, pelo contrário, send_file está bem? ou age da mesma maneira?
Ben
169

Você pode usar o send_fileauxiliar para servir arquivos.

require 'sinatra'

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

Isso servirá a index.htmlpartir de qualquer diretório que tenha sido configurado como tendo os arquivos estáticos do seu aplicativo.

Ryan Ahearn
fonte
19
Eu acho que os aplicativos Sinatra mais novos usam set :public_folder, então você usaria em settings.public_foldervez desettings.public
Andrew
4
Atualizei a resposta para usar settings.public_folder. Aplicativos mais antigos ainda podem precisar usar o settings.public.
Chad DeShon
62

Você pode simplesmente hospedá-los da pasta pública e eles não precisam de rotas.

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

No myapp.rb

set :public_folder, 'public'

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

Link para alguma subpasta em público

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

Tudo em ./public está acessível em '/whatever/bla.html

Exemplo:
./public/stylesheets/screen.css
estará acessível através de '/stylesheets/screen.css', nenhuma rota necessária

Morgan
fonte
1
e se public tiver muitas pastas aninhadas (para as quais você não deseja criar rotas) que possuam arquivos index.html que você gostaria de ser o padrão?
Derek Prior
Eu expandi a solução. Espero que ajude a esclarecer, tudo é acessível em público, nenhuma rota necessária apenas omite a parte 'pública' do caminho.
28412 Morgan
1
usando rackup no Heroku eu tive que usar set :public_folder, 'public'. Isso foi fundamental para fazê-lo funcionar, apesar da documentação do Sinatra implicar que isso já estava definido como padrão.
Daniel C
12

Lembre-se de que, na produção, o servidor da Web pode ser enviado index.htmlautomaticamente, para que a solicitação nunca chegue a Sinatra. Isso é melhor para o desempenho, pois você não precisa passar pela pilha do Sinatra / Rack apenas para veicular texto estático, que é o que o Apache / Nginx é incrível em fazer.

Rob Cameron
fonte
Oh sim, duh. Vou usar o Erb e usar o verniz para trocá-lo.
ma11hew28
2
Como você configura isso na produção? Estive procurando por documentação sobre essa referência cruzada com Sinatra e Rack, mas não consigo encontrá-la. Basicamente eu quero index.html para ser carregado em qualquer pasta pública / que tem um, se o usuário só coloca o nome da pasta
12

O Sinatra deve permitir a veiculação de arquivos estáticos do diretório público, conforme explicado nos documentos :

Arquivos estáticos

Os arquivos estáticos são exibidos no diretório ./public. Você pode especificar um local diferente, definindo a opção: public:

Observe que o nome do diretório público não está incluído na URL. Um arquivo ./public/css/style.css é disponibilizado como example.com/css/style.css.

imightbeinatree no Cloudspace
fonte
4
Por que isso tem 4 votos? Ele não responde à pergunta de como apresentar um documento padrão quando uma pasta é solicitada.
Derek Prior
4

Adicione abaixo da linha no arquivo rb principal

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

o gem sinatra-assetpack oferece um monte de recursos. sintaxe é doce:

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

Enquanto ainda estou tendo problemas com o pipeline de ativos de trilhos, sinto que tenho muito mais controle usando o sinatra-assetpack - mas na maioria das vezes ele funciona apenas com algumas linhas de código.

nervosismo
fonte
2

RESPOSTA ATUALIZADA : Eu amarrei tudo o que precede, sem a possibilidade de carregar o conteúdo de css, js .... etc. etc, a única coisa que estava carregando é index.html ... e o resto estava acontecendo = >>404 error

Minha solução: pasta do aplicativo é assim.

index.rb == >> O código Sinatra continua.

require 'rubygems'
require 'sinatra'

get '/' do
  html :index
end

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

public folder== >> contém todo o resto ... 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$

Agora inicie o servidor e você poderá navegar pelas páginas estáticas sem nenhum problema.

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

Você pode considerar mover o index.htmlarquivo para views/index.erbe definir um terminal como:

get '/' do
  erb :index
end
bonh
fonte
1

Você sempre pode usar o Rack :: Static

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

Basta adicionar esta linha antes do comando 'run' em 'config.ru'

use Rack::Static, :urls => [""], :root => 'public', :index => 'index.html'
r0ma
fonte
0

Colocar arquivos na publicpasta tem uma limitação. Na verdade, quando você está no '/'caminho raiz, funciona corretamente porque o navegador definirá o caminho relativo do seu arquivo css, por exemplo, /css/style.csse o sinatra procurará o arquivo no publicdiretório No entanto, se sua localização for, por exemplo /user/create, o navegador da Web procurará seu arquivo css /user/create/css/style.csse falhará.

Como solução alternativa, adicionei o seguinte redirecionamento para carregar corretamente o arquivo css:

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

E essa solução? :

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

portanto, se você agora navegar para (por exemplo) / subdiretório / teste / ele carregará o subdiretório / test / index.html

holdopslippers
fonte