发表一个HTML表单到remote.cgi - 用Ruby编写? [英] POSTing an HTML form to remote.cgi - written in Ruby?

查看:150
本文介绍了发表一个HTML表单到remote.cgi - 用Ruby编写?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在微软办公室现场服务的网站上工作。它有一个联系表格,使访客能够与业主联系。我想编写一个位于一个独立的服务器上的Ruby脚本,该表单将POST。它将解析表单数据并将详细信息发送到预设地址。脚本应该将浏览器重定向到确认页面。



我有一个运行nginx和postfix的ubuntu hardy机器。安装了Ruby,我们将会看到使用Thin和它的Rack功能来处理脚本。现在来编写脚本,我已经写了一个空白。



已经很久了,如果我记得这个过程就是这样的;




  • 读取HTTP标头

  • 解析参数

  • 发送电子邮件

  • 发送重定向头



广义而言,问题已经得到回答。了解如何使用答案比预期更复杂,我认为值得分享。



第一步:



我相当突然地学到,nginx不直接支持cgi脚本。您必须使用一些其他进程来运行脚本,并将nginx提交给代理请求。如果我在php中这样做(在后面我认为本来就是一个更自然的选择),我可以使用像php-fcgi这样的东西,期望生活会很直接。


$ b $ Ruby和fcgi感到非常难过。但是如果我们放弃在运行时加载这些东西的理想,那么Rack可能是最直接的解决方案,而Thin包含了我们所需要的。学习如何使基本的小应用程序对于像我这样的相对Rails新手来说是非常有益的。 Rails应用程序的基础可能看起来很长一段时间,Rack已经帮助我提升了一点点进一步。



尽管如此,遵循耶胡达的建议和查找sinatra又一次惊喜我现在有一个基本的sinatra应用程序运行在一个薄的实例。它通过unix套接字与nginx进行通信,我收集的是标准方式。 Sinatra可以非常优雅的方式来处理不同的请求和路由到应用程序。所有你需要的是一个 get'/'{} 来开始处理对虚拟主机的请求。要添加更多(以干净的方式),我们只需在主文件中包含一个路由/ script.rb。

 
#cgi-bin.rb
#主文件加载为sinatra app

require'sinatra'

#load cgi routes
require'routes / default'
require'routes / contact'

#404行为
not_found do
对不起,这个CGI主机不承认这个请求。
end

这些路由文件将调用存储在单独的类库中的功能: / p>

 #routes / contact.rb 
#contact controller

require'lib / contact / contactTarget'
要求'lib / contact / contactPost'

post'/ contact /:target /?'do | target |
#邮件的目标取自URL
msg = ContactPost.new(request,target)
redirect msg.action,302
end

找出这样一件简单的事情的绝妙恐怖将与我保持一段时间。我期待着宁静地让nginx知道那个.rb文件被执行并且刚刚得到它。现在这个小小的sinatra应用程序正在运行,如果我想在未来添加额外的功能,我可以直接潜入。



实现:



ContactPost类处理消息传递方面。所有需要知道的是请求中的参数和电子邮件的目标。 ContactPost :: action将一切都关闭,并返回控制器重定向到的地址。



有一个单独的ContactTarget类进行一些验证,以确保指定的目标接受来自request.referrer中给出的URL的消息。这是在ContactTarget :: accept处理?正如我们可以从ContactPost :: action方法猜到的那样;

  
#lib / contact / contactPost.rb

class ContactPost

#...

def action
返回失败,除非@ target.accept? @ request.referer
如果发送?
success
else
failed
end
end

#...

end

ContactPost :: success和ContactPost :: failed通过将HTML表单提供的路径与request.referer URI相结合,返回重定向地址。所有的行为都是以HTML格式指定的。使用此脚本的未来网站只需要在用户自己的〜/ cgi / contact.conf中列出,它们将被删除。这是因为ContactTarget查看/home/:target/cgi/contact.conf中的详细信息。也许这是不合适的,但现在对我的目的来说很好。



发送方法很简单,它创建了一个简单的电子邮件类的实例,出来。 Email类基本上是基于Ruby net / smtp文档中给出的标准使用示例;

 #lib / email / email.rb 
需要'net / smtp'

