Python Proxy не обрабатывает POST-запросы - PullRequest
2 голосов
/ 29 октября 2011

Я создаю простой прокси Python, который регистрирует все запросы, отправленные через него.На данный момент все работает , за исключением запросов POST (я не могу голосовать по вопросам StackOverflow).

Я не определил явную функцию POST, но вместо этого я использую функцию GET.

Может кто-нибудь сказать мне, где проблема?

Это мой код:

#!/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:

  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()

1 Ответ

1 голос
/ 29 октября 2011

Выбор чтения на self.connection никогда не возвращается, и если кто-то читает с этого объекта вручную, данные не поступают. Похоже, вы должны читать из self.rfile.

Обратите внимание, что вызов select на self.rfile не возвращается, но self.rfile.read() работает. Вероятно, это связано с тем, что self.rfile является объектоподобным объектом Python, а процесс сервера уже прочитал начало тела POST из ОС.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...