如何使用标准库解析Ruby中的URL参数?

如何使用标准库解析Ruby中的URL参数?,ruby,http,webserver,Ruby,Http,Webserver,我使用以下带有“uri”和“CGI”的代码来解析URL的参数: require 'socket' require 'uri' require 'CGI' server = TCPServer.new 8888 while session = server.accept request = session.gets p "request", request url = "http://somewebsite.com" + request.sub("GET ", "").sub(

我使用以下带有“uri”和“CGI”的代码来解析URL的参数:

require 'socket'
require 'uri'
require 'CGI'

server = TCPServer.new 8888

while session = server.accept
  request = session.gets

  p "request", request

  url = "http://somewebsite.com" + request.sub("GET ", "").sub(" HTTP/1.1", "").gsub(/(\r|\n)/, "")
  uri = URI(url)
  params = CGI.parse(uri.query)

  p "params", params

  session.print "HTTP/1.1 200\r\n" # 1
  session.print "Content-Type: text/html\r\n" # 2
  session.print "\r\n" # 3

  session.print "Hello world! The time is #{Time.now}" #4

  session.close
end
我必须通过添加
http://somewebsite.com
指向路径,并使用
uri
CGI
函数执行此操作。如果浏览器使用,那么它工作得很好。但是,如果浏览器试图访问或随后立即中断,则表示无法拆分。(在
CGI.parse(uri.query)
处失败)

我可以把电话换成

params = uri.query ? CGI.parse(uri.query) : nil
但整个过程似乎有点麻烦,需要创建一个URL,然后如果查询不存在,
CGI.parse
就会中断。有没有更好的方法使用标准库来实现这一点?(是否应该使用其他内容而不是
uri
CGI
?)

(使用标准库的优点是可以自动处理
%20
的案例和中的多个参数,给出


因此。)

你为什么要编造什么?使用
CGI.parse
不需要完整的URI。像这样的方法应该会奏效:

require 'socket'
require 'CGI'

server = TCPServer.new 8888

while session = server.accept
  request = session.gets

  method, full_path = request.split(' ')
  path, params = full_path.split('?')

  params = CGI.parse(params.gsub('?','')) if params

  session.print "HTTP/1.1 200\r\n" # 1
  session.print "Content-Type: text/html\r\n" # 2
  session.print "\r\n" # 3
  session.print "Hello world! The time is #{Time.now}" #4
  session.print "\nparams: #{params}"

  p "params:", params

  session.close
end

如果您不想了解如何重新发明CGI控制盘,也可以使用Rack。从技术上讲,机架不是标准库的一部分,但它离标准库很近

# Gemfile.rb
gem 'rack'

运行
$bundle安装

# application.rb
class Application
  # This is the main entry point for Rack
  # @param env [Hash]
  # @return [Array] status, headers, body
  # @see https://www.rubydoc.info/gems/rack/Rack/Request
  # @see https://www.rubydoc.info/gems/rack/Rack/Response
  def self.call(env)
    request = Rack::Request.new(env)
    Rack::Response.new(
      "Hello " + request.params["name"] || "World",
      200,
      { "Content-Type" => "text/plain" }
    ).finish
  end
end
request.params
是一个散列,包含查询字符串参数和POST请求的请求正文参数

# config.ru
require 'rack'
require_relative 'application'
run Application

运行
$rackup
以启动服务器。

这应该回到webrick。您还可以通过将gems添加到Gemfile来使用thin或puma。是
thin
还是
puma
优于
webrick
?我看到由本地文件启动的webrick未被服务——如何使其服务于本地文件?似乎需要(1)
“Hello”+(request.params[“name”]| |“World”)
(2)
require./application'
您可以在代码中指定端口,而不是启动
rackup-p 8888
?Webrick并不是真正最棒的。我真的很推荐彪马。我认为您可以通过
运行应用程序来指定端口,port:8888
,但通常通过设置Procfile来完成。paren在
“Hello”+(request.params[“name”]| |“World”)
中实际上什么都不做+
实际上是一种方法,所以
“Hello”+请求。params[“name”]| |“World”
评估
请求。params[“name”]| |“World”
首先是这样。按空间分割,然后按
分割,似乎有点低级。。。但我想这是可行的,没有例外情况。。。如果有类似于
方法、路径、参数、协议=CGI.split_请求(request)
(它是否属于
CGI
)的东西,它会工作得更好吗?顺便说一句,我们也可以使用WeBrick的单行启动,并且能够使用
foo.CGI
,并运行Ruby程序。。。在这种情况下,
cgi_request=cgi::new(“html4”)
cgi_请求。params
将随时可用。对于如何解析
会话,没有设置规则。get
以字符串形式出现。做最适合您的用例的事情。在我的回答的早期版本中,我有
方法、uz、参数、协议、version=request.split(/[\s\/]/)
@nopole您在这里的评论中提出并回答了您自己的问题吗?
# config.ru
require 'rack'
require_relative 'application'
run Application