class电子邮件
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}
回复:#{@ from_alias}
主题:#{@ subject}
日期:#{DateTime :: now()。to_s}

#{@ body}
END_OF_MESSAGE
end
end

所有我需要做的是架起应用程序,让nginx知道哪个套接字可以和我们离开。



谢谢你们每个人都有帮助的指针正确的方向!长寿的sinatra!

解决方案

可能最好的方法是使用现有的Ruby库,如Sinatra:


  requirerubygems
requiresinatra

get/ myurldo
#params hash here here
#发送电子邮件
end

你会可能想要使用MailFactory发送实际的电子邮件,但是您绝对不需要关注标题或解析参数。


I am working on a website hosted on microsoft's office live service. It has a contact form enabling visitors to get in touch with the owner. I want to write a Ruby script that sits on a seperate sever and which the form will POST to. It will parse the form data and email the details to a preset address. The script should then redirect the browser to a confirmation page.

I have an ubuntu hardy machine running nginx and postfix. Ruby is installed and we shall see about using Thin and it's Rack functionality to handle the script. Now it's come to writing the script and i've drawn a blank.

It's been a long time and if i remember rightly the process is something like;

  • read HTTP header
  • parse parameters
  • send email
  • send redirect header

Broadly speaking, the question has been answered. Figuring out how to use the answer was more complicated than expected and I thought worth sharing.

First Steps:

I learnt rather abruptly that nginx doesn't directly support cgi scripts. You have to use some other process to run the script and get nginx to proxy requests over. If I was doing this in php (which in hind sight i think would have been a more natural choice) i could use something like php-fcgi and expect life would be pretty straight forward.

Ruby and fcgi felt pretty daunting. But if we are abandoning the ideal of loading these things at runtime then Rack is probably the most straight forward solution and Thin includes all we need. Learning how to make basic little apps with them has been profoundly beneficial to a relative Rails newcomer like me. The foundations of a Rails app can seem hidden for a long time and Rack has helped me lift the curtain that little bit further.

Nonetheless, following Yehuda's advice and looking up sinatra has been another surprise. I now have a basic sinatra app running in a Thin instance. It communicates with nginx over a unix socket in what i gather is the standard way. Sinatra enables a really elegant way to handle different requests and routes into the app. All you need is a get '/' {} to start handling requests to the virtual host. To add more (in a clean fashion) we just include a routes/script.rb into the main file.

# 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

These route files will call on functionality stored in a separate library of 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

The sheer horror of figuring out such a simple thing will stay with me for a while. I was expecting to calmly let nginx know that .rb files were to be executed and to just get on with it. Now that this little sinatra app is up and running, I'll be able to dive straight in if I want to add extra functionality in the future.

Implementation:

The ContactPost class handles the messaging aspect. All it needs to know are the parameters in the request and the target for the email. ContactPost::action kicks everything off and returns an address for the controller to redirect to.

There is a separate ContactTarget class that does some authentication to make sure the specified target accepts messages from the URL given in request.referrer. This is handled in ContactTarget::accept? as we can guess from the ContactPost::action method;


# lib/contact/contactPost.rb

class ContactPost

# ...

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

# ...

end

ContactPost::successful and ContactPost::failed each return a redirect address by combining paths supplied with the HTML form with the request.referer URI. All the behaviour is thus specified in the HTML form. Future websites that use this script just need to be listed in the user's own ~/cgi/contact.conf and they'll be away. This is because ContactTarget looks in /home/:target/cgi/contact.conf for the details. Maybe oneday this will be inappropriate, but for now it's just fine for my purposes.

The send method is simple enough, it creates an instance of a simple Email class and ships it out. The Email class is pretty much based on the standard usage example given in the Ruby net/smtp documentation;

# 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

All I need to do is rack up the application, let nginx know which socket to talk to and we're away.

Thank you everyone for your helpful pointers in the right direction! Long live sinatra!

解决方案

Probably the best way to do this would be to use an existing Ruby library like Sinatra:

require "rubygems"
require "sinatra"

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

You'll probably want to use MailFactory to send the actual email, but you definitely don't need to be mucking about with headers or parsing parameters.

这篇关于发表一个HTML表单到remote.cgi - 用Ruby编写?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