Pergunta

Eu estou trabalhando em um site hospedado no serviço Office Live, da Microsoft. Tem um formulário de contato permitindo que os visitantes para entrar em contato com o proprietário. Eu quero escrever um script Ruby que fica em uma Sever separado e que a forma vai post para. Ele irá analisar os dados do formulário e enviar e-mail os detalhes para um endereço pré-definido. O script deve, então, redirecionar o browser para uma página de confirmação.

Eu tenho uma máquina resistente ubuntu correndo nginx e postfix. Ruby está instalado e veremos sobre o uso fina e é cremalheira funcionalidade para lidar com o script. Agora é vir a escrever o roteiro e eu desenhei um em branco.

Tem sido um longo tempo e se bem me lembro o processo é algo como;

  • ler cabeçalho HTTP
  • parse parâmetros
  • Enviar e-mail
  • Enviar redirecionamento de cabeçalho

Em termos gerais, a questão foi respondida. Descobrir como usar a resposta foi mais complicado do que o esperado e eu pensei que vale a pena compartilhar.

Primeiros passos:

Eu aprendi bastante abruptamente que nginx não suporta diretamente scripts CGI. Você tem que usar algum outro processo para executar o script e obter nginx para pedidos de proxy mais. Se eu estava fazendo isso em php (que na visão traseira eu acho que teria sido uma escolha mais natural) eu poderia usar algo como php-fcgi e esperar que a vida seria bastante simples.

Ruby e fcgi senti muito assustadora. Mas se estamos abandonando o ideal de carregar essas coisas em tempo de execução, em seguida, rack é provavelmente a solução mais simples e Thin inclui toda a necessidade que nós. Aprender a fazer aplicativos pequenos básicos com eles tem sido profundamente benéfico a um parente recém-chegado Rails como eu. Os fundamentos de uma aplicação Rails pode parecer escondido por um longo tempo e cremalheira me ajudou a levantar a cortina que pouco mais.

No entanto, seguindo o conselho de Yehuda e olhando para cima Sinatra foi outra surpresa. Agora tenho um aplicativo de Sinatra básica em execução em uma instância fina. Ele se comunica com nginx através de um socket unix em que percebo é a maneira padrão. Sinatra permite uma maneira muito elegante de tratar diferentes solicitações e rotas para o aplicativo. Tudo que você precisa é de um get '/' {} para começar a lidar com pedidos ao host virtual. Para adicionar mais (de uma forma limpa) que basta incluir um rotas / script.rb no arquivo 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

Esses arquivos de rota irá chamar a funcionalidade armazenado em uma biblioteca separada de classes:

# 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

O horror de descobrir uma coisa tão simples vai ficar comigo por um tempo. Eu estava esperando para deixar calmamente nginx saber que os arquivos .rb estavam para ser executados e apenas para ir em frente. Agora que este pequeno aplicativo Sinatra está instalado e funcionando, eu vou ser capaz de mergulhar de cabeça se eu quiser adicionar funcionalidades extras no futuro.

Implementação:

A classe ContactPost lida com o aspecto de mensagens. Tudo o que precisa saber são os parâmetros do pedido e a meta para o e-mail. chutes ContactPost :: Ação tudo fora e retorna um endereço para o controlador para redirecionar para.

Há uma classe ContactTarget separado que faz alguma autenticação para garantir que o destino especificado aceita mensagens a partir do URL dado na request.referrer. Isso é tratado em ContactTarget :: aceitar? como se pode imaginar a partir do ContactPost :: método de ação;


# lib/contact/contactPost.rb

class ContactPost

# ...

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

# ...

end

ContactPost :: sucesso e ContactPost :: falhou cada retorno de um endereço de redirecionamento através da combinação de caminhos fornecidos com o formulário HTML com o request.referer URI. Todo o comportamento é, portanto, especificada no formulário HTML. sites futuras que usam esse script só precisa ser listada na usuário próprio ~ / cgi / contact.conf e eles vão ser afastado. Isso ocorre porque ContactTarget olha no /home/:target/cgi/contact.conf para os detalhes. Talvez um dia isso vai ser inadequada, mas por agora é apenas multa para os meus propósitos.

O envio conheceuhod é suficiente simples, ele cria uma instância de uma classe simples e-mail e navios para fora. A classe E-mail é praticamente baseado no exemplo de uso padrão dados na documentação net / smtp Rubi;

# 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

Tudo o que precisa fazer é acumular a aplicação, vamos nginx saber qual soquete para conversar e estamos longe.

Obrigado a todos por seus votos ponteiros na direção certa! Sinatra Viva!

Foi útil?

Solução

Provavelmente a melhor maneira de fazer isso seria usar uma biblioteca Ruby existente, como Sinatra:

require "rubygems"
require "sinatra"

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

Você provavelmente vai querer usar MailFactory para enviar o e-mail real, mas você definitivamente não precisa ser mucking com cabeçalhos ou analisar parâmetros.

Outras dicas

É tudo no módulo Net, aqui está um exemplo:

  @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 do Ruby pode ser usado para escrever scripts CGI. Por favor, verifique: http://www.ruby-doc.org /stdlib/libdoc/cgi/rdoc/index.html

A propósito, não há necessidade de ler o cabeçalho HTTP. parametros parsing será fácil usando a classe CGI. Em seguida, enviar o e-mail e de redirecionamento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top