用Python | Set 2创建代理Web服务器

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

null

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

  • 添加域黑名单 .比如谷歌。com,facebook。通用域名格式。在我们的配置目录中创建一个黑名单域列表。现在,只需忽略/删除黑名单域收到的请求。(理想情况下,我们必须做出禁止的回应。)
      # Check if the host:port is blacklistedfor i in range(0, len(config['BLACKLIST_DOMAINS'])):    if config['BLACKLIST_DOMAINS'][i] in url:        conn.close()return
  • 要添加主机阻止,请执行以下操作: 例如,您可能需要允许来自特定子网的连接或特定人员的连接。要添加此项,请创建一个包含所有允许主机的列表。因为主机也可以是子网,所以添加regex以匹配IP地址,特别是IPV4地址。 IPv4地址通常用点十进制表示法表示,它由四个十进制数字组成,每个数字的范围从0到255,用点分隔,例如172.16.254.1。每个部分代表地址的一组8位(八位字节)
  • 使用正则表达式匹配正确的IP地址:
    • 创建一个新方法,并使用fnmatch模块匹配正则表达式。遍历所有正则表达式,如果与其中任何一个匹配,则允许请求。如果未发现客户端地址是任何正则表达式的一部分,则发送禁止响应。现在,再次跳过这个响应创建部分。

注意:在接下来的教程中,我们将创建一个完整的自定义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',)
  • 创建一个单独的方法来记录每条消息 :将其作为参数传递,并使用线程名称和当前时间等附加数据来跟踪日志。另外,创建一个函数,对日志进行着色,使其在标准输出上看起来漂亮。 要实现这一点,请在配置中添加一个布尔值,即着色的日志记录,并创建一个新函数,根据日志级别将传递给它的每个消息着色。
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: PYIT维护一个包含颜色代码的类。将其分离到另一个模块中,以使代码模块化并遵循PEP8标准。
# ColorizePython.pyclass pycolors:HEADER = ' 33[95m'OKBLUE = ' 33[94m'OKGREEN = ' 33[92m'WARNING = ' 33[93m'FAIL = ' 33[91m'ENDC = ' 33[0m' # End colorBOLD = ' 33[1m'UNDERLINE = ' 33[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存储了所有使代码更容易理解的实用程序,并将此方法放在那里。 在需要时添加适当的日志消息,尤其是在 这个 服务器更改。
  • 修改服务器中的shutdown方法,以便在退出应用程序之前退出所有正在运行的线程。 穿线。列举 迭代所有正在运行的线程,因此我们不需要维护它们的列表。当我们试图结束主线程时,线程模块的行为是意外的。官方文件还指出:

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

因此,适当地跳过它。这是同样的代码。

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)

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

关于作者:

平克什·巴贾提亚 来自印度海得拉巴。 他本质上是个极客,有很多值得寻找的项目。他的项目工作可见一斑 在这里

如果你也想在这里展示你的博客,请参见 吉微博 在Geeksforgek上写客博。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享