From f3adef81e3afbde61405ab34e2df3b7f909d34d1 Mon Sep 17 00:00:00 2001 From: John W Kerns Date: Sat, 2 Sep 2017 00:41:24 -0700 Subject: [PATCH] Added HTTP --- checkmyip.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/checkmyip.py b/checkmyip.py index f101d6e..0733293 100644 --- a/checkmyip.py +++ b/checkmyip.py @@ -11,8 +11,6 @@ version = "v1.0.0" - - import os import sys import time @@ -184,6 +182,72 @@ def ssh_talker(client, valdict): #quit() +def http_talker(client, valdict): + def recv_all(sock): + prev_timeout = sock.gettimeout() + try: + sock.settimeout(0.01) + rdata = [] + while True: + try: + rdata.append(sock.recv(MAX_PACKET)) + except socket.timeout: + return ''.join(rdata) + finally: + sock.settimeout(prev_timeout) + def normalize_line_endings(s): + return ''.join((line + '\n') for line in s.splitlines()) + while True: + # headers and body are divided with \n\n (or \r\n\r\n - that's why we + # normalize endings). In real application usage, you should handle + # all variations of line endings not to screw request body + request = normalize_line_endings(recv_all(client)) # hack again + request_head, request_body = request.split('\n\n', 1) + # first line is request headline, and others are headers + request_head = request_head.splitlines() + request_headline = request_head[0] + # headers have their name up to first ': '. In real world uses, they + # could duplicate, and dict drops duplicates by default, so + # be aware of this. + request_headers = dict(x.split(': ', 1) for x in request_head[1:]) + # headline has form of "POST /can/i/haz/requests HTTP/1.0" + request_method, request_uri, request_proto = request_headline.split(' ', 3) + response_body = [ + '

Hello, world!

', + '

This page is in location %(request_uri)r, was requested ' % locals(), + 'using %(request_method)r, and with %(request_proto)r.

' % locals(), + '

Request body is %(request_body)r

' % locals(), + '

Actual set of headers received:

', + '') + response_body_raw = ''.join(response_body) + # Clearly state that connection will be closed after this response, + # and specify length of response body + response_headers = { + 'Content-Type': 'text/html; encoding=utf8', + 'Content-Length': len(response_body_raw), + 'Connection': 'close', + } + response_headers_raw = ''.join('%s: %s\n' % (k, v) for k, v in \ + response_headers.iteritems()) + # Reply as HTTP/1.1 server, saying "HTTP OK" (code 200). + response_proto = 'HTTP/1.1' + response_status = '200' + response_status_text = 'OK' # this can be random + # sending all this stuff + client.send('%s %s %s' % (response_proto, response_status, \ + response_status_text)) + client.send(response_headers_raw) + client.send('\n') # to separate headers from body + client.send(response_body_raw) + # and closing connection, as we stated before + client.close() + + def start(): talkers = {22: ssh_talker, 23: telnet_talker, 80: telnet_talker} for talker in talkers: