ruby sinatra 服务器中的 CGI
CGI in a ruby sinatra server
我正在使用 sinatra 和 ruby 开发一个简单的网络应用程序,我有两个文件:app.rb
是我的 sinatra 应用程序,test.cgi
是一个 CGI 程序。我需要执行CGI脚本,例如:
#!/usr/bin/env ruby
# encoding: utf-8
# app.rb
require "sinatra"
get "/form" do
File.read("my_web_form.html")
end
post "/form" do
# I need execute the CGI script, but this not works:
cgi "text.cgi"
end
我的 CGI 脚本是一种自定义语言(我有一个自己创建的解释器),我尝试将它嵌入到网络应用程序中。谢谢
我已经进行了一些搜索,但无法按照您尝试的方式(这是直观的方式)找到 "render CGI" 的方法。
不过,您似乎确实可以 运行 Sinata 来自 CGI。有关代码示例,请参阅 here。
几天前我其实也在尝试这样做,但我想我放弃了。但是看到你的问题鼓励我弄清楚。请参阅以下有关如何从 sinatra 呈现 CGI 的示例:
一个示例 CGI 文件,假设它位于 ./app.cgi
并且 chmod +x
已经 运行
#!/usr/bin/env ruby
require "cgi"
cgi = CGI.new("html4")
cgi.out{
cgi.html{
cgi.head{ "\n"+cgi.title{"This Is a Test"} } +
cgi.body{ "\n"+
cgi.h1 { "This is a Test" } + "\n"+
}
}
}
定义render_cgi
方法的模块:
class RenderCgiError < StandardError
end
module RenderCgi
def render_cgi(filepath, options={})
headers_string, body = run_cgi_and_parse_output(filepath, options)
headers_hash = parse_headers_string(headers_string)
response = Rack::Response.new
headers_hash.each { |k,v| response.header[k] = v }
response.body << body
response
end
private
def run_cgi_and_parse_output(filepath, options={})
options_string = options.reduce("") { |str, (k,v)| str << "#{k}=#{v} " }
# make sure options has at least one key-val pair, otherwise running the CGI may hang
if options_string.split("=").select { |part| (part&.length || -1) > 0 }.length < 2
raise(RenderCgiError, "one truthy key and associated truthy val is required for options")
end
output = `sh #{filepath} #{options_string}`
headers_string, body = output.split("\n\r")
return [headers_string, body]
end
def parse_headers_string(string)
return string.split("\n").reduce({}) do |results, line|
key, val = line.split(": ")
results[key.chomp] = val.chomp
next results
end
end
end
和一个 Sinatra 应用 运行就是它
require 'sinatra'
class MyApp < Sinatra::Base
include RenderCgi
get '/' do
render_cgi("./app.cgi", { "foo" => "bar" })
end
end
MyApp.run!
我正在使用 sinatra 和 ruby 开发一个简单的网络应用程序,我有两个文件:app.rb
是我的 sinatra 应用程序,test.cgi
是一个 CGI 程序。我需要执行CGI脚本,例如:
#!/usr/bin/env ruby
# encoding: utf-8
# app.rb
require "sinatra"
get "/form" do
File.read("my_web_form.html")
end
post "/form" do
# I need execute the CGI script, but this not works:
cgi "text.cgi"
end
我的 CGI 脚本是一种自定义语言(我有一个自己创建的解释器),我尝试将它嵌入到网络应用程序中。谢谢
我已经进行了一些搜索,但无法按照您尝试的方式(这是直观的方式)找到 "render CGI" 的方法。
不过,您似乎确实可以 运行 Sinata 来自 CGI。有关代码示例,请参阅 here。
几天前我其实也在尝试这样做,但我想我放弃了。但是看到你的问题鼓励我弄清楚。请参阅以下有关如何从 sinatra 呈现 CGI 的示例:
一个示例 CGI 文件,假设它位于 ./app.cgi
并且 chmod +x
已经 运行
#!/usr/bin/env ruby
require "cgi"
cgi = CGI.new("html4")
cgi.out{
cgi.html{
cgi.head{ "\n"+cgi.title{"This Is a Test"} } +
cgi.body{ "\n"+
cgi.h1 { "This is a Test" } + "\n"+
}
}
}
定义render_cgi
方法的模块:
class RenderCgiError < StandardError
end
module RenderCgi
def render_cgi(filepath, options={})
headers_string, body = run_cgi_and_parse_output(filepath, options)
headers_hash = parse_headers_string(headers_string)
response = Rack::Response.new
headers_hash.each { |k,v| response.header[k] = v }
response.body << body
response
end
private
def run_cgi_and_parse_output(filepath, options={})
options_string = options.reduce("") { |str, (k,v)| str << "#{k}=#{v} " }
# make sure options has at least one key-val pair, otherwise running the CGI may hang
if options_string.split("=").select { |part| (part&.length || -1) > 0 }.length < 2
raise(RenderCgiError, "one truthy key and associated truthy val is required for options")
end
output = `sh #{filepath} #{options_string}`
headers_string, body = output.split("\n\r")
return [headers_string, body]
end
def parse_headers_string(string)
return string.split("\n").reduce({}) do |results, line|
key, val = line.split(": ")
results[key.chomp] = val.chomp
next results
end
end
end
和一个 Sinatra 应用 运行就是它
require 'sinatra'
class MyApp < Sinatra::Base
include RenderCgi
get '/' do
render_cgi("./app.cgi", { "foo" => "bar" })
end
end
MyApp.run!