tutorialspoint's simple web browser using tcpsocket - ruby

This piece of code supposedly gets the content of any web page:
require 'socket'
host = 'www.tutorialspoint.com' # The web server
port = 80 # Default HTTP port
path = "/index.htm" # The file we want
# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0\r\n\r\n"
socket = TCPSocket.open(host,port) # Connect to server
socket.print(request) # Send request
response = socket.read # Read complete response
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2)
puts headers
puts body
When I run it in the command line, I get a 404 Error, but when i go to www.tutorialspoint.com/index.htm it's there, so what gives?:
404 Error Information
Although, I don't have trouble using the open-uri library to get the contents of a web page. But I want to know how to use this one though.

Your request misses the Host parameter:
host = 'www.tutorialspoint.com' # The web server
port = 80 # Default HTTP port
path = "/index.htm" # The file we want
# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0\r\nHost: #{host}\r\n\r\n"
Note that apparently not all and every webserver require the "Host:" line (but see comments).

Related

Ruby server logging a socket's request thrice

I am writing a simple server in Ruby in order to understand the Socket module. Here is my code:
require 'socket'
s = TCPServer.new(3939)
loop do
c = s.accept
STDERR.puts c.gets
c.close
end
I simply want to print the request to the server console before closing the socket. Why does it print the request thrice, instead of just once?
If I curl that code
$ curl localhost:3939
I get an empty reply
curl: (52) Empty reply from server
and a single GET request
GET / HTTP/1.1

Simple server built on top of Raspbian refuses connections- fix?

Recently I have gotten a Raspberry Pi, and my first project I decided to build was a simple server that returns 'Hello World' to any and all clients. This is the code:
require 'socket' # Provides TCPServer and TCPSocket classes
puts 'initializing, standby'
server = TCPServer.new('localhost', 2345)
loop do
socket = server.accept
puts 'hello, this is alien'
request = socket.gets
STDERR.puts request
response = "Hello World!\n"
socket.print "HTTP/1.1 200 OK\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: #{response.bytesize}\r\n" +
"Connection: close\r\n"
socket.print "\r\n"
socket.print response
socket.close
end
When I run that, the command line outputs initializing, standby. But then when I go to a browser and put in http://localhost:2345/anything, it returns connection refused. Changing localhost to its IP address or hostname does not work either. I have successfully SSHed to the raspberry pi. What is the problem, and how do I fix it?
Your code:
server = TCPServer.new('localhost', 2345)
means the server only listens connections from localhost. You can access it from the pi that is:
curl localhost:2345
But if you want to access the server from outside the pi, the server has to listen connections from anywhere like the following:
server = TCPServer.new('0.0.0.0', 2345)

Ruby TCPServer fails to work sometimes

I've implemented a very simple kind of server in Ruby, using TCPServer. I have a Server class with serve method:
def serve
# Do the actual serving in a child process
#pid = fork do
# Trap signal sent by #stop or by pressing ^C
Signal.trap('INT') { exit }
# Create a new server on port 2835 (1 ounce = 28.35 grams)
server = TCPServer.new('localhost', 2835)
#logger.info 'Listening on http://localhost:2835...'
loop do
socket = server.accept
request_line = socket.gets
#logger.info "* #{request_line}"
socket.print "message"
socket.close
end
end
end
and a stop method:
def stop
#logger.info 'Shutting down'
Process.kill('INT', #pid)
Process.wait
#pid = nil
end
I run my server from the command line, using:
if __FILE__ == $0
server = Server.new
server.logger = Logger.new(STDOUT)
server.logger.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
begin
server.serve
Process.wait
rescue Interrupt
server.stop
end
end
The problem is that, sometimes, when I do ruby server.rb from my terminal, the server starts, but when I try to make a request on localhost:2835, it fails. Only after several requests it starts serving some pages. In other cases, I need to stop/start the server again for it to properly serve pages. Why is this happening? Am I doing something wrong? I find this very weird...
The same things applies to my specs: I have some specs defined, and some Capybara specs. Before each test I create a server and start it and after each test I stop the server. And the problem persists: tests sometimes pass, sometimes fail because the requested page could not be found.
Is there something fishy going on with my forking?
Would appreciate any answer because I have no more place to look...
Your code is not an HTTP server. It is a TCP server that sends the string "message" over the socket after receiving a newline.
The reason that your code isn't a valid HTTP server is that it doesn't conform to the HTTP protocol. One of the many requirements of the HTTP protocol is that the server respond with a message of the form
HTTP/1.1 <code> <reason>
Where <code> is a number and <reason> is a human-readable "status", like "OK" or "Server Error" or something along those lines. The string message obviously does not conform to this requirement.
Here is a simple introduction to how you might build a HTTP server in ruby: https://practicingruby.com/articles/implementing-an-http-file-server

Proxy for Ruby HTTP traffic

I have a ruby script, that posts data to a URL:
require 'httparty'
data = {}
data[:client_id] = '123123'
data[:key] = '123321'
url = "http://someserver.com/endpoint/"
response = HTTParty.post(url, :body => data)
Now i am using Charles for sniffing the HTTP traffic. This works great from the browser, but not from the terminal, where I run my script:
$ ruby MyScript.rb
How can I tell ruby or my Terminal.app to use the Charles proxy at http://localhost:88888
Update Another solution would be to see the request before it is being sent. So that I would not necessarily need the proxy.
Setting the proxy as timmah suggested should work.
Anyway 88888 is not a valid port! I think you want to use 8888 (Charles proxy default port).
So the right commands would be:
export http_proxy=localhost:8888
ruby MyScript.rb
If your script was to use https:// you would also/instead need to specify a HTTPS proxy like so:
export https_proxy=localhost:8888

TCP Minecraft Server in Ruby

I'm attempting to create a script in ruby that connects to a Minecraft server via TCP and fetches the current number of players much like the PHP script at http://www.webmaster-source.com/2012/07/05/checking-the-status-of-a-minecraft-server-with-php/
When running the code below I get �Took too long to log in
require 'socket'
server = TCPSocket.new '192.241.174.210', 25565
while line = server.gets
puts line
end
server.close
What am I doing wrong here?
you're not sending this:
fwrite($sock, "\xfe");
from the script you linked. You have to send that before you call read, like they do.
Basically the server is waiting for you to send data and when you don't after a timeout, you are disconnected.

Resources