Python web server - IndexError when splitting filename - python

I have successfully been able to access my web-server from a browser, downloaded a file on the server and properly viewed it with chrome. However, when the server standbys for approx. 20 seconds, it'll crash with an IndexError.
from socket import *
serverport = 972
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverport))
serverSocket.listen(1)
print 'Standing by...'
while True:
#Establish the connection
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
print 'Success! File sent!'
connectionSocket.close()
except IOError:
errormessage = 'Error 404 - File not found'
connectionSocket.send(errormessage)
The output i get is the following:
Standing by..
Success! File sent! #sent everytime i request the webpage on the client localhost:80/helloworld.html
Traceback (most recent call last):
File "C:/Users/Nikolai/Dropbox/NTNU/KTN/WebServer/TCPServer.py", line 14, in <module>
filename = message.split()[1]
IndexError: list index out of range

This is probably the client closing the connection. When the connection is finished, an empty string '' is received.
''.split()[1] will fail with index out of range. My advice is to try with this patch:
message = connectionSocket.recv(1024)
if not message:
# do something like return o continue
As an aside, you should recv from your socket until you get the empty string. In your code, what happens if the request is larger than 1024? Something like this can be done:
try:
message = ''
rec = connectionSocket.recv(1024)
while rec:
rec = connectionSocket.recv(1024)
message += rec
if not message:
connectionSocket.close()
continue
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
print 'Success! File sent!'
connectionSocket.close()
You should read Socket Programming HOWTO, specially the part of creating multithreaded servers, which is probably how you want to do yours :)
Hope this helps!

Related

Trying to use a Pycharm generated socket to pull the contents of an HTML file in the same directory

So essentially, I have an HTML file in the same directory as my .py file, which contains the following code:
import sys
from socket import *
serverPort = 12500
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
while True:
print('The server is ready to receive')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024).decode()
filename = message.split()[1]
print(filename)
temp = open(filename[1:])
outputdata = temp.readlines()
print(outputdata)
connectionSocket.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='UTF-8'))
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
except IOError:
connectionSocket.send(bytes('HTTP/1.1 404 NOT FOUND\r\n\r\n', encoding="UTF-8"))
connectionSocket.close()
serverSocket.close()
sys.exit()
My goal for this server is that it displays the content of the HTML file when I reference it in a web browser, and gives a 404 error when a non-existent file is found.
An example input would be:
http://127.0.0.1:12500/Hello.html
This would yield this output with my current code:
The server is ready to receive
/Hello.html
So it is just reading the /Hello.html portion instead of the file. Is there a way to remedy this? Thank you!

Unable to split a tuple object in Python: 'tuple' object has no attribute 'split'

When I try to run my program I get the error shown below:
Traceback (most recent call last):
File "/Volumes/USER/server.py", line 15, in <module>
filename = message.split()[1]
AttributeError: 'tuple' object has no attribute 'split'
I tried changing the value for
filename = message.split()[0] but it didn't work.
#import socket module
import socket
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Prepare a sever socket
serverName = socket.gethostname()
serverPort = 1234
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
while True:
#Establish the connection
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recvfrom(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#Send one HTTP header line into socket
header = 'HTTP/1.1 200 OK\r\n' +\
'Connection: close\r\n' + \
'Content-Type: text/html\r\n' + \
'Content-Length: %d\r\n\r\n' % (len(outputdata))
connectionSocket.send(header.encode())
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.close()
except IOError:
#Send response message for file not found
header = 'HTTP/1.1 404 Not Found\r\n\r\n'
connectionSocket.send(header.encode())
#Close client socket
connectionSocket.close()
serverSocket.close()
In the same directory as the program, server.py, I have a file called helloworld.html thats supposed to load when I go to the IP address of the server with the hard coded port and also show a 404 when I go to a file that doesn't exist. ex (192.168.1.2:1234/helloworld.html)
Per the documentation:
socket.accept()
Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.
So, in your code, after you do
message = connectionSocket.recvfrom(1024)
filename = message.split()
message becomes a tuple (conn, address).
Now, tuples don't have the method split(). Only strings have that method. What I think you're trying to do is split the address - so you have to first get the second element of the tuple (which is, of course, a string), and then split that:
filename = message[1].split()

List index out of range preventing 404 error?

I'm trying to complete this lab but cannot seem to get it to work correctly. When I try to get a file not present of the server, I am given
This page isn’t working
127.0.0.1 sent an invalid response.
ERR_INVALID_HTTP_RESPONSE
The response I'd like to get is along the lines of
404 File not found
When I try to load a file not present, the compiler says for line 16:
filename = message.split()[1]
IndexError: list index out of range
The code compiles and I am able to open my Hello World file, but I am just not able to get this 404 error. I was given a skeleton code, so there are some things that I cannot change without deviating from course material.
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepare a server socket
serverPort = 7000
serverSocket.bind(('127.0.0.1', serverPort))
serverSocket.listen(5)
while True:
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
#Fill in start #Fill in end
try:
message = connectionSocket.recv(1024)
print (message)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#Send one HTTP header line into socket
#Fill in start
connectionSocket.send('\nHTTP/1.x 200 OK\n'.encode())
#Fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
print ('File Recieved')
except IOError:
connectionSocket.send('\n404 File Not Found\n'.encode())
connectionSocket.close()
#Close client socket
serverSocket.close()
sys.exit()
The skeleton code appears to be Python 2, and I'm using Python 3. I've made some minor syntax adjustments to adjust.
Removing print(message) yields "File Recieved" in the compiler, but still no 404 error in the browser. I'm at loss after 8 hours.
One way to handle an IndexError in message.split()[1] is to handle and IndexError in message.split()[1] ;)
try:
filename = message.split()[1]
except IndexError:
send_404_response()
continue

