Domanda

Sto lavorando su un sito web ospitato su ufficio di servizio live di Microsoft. Ha un modulo di contatto che permette ai visitatori di entrare in contatto con il proprietario. Voglio scrivere uno script di Ruby che si siede su un sever separata e che il modulo sarà POST a. Sarà analizzare i dati del modulo e-mail i dettagli a un indirizzo prestabilito. Lo script dovrebbe quindi reindirizzare il browser a una pagina di conferma.

Ho una macchina robusta Ubuntu in esecuzione nginx e Postfix. Rubino è installato e vedremo di usare sottile ed è la funzionalità Rack per gestire lo script. Ora è venuto a scrivere la sceneggiatura e ho disegnato un vuoto.

E 'stato un lungo periodo di tempo e se non ricordo male il processo è qualcosa di simile;

  • leggi HTTP intestazione
  • parse parametri
  • invia un'email
  • inviare intestazione redirect

In linea generale, la questione è stata risolta. Capire come utilizzare la risposta è stata più complicata del previsto e ho pensato che vale la pena condividere.

Primi passi:

Ho imparato piuttosto bruscamente che nginx non supporta direttamente script CGI. Devi usare un altro processo per eseguire lo script e ottenere nginx per le richieste proxy sopra. Se stavo facendo questo in php (che in vista posteriori penso che sarebbe stata una scelta più naturale) potrei usare qualcosa come php-fcgi e si aspettano la vita sarebbe piuttosto semplice.

Ruby e fcgi sentivo abbastanza scoraggiante. Ma se noi abbandoniamo l'ideale di caricamento di queste cose, allora in fase di esecuzione Rack è probabilmente la soluzione più avanti dritto e sottile include tutti abbiamo bisogno. Imparare a fare piccole applicazioni di base con loro è stata profondamente utile per un parente nuovo arrivato Rails come me. Le fondamenta di un'applicazione Rails può sembrare nascosto per molto tempo e Rack mi ha aiutato sollevare la cortina di quel qualcosa in più.

Tuttavia, seguendo il consiglio di Yehuda e alzando lo sguardo Sinatra è stata un'altra sorpresa. Ora ho un app Sinatra base in esecuzione in un'istanza sottile. Comunica con nginx su un socket unix in quanto ho capito è il modo standard. Sinatra permette un modo molto elegante per gestire le diverse richieste e percorsi in app. Tutto ciò che serve è un get '/' {} per iniziare a gestire le richieste per l'host virtuale. Per aggiungere più (in modo pulito) abbiamo appena includere un itinerari / script.rb nel file principale.

# 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

Questi file percorso chiameranno sulla funzionalità memorizzati in una libreria separata di classi:

# 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'orrore di capire una cosa così semplice rimarrà con me per un po '. Mi aspettavo di lasciare tranquillamente nginx sapere che i file .RB dovevano essere eseguiti e per ottenere appena sopra con esso. Ora che questa piccola applicazione Sinatra è attivo e funzionante, sarò in grado di immergersi dritto se voglio aggiungere altre funzionalità in futuro.

Implementazione:

La classe ContactPost gestisce l'aspetto di messaggistica. Tutto ciò che ha bisogno di sapere sono i parametri nella richiesta e l'obiettivo per l'e-mail. ContactPost :: azione prende tutto fuori e restituisce un indirizzo per il controller per reindirizzare.

C'è una classe ContactTarget separata che fa un po 'di autenticazione per assicurarsi che la destinazione specificata accetta messaggio per l'URL specificato in request.referrer. Questo è gestito in ContactTarget :: accettare? come si può intuire dal metodo di ContactPost :: azione;


# lib/contact/contactPost.rb

class ContactPost

# ...

  def action
    return failed unless @target.accept? @request.referer
    if send?
      successful
    else
      failed
    end
  end

# ...

end

ContactPost :: successo e ContactPost :: fallito ogni ritorno un indirizzo di reindirizzamento combinando percorsi fornite con il modulo HTML con il request.referer URI. Tutto il comportamento è quindi specificato nel modulo HTML. siti web futuri che utilizzano questo script solo bisogno di essere elencati in proprio ~ / cgi / contact.conf dell'utente e saranno via. Questo perché ContactTarget guarda in /home/:target/cgi/contact.conf per i dettagli. Forse oneday questo sarà inadeguato, ma per ora è solo bene per i miei scopi.

L'invio incontratohod è abbastanza semplice, si crea un'istanza di una classe semplice e-mail e le navi esso fuori. La classe E-mail è praticamente basa su un utilizzo esempio standard indicato nella documentazione di Rubino net / smtp;

# 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

Tutto quello che devi fare è accumulare l'applicazione, lasciare che nginx sapere quale presa con cui parlare e siamo lontani.

Grazie a tutti per le vostre indicazioni utili nella giusta direzione! Lunga Sinatra dal vivo!

È stato utile?

Soluzione

Probabilmente il modo migliore per farlo sarebbe quello di utilizzare una libreria Ruby esistente come Sinatra:

require "rubygems"
require "sinatra"

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

Probabilmente desidera utilizzare MailFactory per inviare l'e-mail reale, ma sicuramente non c'è bisogno di essere pasticciare in giro con le intestazioni o parametri di analisi.

Altri suggerimenti

E 'tutto nel modulo Rete, ecco un esempio:

  @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 di Ruby può essere utilizzato per la scrittura di script CGI. Si prega di verificare: http://www.ruby-doc.org /stdlib/libdoc/cgi/rdoc/index.html

A proposito, non v'è alcuna necessità di leggere l'intestazione HTTP. parametri parsing sarà facile utilizzando la classe CGI. Quindi, inviare l'e-mail e reindirizzare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top