Question

Je travaille sur un site Web hébergé sur le bureau de service Microsoft en direct. Il a une forme de contact permettant aux visiteurs d'entrer en contact avec le propriétaire. Je veux écrire un script Ruby qui se trouve sur un sever séparé et que le formulaire POST à. Il analysera les données de formulaire et envoyez les détails à une adresse prédéfinie. Le script doit alors rediriger le navigateur vers une page de confirmation.

J'ai une machine à ubuntu hardy courir nginx et Postfix. Ruby est installé et nous verrons sur l'utilisation de Thin et ses fonctionnalités de rack pour gérer le script. Maintenant, il est venu à l'écriture du scénario et je l'ai fait chou blanc.

Il a été longtemps et si je me souviens bien le processus est quelque chose comme:

  • lire tête HTTP
  • analyser les paramètres
  • envoyez un courriel
  • envoyer en-tête de redirection

D'une manière générale, a été répondu à la question. Comprendre comment utiliser la réponse était plus compliquée que prévu et je pensais partager.

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 obtenir nginx aux demandes de proxy sur. Si je faisais cela en php (qui à la vue arrière, je pense aurait été un choix plus naturel) que je pourrais utiliser quelque chose comme php-fcgi et attendre la vie serait assez simple.

Ruby et fcgi sentait assez intimidante. Mais si nous abandonnons l'idéal de charger ces choses lors de l'exécution alors rack est probablement la solution la plus directe et mince comprend tout ce qu'il faut. Apprendre à faire de petites applications de base avec eux a été profondément bénéfique pour un nouveau venu Rails par rapport comme moi. Les bases d'une application Rails peuvent paraître cachés pendant longtemps et rack m'a permis de lever le rideau que peu plus loin.

Néanmoins, suivant les conseils de Yehuda et regardant sinatra a été une autre surprise. J'ai maintenant une application de base en cours d'exécution dans sinatra une instance mince. Il communique avec nginx sur une prise unix dans ce que je crois est la manière standard. Sinatra permet vraiment un moyen élégant pour traiter les demandes et les itinéraires différents dans l'application. Tout ce que vous avez besoin est un get '/' {} pour commencer le traitement des demandes à l'hôte virtuel. Pour ajouter plus (de façon propre) nous incluons à seulement 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 me attendais à laisser tranquillement nginx savoir que les fichiers .rb devaient être exécutés et pour obtenir juste avec elle. Maintenant que cette petite application est sinatra et la course, je serai en mesure de plonger directement si je veux ajouter des fonctionnalités supplémentaires à l'avenir.

Mise en œuvre:

Les poignées de classe ContactPost l'aspect de la messagerie. Tout ce qu'il a besoin de savoir sont les paramètres de la demande et la cible pour l'e-mail. ContactPost :: l'action démarre tout de et retourne une adresse pour le contrôleur de redirection.

Il y a une classe ContactTarget distincte qui fait une authentification pour vous assurer que la cible spécifiée accepte les messages de l'URL donnée dans request.referrer. Ceci est géré en ContactTarget :: accepter? comme on peut le deviner à partir de la méthode :: l'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. futurs sites Web qui utilisent ce script juste besoin d'être énumérés dans son propre ~ / cgi / contact.conf de l'utilisateur et ils seront loin. En effet, ContactTarget regarde dans /home/:target/cgi/contact.conf pour les détails. ONEDAY Peut-être que ce sera inappropriée, mais pour l'instant, il est très bien pour mes besoins.

L'envoi rencontréHod est assez simple, il crée une instance d'une classe simple e-mail et l'expédie sur. La classe Email est à peu près basée sur l'exemple d'utilisation standard donné dans la documentation nette / smtp Ruby;

# lib/email/email.rb
require 'net/smtp'

class Email
  def initialize(from_alias, to, reply, subject, body)
    @from_alias = from_alias
    @from = "cgi_user@host.domain.com"
    @to = to
    @reply = reply
    @subject = subject
    @body = body
  end

  def send
    Net::SMTP.start('localhost', 25) do |smtp|
      smtp.send_message to_s, @from, @to
    end
  end

  def to_s
<<END_OF_MESSAGE
From: #{@from_alias} 
To: #{@to} 
Reply-To: #{@from_alias} 
Subject: #{@subject}
Date: #{DateTime::now().to_s}

#{@body}
END_OF_MESSAGE
  end
end

Tout ce que je dois faire est l'application engranger, laissez nginx savoir quel socket pour parler et nous sommes loin.

Merci à tous pour vos conseils utiles dans la bonne direction! sinatra Vive!

Était-ce utile?

La solution

Probablement la meilleure façon de le faire serait d'utiliser une bibliothèque Ruby existante comme Sinatra:

require "rubygems"
require "sinatra"

get "/myurl" do
  # params hash available here
  # send email
end

Vous voudrez probablement utiliser MailFactory pour envoyer l'e-mail réelle, mais vous avez certainement pas besoin d'être déblayage sur les en-têtes ou des paramètres d'analyse syntaxique.

Autres conseils

Il est dans le module Net, voici un exemple:

  @net = Net::HTTP.new 'http://www.foo.com', 80
  @params = {:name => 'doris', :email => 'doris@foo.com'}

  # Create HTTP request
  req = Net::HTTP::Post.new( 'script.cgi', {} )
  req.set_form_data @params

  # Send request
  response = @net.start do |http|
    http.read_timeout = 5600
    http.request req
  end

classe CGI de Ruby peut être utilisé pour écrire des scripts CGI. S'il vous plaît vérifier: http://www.ruby-doc.org /stdlib/libdoc/cgi/rdoc/index.html

Par ailleurs, il n'y a pas besoin de lire l'en-tête HTTP. Parsing seront faciles paramètres en utilisant la classe CGI. Ensuite, envoyez le courrier électronique et rediriger.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top