Python Socket Programming - Bad file descriptor error

I'm trying to create a simple server, and keep getting the following error in IDLE:
File "C:\Python27\lib\socket.py", line 202, in accept
sock, addr = self._sock.accept()
File "C:\Python27\lib\socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
This is my code. I've tried understanding why, and it has something to do with closing one of the sockets and then trying to use it again but I don't really get how I'm supposed to fix it. Any and all help is appreciated. :)
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
port=10101
serverSocket.bind(('',port))
serverSocket.listen(5)
while True:
print 'Ready to serve...'
connectionSocket, addr = serverSocket.accept()
try:
message = serverSocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
connectionSocket.send("HTTP/1.1 200 OK\r\n\n")
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
connectionSocket.send('HTTP/1.1 404 File not found\r\n\n')
connectionSocket.close()
serverSocket.close()
serverSocket.close()
A couple of things:
As user27994550 put in his code, you want to use
message = connectionSocket.recv(1024)
to receive messages, not the server socket.
The other thing that both of your codes missed is you don't want to call
serverSocket.close()
in your except function unless you're closing the program overall. If you close the server socket, the next time you call
connectionSocket, addr = serverSocket.accept()
you won't be able to accept another connection. Hope this helps!
You are trying to use the "message" variable data without checking if its empty.
I think this might be the problem.
Try this:
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
port=10101
serverSocket.bind(('localhost',port))
serverSocket.listen(5)
while True:
print('Ready to server')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
if message != "": #Checking if empty
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
connectionSocket.send("HTTP/1.1 200 OK\r\n\n")
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i])
connectionSocket.close()
except IOError:
connectionSocket.send('HTTP/1.1 404 File not found\r\n\n')
connectionSocket.close()
serverSocket.close()

Python WebServer breaks with .send message?

Inserting a .send to send an OK message apparently makes the rest of the code not work?
If I remove the client.send messages from the following code, it works. But with it, nothing happens in the browser, checking in Firefox, it says that the request went through, but there isn't any page displayed... it's just blank. Why would .send messages cause nothing to happen?
from socket import *
server = socket(AF_INET, SOCK_STREAM)
port = 12030
server.bind((gethostname(), port))
server.listen(1)
while True:
print 'Ready to serve'
conection, addr = server.accept()
try:
print 'Working'
message = conection.recv(1024)
conection.send("HTTP/1.0 200 OK\r\n")
conection.send("Content-Type:text/html\r\n")
filename = message.split()[1]
print "FILENAME", filename
f = open(filename[1:]) #cuts off the '/' in the request page
outputdata = f.read()
print "OUTDATA: ", outputdata
for i in range(0, len(outputdata)):
conection.send(outputdata[i])
conection.close()
except IOError:
print 'IO ERROR'
conection.send("404 NOT FOUND")
print message
conection.close()
except KeyboardInterrupt:
server.close()
conection.close()
break;
As seen here, it doesn't affect the data stream at all..
user ##$$ python webServer.py
Ready to serve
Working
FILENAME /HelloWorld.html
OUTDATA: <html>Hello World</html>
Ready to serve

Categories