Как использовать стандартную библиотеку для разбора параметров URL в Ruby? - PullRequest
1 голос
/ 19 января 2020

Я использую следующий код с «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

Мне пришлось «составить» полный URL, добавив http://somewebsite.com к пути и используйте для этого функции uri и CGI. Если браузер использует http://localhost: 8888 /? A = 123 & b = hello , тогда он работает хорошо. Но если браузер попытался получить доступ к http://localhost: 8888 / favicon.ico или http://localhost: 8888 , он сразу же сломался, сказав, что разделение невозможно. (с ошибкой CGI.parse(uri.query))

Я могу изменить строку на

params = uri.query ? CGI.parse(uri.query) : nil

, но все это выглядит немного странно, нужно создать URL, а затем CGI.parse сломается если запрос не существует Есть ли на самом деле лучший способ использовать стандартную библиотеку, чтобы сделать это? (следует ли использовать что-то еще вместо uri и CGI?)

(Преимущество использования стандартной библиотеки заключается в автоматической обработке случаев для %20 и нескольких параметров, как в http://localhost : 8888 /? A = 123 & b = привет% 20world & b = хорошо , что дает

{"a"=>["123"], "b"=>["hello world", "good"]}

в результате.)

Ответы [ 2 ]

1 голос
/ 19 января 2020

Вы также можете просто использовать Rack, если не хотите учиться заново изобретать колесо CGI. Стойка технически не является частью стандартной библиотеки, но она настолько близка, насколько это возможно.

# Gemfile.rb
gem 'rack'

run $ bundle install.

# 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 - это га sh, что содержит параметры строки запроса и параметры из тела запроса для запросов POST.

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

Запустите $ rackup, чтобы запустить сервер.

1 голос
/ 19 января 2020

Зачем тебе что-то придумывать? Вам не нужен полный URI для использования CGI.parse. Примерно так должно работать:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...