Je travaille sur un site Web hébergé sur le service en direct de Microsoft Office. Il dispose d'un formulaire de contact permettant aux visiteurs d'entrer en contact avec le propriétaire. Je veux écrire un script Ruby qui se trouve sur un serveur séparé et auquel le formulaire sera POST. Il va analyser les données du formulaire et envoyer les détails par e-mail à une adresse prédéfinie. Le script doit ensuite rediriger le navigateur vers une page de confirmation.POSTing un formulaire HTML à remote.cgi - écrit en Ruby?
J'ai une machine hardy ubuntu qui exécute nginx et postfix. Ruby est installé et nous verrons comment utiliser Thin et sa fonctionnalité Rack pour gérer le script. Maintenant, il est venu à l'écriture du script et j'ai dessiné un blanc.
Cela fait longtemps et si je me souviens bien le processus est quelque chose comme;
- lecture en-tête HTTP
- paramètres parse
- Envoyer email
- header envoyer redirect
D'une manière générale, la question a été répondu. Déterminer comment utiliser la réponse était plus compliqué que prévu et j'ai pensé que ça valait la peine d'être partagé.
Premiers pas:
j'ai appris assez brusquement que nginx ne supporte pas directement les scripts cgi. Vous devez utiliser un autre processus pour exécuter le script et envoyer nginx aux demandes de proxy. Si je faisais cela en php (qui, à mon avis, aurait été un choix plus naturel), je pourrais utiliser quelque chose comme php-fcgi et s'attendre à ce que la vie soit assez simple. Ruby et fcgi se sentaient plutôt décourageants. Mais si nous abandonnons l'idéal de charger ces choses à l'exécution alors Rack est probablement la solution la plus directe et Thin inclut tout ce dont nous avons besoin. Apprendre à faire de petites applications de base avec eux a été profondément bénéfique pour un nouveau venu Rails comme moi. Les bases d'une application Rails peuvent sembler cachées depuis longtemps et Rack m'a aidé à lever le rideau un peu plus loin. Néanmoins, suivre les conseils de Yehuda et regarder sinatra a été une autre surprise. J'ai maintenant une application basique de sinatra fonctionnant dans une instance mince. Il communique avec nginx sur une socket unix dans ce que je comprends est le moyen standard. Sinatra permet une manière très élégante de gérer différentes demandes et routes dans l'application. Tout ce dont vous avez besoin est un get '/' {}
pour commencer à gérer les demandes à l'hôte virtuel. Pour ajouter plus (d'une manière propre) nous incluons juste un routes/script.rb dans le fichier principal.
# cgi-bin.rb
# main file loaded as a sinatra app
require 'sinatra'
# load cgi routes
require 'routes/default'
require 'routes/contact'
# 404 behaviour
not_found do
"Sorry, this CGI host does not recognize that request."
end
Ces fichiers itinéraire appel à une fonctionnalité stockées dans une bibliothèque de classes séparées:
# routes/contact.rb
# contact controller
require 'lib/contact/contactTarget'
require 'lib/contact/contactPost'
post '/contact/:target/?' do |target|
# the target for the message is taken from the URL
msg = ContactPost.new(request, target)
redirect msg.action, 302
end
L'horreur pure de déterminer une chose si simple restera avec moi pendant un certain temps. Je m'attendais à laisser calmement nginx savoir que les fichiers .rb devaient être exécutés et juste continuer avec lui. Maintenant que cette petite application Sinatra est opérationnelle, je serai capable de plonger directement si je veux ajouter des fonctionnalités supplémentaires à l'avenir.
Mise en œuvre:
La classe gère ContactPost l'aspect de la messagerie.Tout ce qu'il faut savoir sont les paramètres dans la demande et la cible pour l'email. ContactPost :: action déclenche tout et renvoie une adresse pour le contrôleur à rediriger vers.
Il existe une classe ContactTarget distincte qui effectue une certaine authentification pour s'assurer que la cible spécifiée accepte les messages provenant de l'URL fournie dans request.referrer. Ceci est géré dans ContactTarget :: accept? comme on peut le deviner à partir de la méthode d'action ContactPost ::;
# lib/contact/contactPost.rb
class ContactPost
# ...
def action
return failed unless @target.accept? @request.referer
if send?
successful
else
failed
end
end
# ...
end
ContactPost :: succès et ContactPost :: a échoué chaque retour d'une adresse de redirection en combinant les chemins fournis avec le formulaire HTML avec l'URI request.referer. Tout le comportement est ainsi spécifié dans le formulaire HTML. Les futurs sites Web qui utilisent ce script doivent juste être listés dans le propre ~/cgi/contact.conf de l'utilisateur et ils seront absents. C'est parce que ContactTarget recherche dans /home/:target/cgi/contact.conf pour les détails. Peut-être qu'un jour ce sera inapproprié, mais pour l'instant c'est très bien pour mes objectifs.
La méthode send est assez simple, elle crée une instance d'une simple classe Email et l'expédie. La classe Email est basée sur l'exemple d'utilisation standard donné dans la documentation Ruby net/smtp; Tout ce que j'ai besoin de faire est de mettre l'application en rack, de laisser savoir à nginx à quelle prise parler et nous sommes partis.
Merci à tous pour vos conseils utiles dans la bonne direction! Vive sinatra!
"Ruby est installé et nginx est prêt à exécuter des fichiers ruby sur mon hôte virtuel choisi." Eh bien, je fignais. J'ai juste supposé que ce serait facile, donc je ne voulais pas encombrer la question avec ça. Nginx ne supporte pas directement les CGI. Le support est donné par procuration, généralement à une instance de fcgi, bien que je pense avoir trouvé comment faire travailler Ruby avec Thin donc je vais aller dans cette direction. Jusqu'à présent, cela aurait été plus facile en php! – deau