Reputation: 150986
I am using the following code with "uri" and "CGI" to parse the params of the 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
I had to "make up" a full URL by adding the http://somewebsite.com
to the path, and use uri
and CGI
functions to do it. If the browser uses http://localhost:8888/?a=123&b=hello then it works well. But if the browser tried to access http://localhost:8888/favicon.ico or http://localhost:8888 then it broke right away, saying cannot split. (failing at CGI.parse(uri.query)
)
I can change the line to
params = uri.query ? CGI.parse(uri.query) : nil
but the whole thing seems a bit hacky, needing to make up a URL and then CGI.parse
would break if query doesn't exist. Is there actually a better way to use standard library to do it? (should something else be used instead of uri
and CGI
?)
(Using standard library has the advantage of automatically handling the cases for %20
and multiple params as in http://localhost:8888/?a=123&b=hello%20world&b=good, giving
{"a"=>["123"], "b"=>["hello world", "good"]}
as the result.)
Upvotes: 1
Views: 743
Reputation: 101891
You could also just use Rack if you don't want to learn about reinventing the CGI wheel. Rack is not technically part of the standard library but is as close as you get.
# 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
is a hash that contains query string parameters and parameters from the request body for POST requests.
# config.ru
require 'rack'
require_relative 'application'
run Application
Run $ rackup
to start the server.
Upvotes: 1
Reputation: 11206
Why do you need to make up anything? You don't need a full URI to use CGI.parse
. Something like this should work:
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
Upvotes: 1