I have been working on this program which basically sends an HTML request to the specified server, but each time I run it to send a GET request it responds with a 404 not found page of that site. Can anybody please guide what am I doing wrong out here? I tried copying the Firefox HTML request file and sending that still no use.
import socket
server,port = 'google.com',80
ip = socket.gethostbyname(server)
print (ip)
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((server,port))
request = 'GET /HTTP/1.1\nHost: '+str(ip)+'\n\n'
print(request)
sock.sendall(request.encode())
while True:
data = ' '
data = sock.recv(4096)
if data == ' ':
break
print(data.decode())
And also what are the applications of socket module apart from creating remote servers?
I think your problem is your request. First, you need a space after that first /. Second, for the host, it should be www.google.com, not an IP address.
request = 'GET / HTTP/1.1 \nHost: www.google.com\n\n'
Also, you should change that first line to www.google.com, since it will redirect you there anyway:
server,port = 'www.google.com',80
Related
I have the following code for a simple Server that handles GET requests from the browser over TCP.
while True:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('127.0.0.1', int(args.port)))
print(f'TCP Server listening on port {args.port}...')
s.listen()
connection, addr = s.accept()
print(f'Connected by {addr}')
while True:
data = connection.recv(args.buf)
if not data:
print('Connection closed')
break
message = data.decode()
response = handle_request(message)
connection.sendall(response)
connection.close()
This works somewhat, but not really. When the browser GETs a PNG or html file, that it has cached (if-modified-since), it works seamlessly. However, when it has to serve a new file, the browser (Safari) stalls until I shut down the server but then mysteriously shows the actual file the browser was trying to GET.
I wonder if this has something to do with my implementation of the connection, but I assume that it more likely has to do with my http headers.
This is what my simple headers and response to the browser look like:
header = f"HTTP/1.1 {status}\r\n" \
f"Host: {header_dict['host']}\r\n" \
f"Date: {datetime.today().strftime(time_format)}\r\n" \
f"Last-Modified: {mod_time}\r\n" \
f"Connection: Keep-Alive\r\n" \
f"\r\n".encode()
with open(filename, "rb") as f:
payload = f.read()
response = header + payload
Is there anything important missing from the header for Safari (or any other browser) to work with it? Thanks!
As KompjoeFriek commented, the browser needs to know how much data it is getting from the server. So the content-length header is necessary when handling a get request to serve some data. Without it, it waits until the connection is closed to show the data it has received. Adding a content-length header solved the problem.
So, i am trying to create a simple server on python and trying to access a html file in the same directory through it, but as the output i keep on getting ready to serve...
output
EDIT:
Put an HTML file (e.g., HelloWorld.html) in the same directory that the server is in. Run the server program. Determine the IP address of the host that is running the server (e.g., 128.238.251.26). From another host, open a browser and provide the corresponding URL. For example:
http://128.238.251.26:6789/HelloWorld.html
‘HelloWorld.html’ is the name of the file you placed in the server directory. Note also the use of the port number after the colon. You need to replace this port number with whatever port you have used in the server code. In the above example, we have used the port number 6789. The browser should then display the contents of HelloWorld.html. If you omit ":6789", the browser will assume port 80 and you will get the web page from the server only if your server is listening at port 80.
Then try to get a file that is not present at the server. You should get a “404 Not Found” message.
#import socket module
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepare a sever socket
serverSocket.bind(('', 12006))
serverSocket.listen(1)
while True:
print 'Ready to serve...'
#Establish the connection
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
f.close()
#Send one HTTP header line into socket
connectionSocket.send('HTTP/1.0 200 OK\r\n\r\n')
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
#Send response message for file not found
connectionSocket.send('404 Not Found')
#Close client socket
connectionSocket.close()
serverSocket.close()
Your output is a standart output, that used through print function. you should to make a request to your server and you'll get the correct output
If your server on your local machine, you should use localhost address; if not, you should use your server ip. Also you should to specify a port. 12006 in your case. localhost:12006 as an example
Also socket.send method requires a byte-like object. not string
If it's only a string literal, you should to add a b character before the first quotation mark
Example:
connectionSocket.send(b'HTTP/1.0 200 OK\r\n\r\n')
If it is a string object, you should to encode it:
connectionSocket.send(outputdata[i].encode())
Check out the documentation
So I built a very simple HTTP server in Python. It's purpose is to send a file when it gets a request.
This works in chrome but in Firefox it keeps downloading without making any progress. I also noticed that in Chrome, the name of the downloaded file is download.png where as the actual name of the file is s.png. Could someone tell me what is wrong with this code? Also I tried printing a message and sending html code too in firefox, it just keeps on showing the message "waiting on localhost" and does nothing.
import socket
serversocket = socket.socket()
serversocket.bind(("127.0.0.1", 80))
serversocket.listen(800)
msg = open("s.png", "r").read()
msg = "HTTP/1.0 200 OK\r\nServer: ls\r\nContent-Type: image/png\r\nContent-Disposition: attachement\r\nfilename: s.png\r\n\r\n" + msg + "\r\n\r\n"
while 1:
(clientsocket, address) = serversocket.accept()
clientsocket.send(msg)
Do not insert newline between Content-Disposition and the name of the file.
Using : between filename and the name of the file is also wrong.
I think you shouldn't add useless newlines after the image data.
Using binary mode is good for reading binary files.
You should close the connection after sending the message. Otherwise, the client cannot tell where the end of file is because you didn't send Content-Length header.
It seems good for Firefox to read the request before sending the response.
Try this (tested with Python 3.4.2 and Python 2.7.11):
import socket
serversocket = socket.socket()
serversocket.bind(("127.0.0.1", 80))
serversocket.listen(800)
msg = open("s.png", "rb").read()
msg = "HTTP/1.0 200 OK\r\nServer: ls\r\nContent-Type: image/png\r\nContent-Disposition: attachement; filename=s.png\r\n\r\n".encode('UTF-8') + msg
while True:
(clientsocket, address) = serversocket.accept()
recvdata = ''.encode('UTF-8')
while True:
recvdata += clientsocket.recv(4096)
if "\r\n\r\n".encode('UTF-8') in recvdata:
break
clientsocket.send(msg)
clientsocket.close()
I'm building a proxy server in Python and I got a question.
First I'll be showing you a part of my code that presents the receiving data from the client: If there is data from the client, it downloads the content of the requested website (By using the urllib library) and then sending to the client 200 OK with the content length and the content itself:
data = currentSocket.recv(4096)
if data == "":
open_client_sockets.remove(currentSocket)
print 'Conn is closed'
else:
dataSplit = data.split("\r\n")
Host = HostFliter(dataSplit)
print Host, " Host"
if Host == "":
break
contentURL = urllib.urlopen(Host)
content_to_send = contentURL.read()
currentSocket.send("HTTP/1.1 200 OK\r\nContent-Length:"+str(len(content_to_send))+"\r\n\r\n"+str(content_to_send))
contentURL.close()
**The variable "Host" contains the url of the website.
Now for the question:
Where do I get the headers from the server and then send them to the client?
**The libraries I use: socket, select, urllib.
**This is for the select library:
rlist, wlist, xlist = select.select([serverSocket] + open_client_sockets, open_client_sockets, [])
The HTTP response syntax is as follows
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 38
<html><body>Hello world!</body></html>
So you need to send headers just before \r\n separated by \n in above format.
I am trying to implement a server in Python. When the browser connects to localhost with port number 9999, it will open the file index.html with the images.jpg in that page, but the image can not be shown. How can I make the web server handle the image as well?
Here is my code so far:
from socket import *
import os
serversocket = socket(AF_INET, SOCK_STREAM)
port = 5000
host = '127.0.0.1'
size = os.path.getsize("index.html")
myfile = open('index.html', 'rb')
mycontent = "Welcome to Very Simple Web Server"
size = len(mycontent)
header = "HTTP/1.0 200 OK \r\n Content_Length:" + str(size) + "\r\n\r\n"
mycontent = myfile.read()
serversocket.bind((host, port))
serversocket.listen(5)
print('Server is listening on port 9999')
while (1):
conn, addr = serversocket.accept()
print('Connected by', addr)
conn.send(bytes(header))
conn.send(mycontent)
conn.close()
Your code creates an infinite loop that will just only send one file, and never accepts other connections.
In order for the image to show, the browser has to send another request to the URL of the image, and this request is not being serviced by your code.
In order for your server to work, you need to:
Start a loop
Listen for connections
Interpret the headers of the incoming request, and then act appropriately. Lets assume that you only deal with GET requests and not other things like POST, HEAD, PUT, etc.
Look at the requested resource (the URL)
Find the resource on the file system (so now, you have to parse the URL)
Package the resource into a HTTP response (read the file set the appropriate mime type)
Send the response back to the client with the appropriate headers (the server response headers)
Repeat
To display a HTML page with one image, it takes two requests, one for the HTML page, and another for the image. If the HTML code has a link to a CSS file, now you need three requests - one for the HTML page, one for the CSS file and a final one for the image. All these requests need to be completed successfully in order for the browser to render the page.
You never need to do this by hand, use a web development framework which will take care of all this "boring" stuff so you can then deal with solving the actual problem.