Servir des fichiers statiques avec Sinatra


139

J'ai un site Web d'une page utilisant uniquement HTML, CSS et JavaScript. Je souhaite déployer l'application sur Heroku, mais je ne trouve pas de moyen de le faire. J'essaye maintenant de faire fonctionner l'application avec Sinatra.

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

Et ce qui suit est le contenu de myapp.rb.

require 'rubygems'
require 'sinatra'

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

1
J'ai appris que l'accès à localhost: 2345 / index.html fonctionne.
TK.

Vous pouvez utiliser WebBrick pour servir des fichiers statiques en quelques lignes. require 'webrick'; server = WEBrick::HTTPServer.new Port: 1234; server.mount '/', WEBrick::HTTPServlet::FileHandler, 'www/'; trap("INT") { server.stop }; server.start;Alors courez ruby myapp.rb. Supprimez le port pour Heroku. Mettez web: ruby myapp.rbvotre Procfile. Le commentaire ne répond pas car ce n'est pas pour Sinatra, mais je pense que cela simplifie les dépendances.
Chloe

Réponses:


131

Sans configuration supplémentaire, Sinatra servira les actifs dans public. Pour l'itinéraire vide, vous voudrez rendre le document d'index.

require 'rubygems'
require 'sinatra'

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

Les routes doivent retourner un Stringqui devient le corps de la réponse HTTP. File.readouvre un fichier, lit le fichier, ferme le fichier et renvoie un fichier String.


52
Tu devrais plutôt faire send_file File.expand_path('index.html', settings.public).
Konstantin Haase

32
C'est maintenant incorrect. Vous devriez remplacer settings.publicpar settings.public_folderpour obtenirsend_file File.expand_path('index.html', settings.public_folder)
Alistair Holt

2
@zhirzh send_file, il fait des trucs supplémentaires pour vous github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L351
iain

1
File.readlit le fichier entier en mémoire. Cela peut être correct ou non, selon la taille des fichiers et le nombre de demandes simultanées.
Wayne Conrad le

@WayneConrad à l'opposé, send_file, ça va? ou il agit de la même manière?
Ben

169

Vous pouvez utiliser l' send_fileassistant pour servir des fichiers.

require 'sinatra'

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

Cela servira à index.htmlpartir de n'importe quel répertoire configuré comme contenant les fichiers statiques de votre application.


19
Je pense que les nouvelles applications Sinatra utilisent set :public_folder, donc vous utiliseriez à la settings.public_folderplace desettings.public
Andrew

4
J'ai mis à jour la réponse pour utiliser settings.public_folder. Les applications plus anciennes peuvent encore avoir besoin d'utiliser settings.public.
Chad DeShon

62

Vous pouvez simplement les héberger à partir du dossier public et ils n'ont pas besoin de routes.

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

Dans myapp.rb

set :public_folder, 'public'

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

Lien vers un sous-dossier en public

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

Tout dans ./public est accessible depuis '/whatever/bla.html

Exemple:
./public/stylesheets/screen.css
Sera accessible via '/stylesheets/screen.css' aucune route requise


1
que se passe-t-il si public a de nombreux dossiers imbriqués (pour lesquels vous ne souhaitez pas créer de routes) contenant des fichiers index.html que vous souhaitez utiliser par défaut?
Derek Prior le

J'ai élargi la solution. J'espère que cela aide à clarifier, tout est accessible en public, aucun itinéraire requis, omettez simplement la partie «publique» du chemin.
Morgan

1
en utilisant rackup sur Heroku je devais utiliser set :public_folder, 'public'. C'était la clé pour le faire fonctionner, malgré la documentation de Sinatra impliquant que cela était déjà défini par défaut.
Daniel C

12

Gardez à l'esprit qu'en production, votre serveur Web peut envoyer index.htmlautomatiquement afin que la demande ne parvienne jamais à Sinatra. C'est meilleur pour les performances car vous n'avez pas à passer par la pile Sinatra / Rack juste pour servir du texte statique, ce que Apache / Nginx est génial à faire.


Oh ouais, duh. J'utiliserai juste Erb alors et utiliserai Varnish pour l'encaisser.
ma11hew28

2
Comment configurez-vous cela en production? J'ai cherché de la documentation sur ce référencement croisé avec Sinatra et Rack mais je ne peux pas la trouver. Fondamentalement, je veux que index.html soit chargé dans n'importe quel dossier / public qui en a un si l'utilisateur ne met que le nom du dossier

12

Sinatra devrait vous permettre de servir des fichiers statiques à partir du répertoire public comme expliqué dans la documentation :

Fichiers statiques

Les fichiers statiques sont servis à partir du répertoire ./public. Vous pouvez spécifier un emplacement différent en définissant l'option: public:

Notez que le nom du répertoire public n'est pas inclus dans l'URL. Un fichier ./public/css/style.css est mis à disposition sous le nom example.com/css/style.css.


4
Pourquoi cela a-t-il 4 votes? Il ne répond pas à la question de savoir comment présenter un document par défaut lorsqu'un dossier est demandé.
Derek Prior


2

le joyau sinatra-assetpack offre tout un tas de fonctionnalités. la syntaxe est douce:

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

alors que j'ai toujours des problèmes avec le pipeline des actifs de rails, j'ai l'impression d'avoir beaucoup plus de contrôle en utilisant sinatra-assetpack - mais la plupart du temps, cela ne fonctionne qu'avec quelques lignes de code.


2

RÉPONSE MIS À JOUR : J'ai lié tout ce qui précède sans chance de pouvoir charger css, js .... etc contenu la seule chose qui était en cours de chargement est index.html ... et le reste allait = >>404 error

Ma solution: le dossier de l'application ressemble à ceci.

index.rb == >> Le code 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== >> contient tout le reste ... 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$

Maintenant, démarrez le serveur et vous pourrez naviguer sans problème dans les pages statiques.

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

Vous pouvez envisager de déplacer le index.htmlfichier vers views/index.erbet de définir un point de terminaison comme:

get '/' do
  erb :index
end

0

Le placement de fichiers dans un publicdossier a une limitation. En fait, lorsque vous êtes dans le '/'chemin racine , cela fonctionne correctement car le navigateur définira le chemin relatif de votre fichier css par exemple /css/style.csset sinatra recherchera le fichier dans le publicrépertoire. Cependant, si votre emplacement est par exemple /user/create, le navigateur Web recherchera votre fichier css dans/user/create/css/style.css et échouera.

Pour contourner le problème, j'ai ajouté la redirection suivante pour charger correctement le fichier css:

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

-7

Et cette solution? :

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

donc si vous naviguez maintenant vers (par exemple) / sous-répertoire / test / il chargera le sous-répertoire / test / index.html

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.