用Python创建代理Web服务器S2

2021年5月12日21:29:49 发表评论 930 次浏览

先决条件:在Python中创建代理Web服务器– Set1

在本教程中, 添加了一些有趣的功能以使其更有用。

  • 将网域加入黑名单。对于前google.com, facebook.com。在我们的配置字典中创建BLACKLIST_DOMAINS的列表。现在, 只需忽略/删除收到的列入黑名单的域的请求即可。 (理想情况下, 我们必须以禁止的回应来回应。)
          
    # Check if the host:port is blacklisted
    for i in range(0, len(config['BLACKLIST_DOMAINS'])):
        if config['BLACKLIST_DOMAINS'][i] in url:
            conn.close()
    return
    
  • 要添加主机阻止:假设你可能需要允许来自特定子网的连接或特定人的连接。要添加此内容, 请创建所有允许的主机的列表。由于主机也可以是子网, 因此添加正则表达式以匹配IP地址, 尤其是IPV4地址。" IPv4地址以点十进制表示法规范地表示, 它由四个十进制数字组成, 每个数字的范围从0到255, 由点分隔, 例如172.16.254.1。每个部分代表地址的一组8位(八位字节)。"
  • 使用正则表达式匹配正确的IP地址:
    • 在Server类中创建一个新方法_ishostAllowed, 并使用fnmatch模块来匹配正则表达式。遍历所有正则表达式, 如果匹配任何正则表达式则允许请求。如果没有发现客户地址是任何正则表达式的一部分, 则发送一个FORBIDDEN响应。再次, 现在跳过此响应创建部分。

注意:在接下来的教程中, 我们将创建完整的自定义Web服务器, 在那里将创建createResponse函数来处理通用响应的创建。

def _ishostAllowed(self, host):

    """ Check if host is allowed to access
        the content """
    for wildcard in config['HOST_ALLOWED']:
        if fnmatch.fnmatch(host, wildcard):
            return True
    return False

默认主机匹配正则表达式为" *", 以匹配所有主机。不过, 也可以使用" 192.168。*"形式的正则表达式。服务器当前正在处理请求, 但不显示任何消息, 因此我们不知道服务器的状态。其消息应登录到控制台。为此, 请使用日志记录模块, 因为它是线程安全的。 (如果你记得, 服务器是多线程的。)

导入模块并设置其初始配置。

logging.basicConfig(level = logging.DEBUG, format = '[%(CurrentTime)-10s] (%(ThreadName)-10s) %(message)s', )
  • 创建一个单独的方法来记录每条消息:将其作为参数传递, 并带有其他数据, 例如线程名和当前时间, 以跟踪日志。还创建一个使日志着色的函数, 以便在STDOUT上看起来漂亮。
    为此, 在配置中添加一个布尔值COLORED_LOGGING并创建一个新函数, 该函数根据LOG_LEVEL为传递给它的每个味精着色。
def log(self, log_level, client, msg):

    """ Log the messages to appropriate place """
    LoggerDict = {
       'CurrentTime' : strftime("%a, %d %b %Y %X", localtime()), 'ThreadName' : threading.currentThread().getName()
    }
    if client == -1: # Main Thread
        formatedMSG = msg
    else: # Child threads or Request Threads
        formatedMSG = '{0}:{1} {2}'.format(client[0], client[1], msg)
    logging.debug('%s', utils.colorizeLog(config['COLORED_LOGGING'], log_level, formatedMSG), extra=LoggerDict)
  • 创建一个新模块ColorizePython.py:它包含一个pycolors类, 该类维护一个颜色代码列表。将其分成另一个模块, 以使代码模块化并遵循PEP8标准。
# ColorizePython.py
class pycolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m' # End color
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

模块:

import ColorizePython

方法:

def colorizeLog(shouldColorize, log_level, msg):
    ## Higher is the log_level in the log()
    ## argument, the lower is its priority.
    colorize_log = {
    "NORMAL": ColorizePython.pycolors.ENDC, "WARNING": ColorizePython.pycolors.WARNING, "SUCCESS": ColorizePython.pycolors.OKGREEN, "FAIL": ColorizePython.pycolors.FAIL, "RESET": ColorizePython.pycolors.ENDC
    }

    if shouldColorize.lower() == "true":
        if log_level in colorize_log:
            return colorize_log[str(log_level)] + msg + colorize_log['RESET']
        return colorize_log["NORMAL"] + msg + colorize_log["RESET"]
    return msg
  • 由于colorizeLog不是服务器类的函数, 因此将其创建为名为utils.py的单独模块, 该模块存储使代码更易于理解的所有实用程序并将此方法放在此处。在任何需要的地方添加适当的日志消息, 尤其是在服务器状态更改时。
  • 在退出应用程序之前, 修改服务器中的关闭方法以退出所有正在运行的线程。threading.enumerate()迭代所有正在运行的线程, 因此我们不需要维护它们的列表。当我们尝试结束main_thread时, 线程模块的行为是意外的。官方文档还指出:

如果试图加入当前线程, join()会引发RuntimeError, 因为这将导致死锁。在线程启动之前加入()线程也是错误的, 尝试这样做会引发相同的异常。"

因此, 请适当跳过它。这是相同的代码。

def shutdown(self, signum, frame):
    """ Handle the exiting server. Clean all traces """
    self.log("WARNING", -1, 'Shutting down gracefully...')
    main_thread = threading.currentThread() # Wait for all clients to exit
    for t in threading.enumerate():
        if t is main_thread:
            continue
            self.log("FAIL", -1, 'joining ' + t.getName())
        t.join()
        self.serverSocket.close()
    sys.exit(0)

如果你有任何意见/建议/疑问, 请随时提问。 🙂

关于作者:

Pinkesh Badjatiya来自海得拉巴(IIIT)海德拉巴。可见他的项目工作这里。

如果你还希望在此处展示你的博客, 请参阅日志用于在lsbin上撰写访客博客。

首先, 你的面试准备可通过以下方式增强你的数据结构概念:Python DS课程。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: