0

I coded a Python HTTP server as below and I run the server from the directory which this python file exist. I am typing "python myserver.py" in the cmd and server succesfully starts and reads the index.html in the directory but my problem is after some time my code gives the following error and closes the server

Traceback (most recent call last): File "myserver.py", line 20, in requesting_file = string_list[1] IndexError: list index out of range

How can I fix this problem ?

import socket
HOST,PORT = '127.0.0.1',8082
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
my_socket.bind((HOST,PORT))
my_socket.listen(1)
print('Serving on port ',PORT)
while True:
 connection,address = my_socket.accept()
 request = connection.recv(1024).decode('utf-8')
 string_list = request.split(' ') # Split request from spaces
 print (request)
 method = string_list[0]
 requesting_file = string_list[1]
 print('Client request ',requesting_file)
 myfile = requesting_file.split('?')[0] # After the "?" symbol not relevent here
 myfile = myfile.lstrip('/')
 if(myfile == ''):
 myfile = 'index.html' # Load index file as default
 try:
 file = open(myfile,'rb') # open file , r => read , b => byte format
 response = file.read()
 file.close()
 header = 'HTTP/1.1 200 OK\n'
 if(myfile.endswith(".jpg")):
 mimetype = 'image/jpg'
 elif(myfile.endswith(".css")):
 mimetype = 'text/css'
 else:
 mimetype = 'text/html'
 header += 'Content-Type: '+str(mimetype)+'\n\n'
 except Exception as e:
 header = 'HTTP/1.1 404 Not Found\n\n'
 response = '<html><body><center><h3>Error 404: File not found</h3><p>Python HTTP Server</p></center></body></html>'.encode('utf-8')
 final_response = header.encode('utf-8')
 final_response += response
 connection.send(final_response)
 connection.close()

asked Nov 19, 2017 at 11:43
1
  • Maybe string_list has just one element. Commented Nov 19, 2017 at 11:45

1 Answer 1

1

socket.recv(n) is not guaranteed to read the entire n bytes of the message in one go and can return fewer bytes than requested in some circumstances.

Regarding your code it's possible that only the method, or part thereof, is received without any space character being present in the received data. In that case split() will return a list with one element, not two as you assume.

The solution is to check that a full message has been received. You could do that by looping until sufficient data has been received, e.g. you might ensure that some minimum number of bytes has been received by checking the length of data and looping until the minimum has been reached.

Alternatively you might continue reading until a new line or some other sentinel character is received. It's probably worth capping the length of the incoming data to avoid your server being swamped by data from a rogue client.

Finally, check whether split() returns the two values that you expect and handle accordingly if it does not. Furthermore, be very careful about the file name; what if it contains a relative path, e.g. ../../etc/passwd?

answered Nov 19, 2017 at 12:22
Sign up to request clarification or add additional context in comments.

2 Comments

I solve the problem by adding if not request: # time.sleep(0.01) continue
@erkevarol: that solution will only work if the client closes the connection without sending any data. It is still possible that a truncated message could be received.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.