Python 代理不处理 POST 请求 [英] Python Proxy isn't handling POST requests

查看:66
本文介绍了Python 代理不处理 POST 请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个简单的 Python 代理,用于记录通过它发送的所有请求.目前,一切正常除了 POST 请求(我无法对 StackOverflow 问题进行投票).

I'm creating a simple Python proxy that logs all requests sent through it. For now, everything works except POST requests (I can't vote on StackOverflow questions).

我没有定义显式的 POST 函数,但我使用的是 GET 函数.

I haven't defined an explicit POST function, but I am using the GET function instead.

谁能告诉我问题出在哪里?

Could anyone tell me where the problem is?

这是我的代码:

#!/usr/local/bin/python2

import BaseHTTPServer, select, socket, SocketServer, urlparse

class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  def __init__(self, request, client_address, server):
      self.request = request
      self.client_address = client_address
      self.server = server
      self.setup()

      self.socket = socket

      self.server_version = 'TestProxy 1.0'
      self.request_buffer_size = 0

      try:
        self.handle()
      finally:
        self.finish()

  def connect_to(self, location, destination_socket):
    i = location.find(':')

    if i >= 0:
      host = location[:i]
      port = int(location[i + 1:])
    else:
      host = location
      port = 80

    print 'Connecting to {0}:{1}'.format(host, port)

    try:
      self.socket.connect((host, port))
    except socket.error, arg:
      try:
        msg = arg[1]
      except:
        msg = arg

      self.send_error(404, msg)

      return 0
    return 1

  def do_CONNECT(self):
    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
      if self.connect_to(self.path, socket):
        self.log_request(200)
        self.wfile.write(self.protocol_version + ' 200 Connection established\n')
        self.wfile.write('Proxy-agent: {0}\n'.format(self.version_string()))
        self.wfile.write('\n')

        self.read_write(self.socket, 300)
    finally:
      print 'Connection closed.'
      self.socket.close()
      self.connection.close()

  def do_GET(self):
    scm, location, path, parameters, query, fragment = urlparse.urlparse(self.path, 'http')

    if scm != 'http' or fragment or not location:
      self.send_error(400, 'bad url {0}'.format(self.path))
      return

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
      if self.connect_to(location, self.socket):
        self.log_request()
        self.socket.send('{0} {1} {2}\n'.format(self.command, urlparse.urlunparse(('', '', path, parameters, query, '')), self.request_version))
        self.headers['Connection'] = 'close'

        del self.headers['Proxy-Connection']

        for key, value in self.headers.items():
          self.socket.send('{0}: {1}\n'.format(key, value))

        self.socket.send('\n')
        self.read_write(self.socket)
    finally:
      print 'Closing connection...'

      self.socket.close()
      self.connection.close()

  def read_write(self, socket, max_idling = 100):
    iw = [self.connection, socket]
    ow = []
    count = 0

    while count != max_idling:
      count += 1
      read_list, write_list, exception_list = select.select(iw, ow, iw, 3)

      if exception_list:
        break

      if read_list:
        for item in read_list:
          out = self.connection if item is socket else socket
          data = item.recv(8192)

          if data:
            out.send(data)
            count = 0
      else:
        pass
        #print 'Idle for {0}'.format(count)

  do_HEAD   = do_GET
  do_POST   = do_GET
  do_PUT    = do_GET
  do_DELETE = do_GET

class ThreadingHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): pass

if __name__ == '__main__':
  BaseHTTPServer.test(ProxyHandler, ThreadingHTTPServer)

这部分处理 POST/GET 请求:

This part handles the POST/GET requests:

  def do_GET(self):
    scm, location, path, parameters, query, fragment = urlparse.urlparse(self.path, 'http')

    if scm != 'http' or fragment or not location:
      self.send_error(400, 'bad url {0}'.format(self.path))
      return

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
      if self.connect_to(location, self.socket):
        self.log_request()
        self.socket.send('{0} {1} {2}\n'.format(self.command, urlparse.urlunparse(('', '', path, parameters, query, '')), self.request_version))
        self.headers['Connection'] = 'close'

        del self.headers['Proxy-Connection']

        for key, value in self.headers.items():
          self.socket.send('{0}: {1}\n'.format(key, value))

        self.socket.send('\n')
        self.read_write(self.socket)
    finally:
      print 'Closing connection...'

      self.socket.close()
      self.connection.close()

推荐答案

self.connection 上的读取选择永远不会返回,如果手动从该对象读取,则不会有数据到来.看起来你必须从 self.rfile 读取.

The read-select on self.connection never returns, and if one manually reads from that object, no data is coming. It looks like you have to read from self.rfile.

注意在 self.rfile 上调用 select 不会返回,但是 self.rfile.read()确实有效.这可能是因为 self.rfile 是一个类似 Python 文件的对象,并且服务器进程已经从操作系统读取了 POST 正文的开头.

Note that calling select on self.rfile doesn't return, but self.rfile.read() does work. That is probably because self.rfile is a Python file-like object, and the server process has already read the start of the POST body from the OS.

这篇关于Python 代理不处理 POST 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