daily pastebin goal
33%
SHARE
TWEET

Untitled

a guest Oct 12th, 2017 48 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. def make_http_request(host, port, resource, file_name):
  2.     """
  3.     Get an HTTP resource from a server
  4.  
  5.     :param bytes host: the ASCII domain name or IP address of the server machine (i.e., host) to connect to
  6.     :param int port: port number to connect to on server host
  7.     :param bytes resource: the ASCII path/name of resource to get. This is everything in the URL after the domain name,
  8.            including the first /.
  9.     :param file_name: string (str) containing name of file in which to store the retrieved resource
  10.     :return: the status code
  11.     :rtype: int
  12.     :author: Noah Mayers
  13.     """
  14.  
  15.     # Open socket, establish connection, and request web resource
  16.     tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  17.     tcp_socket.connect((host, port))
  18.     tcp_socket.sendall(b'GET ' + resource + b' HTTP/1.1\x0d\x0a' + b'Host: ' + host + b'\x0d\x0a\x0d\x0a')
  19.  
  20.     # Obtains length, and receives content based on that length
  21.     response = b''
  22.     length = get_length(tcp_socket)
  23.     for i in range(0, length):
  24.         response += tcp_socket.recv(1)
  25.  
  26.     # Creates file and writes to the file
  27.     file_object = open(file_name, "w+b")
  28.     file_object.write(response)
  29.     file_object.close()
  30.  
  31.     tcp_socket.close()
  32.  
  33.     return response
  34.  
  35.  
  36. def get_length(data_socket):
  37.     """
  38.     Reads length until proper indicator is given
  39.     :return: length of response
  40.     :rtype: int
  41.     :author: Matthew Kouzios
  42.     """
  43.     message = b''
  44.     numCRLF = 0
  45.     CR = b'\x0d'
  46.     data = list()
  47.  
  48.     # Loop through header storing each line in a list until CRLF is found back to back,
  49.     #  as that indicates the end of header
  50.     while numCRLF != 2:
  51.         val = next_byte(data_socket)
  52.         if val == CR:
  53.             numCRLF += 1
  54.             message = message.decode('ASCII')
  55.             data.append(message)
  56.             message = b''
  57.             next_byte(data_socket)  # Clear LF value
  58.         else:
  59.             numCRLF = 0
  60.             message += val
  61.  
  62.     # Loop through list of header lines to find length of header through chunking or Content-Length
  63.     for i in range(len(data)):
  64.         message = data[i]
  65.         message_no_nums = re.sub("\d+", "", message)
  66.         if message_no_nums == 'Content-Length: ':
  67.             message_only_nums = re.sub(r"\D", "", message)
  68.             return int(message_only_nums)
  69.         if message == 'Transfer-Encoding: chunked':
  70.             return get_chunked_length(data_socket) - 2  # \r\n are last 2 bytes, thus subtract 2
  71.  
  72.  
  73. def get_chunked_length(data_socket):
  74.     """
  75.     Reads length of chunked data until proper indicator is given
  76.     :return: length of response
  77.     :rtype: int
  78.     :author: Matthew Kouzios
  79.     """
  80.     find_length = True
  81.     CR = b'\x0d'
  82.     message = b''
  83.  
  84.     # Clear the first two bytes to ensure proper length
  85.     next_byte(data_socket)
  86.     next_byte(data_socket)
  87.  
  88.     # Loop until \r\n is hit, then return the values
  89.     while find_length:
  90.         val = next_byte(data_socket)
  91.         if val == CR:
  92.             length = int.from_bytes(message, 'big')
  93.             return length
  94.         message += val
  95.  
  96.  
  97. def next_byte(data_socket):
  98.     """
  99.     Read the next byte from the socket data_socket.
  100.     The data_socket argument should be an open tcp data connection
  101.     socket (either a client socket or a server data socket).
  102.     It should not be a tcp server's listening socket.
  103.  
  104.     Read the next byte from the server.
  105.     If the byte is not yet available, this method blocks (waits)
  106.       until the byte becomes available.
  107.     If there are no more bytes, this method blocks indefinitely.
  108.  
  109.     :param data_socket: The socket to read from
  110.     :return: the next byte, as a bytes object with a single byte in it
  111.     """
  112.  
  113.     return data_socket.recv(1)
RAW Paste Data
Top