예제 #1
0
파일: tests.py 프로젝트: Firues/proxy.py
 def test_get_full_parse(self):
     raw = text_(CRLF, encoding="utf-8").join([
         "GET %s HTTP/1.1",
         "Host: %s",
         text_(CRLF, encoding="utf-8")
     ])
     self.parser.parse(bytes_(raw % ('https://example.com/path/dir/?a=b&c=d#p=q', 'example.com')))
     self.assertEqual(self.parser.build_url(), b'/path/dir/?a=b&c=d#p=q')
     self.assertEqual(self.parser.method, b"GET")
     self.assertEqual(self.parser.url.hostname, b"example.com")
     self.assertEqual(self.parser.url.port, None)
     self.assertEqual(self.parser.version, b"HTTP/1.1")
     self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
     self.assertDictContainsSubset({b'host': (b'Host', b'example.com')}, self.parser.headers)
     self.assertEqual(bytes_(raw % ('/path/dir/?a=b&c=d#p=q', 'example.com')), self.parser.build(del_headers=[b'host'], add_headers=[(b'Host', b'example.com')]))
예제 #2
0
파일: tests.py 프로젝트: Firues/proxy.py
 def test_post_full_parse(self):
     raw = text_(CRLF).join([
         "POST %s HTTP/1.1",
         "Host: localhost",
         "Content-Length: 7",
         "Content-Type: application/x-www-form-urlencoded" + text_(CRLF, encoding="utf-8"),
         "a=b&c=d"
     ])
     self.parser.parse(bytes_(raw % 'http://localhost'))
     self.assertEqual(self.parser.method, b"POST")
     self.assertEqual(self.parser.url.hostname, b"localhost")
     self.assertEqual(self.parser.url.port, None)
     self.assertEqual(self.parser.version, b"HTTP/1.1")
     self.assertDictContainsSubset({b'content-type': (b'Content-Type', b'application/x-www-form-urlencoded')}, self.parser.headers)
     self.assertDictContainsSubset({b'content-length': (b'Content-Length', b'7')}, self.parser.headers)
     self.assertEqual(self.parser.body, b"a=b&c=d")
     self.assertEqual(self.parser.buffer, b"")
     self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
     self.assertEqual(len(self.parser.build()), len(raw % '/'))
예제 #3
0
 def test_get_full_parse(self):
     raw = text_(CRLF, encoding="utf-8").join(
         ["GET %s HTTP/1.1", "Host: %s",
          text_(CRLF, encoding="utf-8")])
     self.parser.parse(
         bytes_(
             raw %
             ('https://example.com/path/dir/?a=b&c=d#p=q', 'example.com')))
     self.assertEqual(self.parser.build_url(), b'/path/dir/?a=b&c=d#p=q')
     self.assertEqual(self.parser.method, b"GET")
     self.assertEqual(self.parser.url.hostname, b"example.com")
     self.assertEqual(self.parser.url.port, None)
     self.assertEqual(self.parser.version, b"HTTP/1.1")
     self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
     self.assertDictContainsSubset({b'host': (b'Host', b'example.com')},
                                   self.parser.headers)
     self.assertEqual(
         bytes_(raw % ('/path/dir/?a=b&c=d#p=q', 'example.com')),
         self.parser.build(del_headers=[b'host'],
                           add_headers=[(b'Host', b'example.com')]))
예제 #4
0
 def test_post_full_parse(self):
     raw = text_(CRLF).join([
         "POST %s HTTP/1.1", "Host: localhost", "Content-Length: 7",
         "Content-Type: application/x-www-form-urlencoded" +
         text_(CRLF, encoding="utf-8"), "a=b&c=d"
     ])
     self.parser.parse(bytes_(raw % 'http://localhost'))
     self.assertEqual(self.parser.method, b"POST")
     self.assertEqual(self.parser.url.hostname, b"localhost")
     self.assertEqual(self.parser.url.port, None)
     self.assertEqual(self.parser.version, b"HTTP/1.1")
     self.assertDictContainsSubset(
         {
             b'content-type':
             (b'Content-Type', b'application/x-www-form-urlencoded')
         }, self.parser.headers)
     self.assertDictContainsSubset(
         {b'content-length': (b'Content-Length', b'7')},
         self.parser.headers)
     self.assertEqual(self.parser.body, b"a=b&c=d")
     self.assertEqual(self.parser.buffer, b"")
     self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
     self.assertEqual(len(self.parser.build()), len(raw % '/'))
예제 #5
0
class ProposedRestApiPlugin(proxy.HttpProxyBasePlugin):
    """Mock responses for your upstream REST API.

    Used to test and develop client side applications
    without need of an actual upstream REST API server.

    Returns proposed REST API mock responses to the client."""

    API_SERVER = b'api.example.com'

    REST_API_SPEC = {
        b'/v1/users/': {
            'count':
            2,
            'next':
            None,
            'previous':
            None,
            'results': [
                {
                    'email': '*****@*****.**',
                    'groups': [],
                    'url': proxy.text_(API_SERVER) + '/v1/users/1/',
                    'username': '******',
                },
                {
                    'email': '*****@*****.**',
                    'groups': [],
                    'url': proxy.text_(API_SERVER) + '/v1/users/2/',
                    'username': '******',
                },
            ]
        },
    }

    def before_upstream_connection(self) -> bool:
        """Called after client request is received and
        before connecting to upstream server."""
        if self.request.host == self.API_SERVER and self.request.url:
            if self.request.url.path in self.REST_API_SPEC:
                self.client.send(
                    proxy.HttpParser.build_response(
                        200,
                        reason=b'OK',
                        headers={b'Content-Type': b'application/json'},
                        body=proxy.bytes_(
                            json.dumps(
                                self.REST_API_SPEC[self.request.url.path]))))
            else:
                self.client.send(
                    proxy.HttpParser.build_response(404,
                                                    reason=b'NOT FOUND',
                                                    body=b'Not Found'))
            return True
        return False

    def on_upstream_connection(self) -> None:
        pass

    def handle_upstream_response(self, raw: bytes) -> bytes:
        return raw

    def on_upstream_connection_close(self) -> None:
        pass
예제 #6
0
 def on_upstream_connection(self) -> None:
     self.cache_file_path = os.path.join(
         self.CACHE_DIR,
         '%s-%s.txt' % (proxy.text_(self.request.host), str(time.time())))
     self.cache_file = open(self.cache_file_path, "wb")
def test_get_full_parse(self):
raw = text_(CRLF, encoding="utf-8").join([
"GET %s HTTP/1.1",
"Host: %s",
text_(CRLF, encoding="utf-8")
])
self.parser.parse(bytes_(raw % ('https://example.com/path/dir/?a=b&c=d#p=q', 'example.com')))
self.assertEqual(self.parser.build_url(), b'/path/dir/?a=b&c=d#p=q')
self.assertEqual(self.parser.method, b"GET")
self.assertEqual(self.parser.url.hostname, b"example.com")
self.assertEqual(self.parser.url.port, None)
self.assertEqual(self.parser.version, b"HTTP/1.1")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
self.assertDictContainsSubset({b'host': (b'Host', b'example.com')}, self.parser.headers)
self.assertEqual(bytes_(raw % ('/path/dir/?a=b&c=d#p=q', 'example.com')), self.parser.build(del_headers=[b'host'], add_headers=[(b'Host', b'example.com')]))

def test_build_url_none(self):
self.assertEqual(self.parser.build_url(), b'/None')

def test_line_rcvd_to_rcving_headers_state_change(self):
self.parser.parse(b"GET http://localhost HTTP/1.1")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_INITIALIZED)
self.parser.parse(CRLF)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_LINE_RCVD)
self.parser.parse(CRLF)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)

def test_get_partial_parse1(self):
self.parser.parse(CRLF.join([
b"GET http://localhost:8080 HTTP/1.1"
]))
self.assertEqual(self.parser.method, None)
self.assertEqual(self.parser.url, None)
self.assertEqual(self.parser.version, None)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_INITIALIZED)

self.parser.parse(CRLF)
self.assertEqual(self.parser.method, b"GET")
self.assertEqual(self.parser.url.hostname, b"localhost")
self.assertEqual(self.parser.url.port, 8080)
self.assertEqual(self.parser.version, b"HTTP/1.1")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_LINE_RCVD)

self.parser.parse(b"Host: localhost:8080")
self.assertDictEqual(self.parser.headers, dict())
self.assertEqual(self.parser.buffer, b"Host: localhost:8080")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_LINE_RCVD)

self.parser.parse(CRLF*2)
self.assertDictContainsSubset({b'host':(b'Host', b'localhost:8080')}, self.parser.headers)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)

def test_get_partial_parse2(self):
self.parser.parse(CRLF.join([
b"GET http://localhost:8080 HTTP/1.1",
b"Host: "
]))
self.assertEqual(self.parser.method, b"GET")
self.assertEqual(self.parser.url.hostname, b"localhost")
self.assertEqual(self.parser.url.port, 8080)
self.assertEqual(self.parser.version, b"HTTP/1.1")
self.assertEqual(self.parser.buffer, b"Host: ")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_LINE_RCVD)

self.parser.parse(b"localhost:8080" + CRLF)
self.assertDictContainsSubset({b'host': (b'Host', b'localhost:8080')}, self.parser.headers)
self.assertEqual(self.parser.buffer, b"")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)

self.parser.parse(b"Content-Type: text/plain" + CRLF)
self.assertEqual(self.parser.buffer, b"")
self.assertDictContainsSubset({b'content-type': (b'Content-Type', b'text/plain')}, self.parser.headers)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)

self.parser.parse(CRLF)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)

def test_post_full_parse(self):
raw = text_(CRLF).join([
"POST %s HTTP/1.1",
"Host: localhost",
"Content-Length: 7",
"Content-Type: application/x-www-form-urlencoded" + text_(CRLF, encoding="utf-8"),
"a=b&c=d"
])
self.parser.parse(bytes_(raw % 'http://localhost'))
self.assertEqual(self.parser.method, b"POST")
self.assertEqual(self.parser.url.hostname, b"localhost")
self.assertEqual(self.parser.url.port, None)
self.assertEqual(self.parser.version, b"HTTP/1.1")
self.assertDictContainsSubset({b'content-type': (b'Content-Type', b'application/x-www-form-urlencoded')}, self.parser.headers)
self.assertDictContainsSubset({b'content-length': (b'Content-Length', b'7')}, self.parser.headers)
self.assertEqual(self.parser.body, b"a=b&c=d")
self.assertEqual(self.parser.buffer, b"")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
self.assertEqual(len(self.parser.build()), len(raw % '/'))

def test_post_partial_parse(self):
self.parser.parse(CRLF.join([
b"POST http://localhost HTTP/1.1",
b"Host: localhost",
b"Content-Length: 7",
b"Content-Type: application/x-www-form-urlencoded"
]))
self.assertEqual(self.parser.method, b"POST")
self.assertEqual(self.parser.url.hostname, b"localhost")
self.assertEqual(self.parser.url.port, None)
self.assertEqual(self.parser.version, b"HTTP/1.1")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)

self.parser.parse(CRLF)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)

self.parser.parse(CRLF)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_HEADERS_COMPLETE)

self.parser.parse(b"a=b")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_BODY)
self.assertEqual(self.parser.body, b"a=b")
self.assertEqual(self.parser.buffer, b"")

self.parser.parse(b"&c=d")
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)
self.assertEqual(self.parser.body, b"a=b&c=d")
self.assertEqual(self.parser.buffer, b"")

def test_response_parse(self):
self.parser.type = HTTP_RESPONSE_PARSER
self.parser.parse(b''.join([
b'HTTP/1.1 301 Moved Permanently\r\n',
b'Location: http://www.youtube.com/\r\n',
b'Content-Type: text/html; charset=UTF-8\r\n',
b'Date: Wed, 22 May 2013 14:07:29 GMT\r\n',
b'Expires: Fri, 21 Jun 2013 14:07:29 GMT\r\n',
b'Cache-Control: public, max-age=2592000\r\n',
b'Server: gws\r\n',
b'Content-Length: 219\r\n',
b'X-XSS-Protection: 1; mode=block\r\n',
b'X-Frame-Options: SAMEORIGIN\r\n\r\n',
b'<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">\n<TITLE>301 Moved</TITLE></HEAD>',
b'<BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF="http://www.youtube.com/">here</A>.\r\n</BODY></HTML>\r\n'
]))
self.assertEqual(self.parser.code, b'301')
self.assertEqual(self.parser.reason, b'Moved Permanently')
self.assertEqual(self.parser.version, b'HTTP/1.1')
self.assertEqual(self.parser.body, b'<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF="http://www.youtube.com/">here</A>.\r\n</BODY></HTML>\r\n')
self.assertDictContainsSubset({b'content-length': (b'Content-Length', b'219')}, self.parser.headers)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)

def test_response_partial_parse(self):
self.parser.type = HTTP_RESPONSE_PARSER
self.parser.parse(b''.join([
b'HTTP/1.1 301 Moved Permanently\r\n',
b'Location: http://www.youtube.com/\r\n',
b'Content-Type: text/html; charset=UTF-8\r\n',
b'Date: Wed, 22 May 2013 14:07:29 GMT\r\n',
b'Expires: Fri, 21 Jun 2013 14:07:29 GMT\r\n',
b'Cache-Control: public, max-age=2592000\r\n',
b'Server: gws\r\n',
b'Content-Length: 219\r\n',
b'X-XSS-Protection: 1; mode=block\r\n',
b'X-Frame-Options: SAMEORIGIN\r\n'
]))
self.assertDictContainsSubset({b'x-frame-options': (b'X-Frame-Options', b'SAMEORIGIN')}, self.parser.headers)
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_HEADERS)
self.parser.parse(b'\r\n')
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_HEADERS_COMPLETE)
self.parser.parse(b'<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">\n<TITLE>301 Moved</TITLE></HEAD>')
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_RCVING_BODY)
self.parser.parse(b'<BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF="http://www.youtube.com/">here</A>.\r\n</BODY></HTML>\r\n')
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)

def test_chunked_response_parse(self):
self.parser.type = HTTP_RESPONSE_PARSER
self.parser.parse(b''.join([
b'HTTP/1.1 200 OK\r\n',
b'Content-Type: application/json\r\n',
b'Date: Wed, 22 May 2013 15:08:15 GMT\r\n',
b'Server: gunicorn/0.16.1\r\n',
b'transfer-encoding: chunked\r\n',
b'Connection: keep-alive\r\n\r\n',
b'4\r\n',
b'Wiki\r\n',
b'5\r\n',
b'pedia\r\n',
b'E\r\n',
b' in\r\n\r\nchunks.\r\n',
b'0\r\n',
b'\r\n'
]))
self.assertEqual(self.parser.body, b'Wikipedia in\r\n\r\nchunks.')
self.assertEqual(self.parser.state, HTTP_PARSER_STATE_COMPLETE)

class MockConnection(object):
  
def _init_(self, buffer=b''):
self.buffer = buffer
  
def recv(self, bytes=8192):
data = self.buffer[:bytes]
self.buffer = self.buffer[bytes:]
return data
  
def send(self, data):
return len(data)
  
def queue(self, data):
self.buffer += data

class TestProxy(unittest.TestCase):

def setUp(self):
self._conn = MockConnection()
self._addr = ('127.0.0.1', 54382)
self.proxy = Proxy(Client(self._conn, self._addr))

def test_http_get(self):
self.proxy.client.conn.queue(b"GET http://httpbin.org/get HTTP/1.1" + CRLF)
self.proxy._process_request(self.proxy.client.recv())
self.assertNotEqual(self.proxy.request.state, HTTP_PARSER_STATE_COMPLETE)

self.proxy.client.conn.queue(CRLF.join([
b"User-Agent: curl/7.27.0",
b"Host: httpbin.org",
b"Accept: /",
b"Proxy-Connection: Keep-Alive",
CRLF
]))
  
self.proxy._process_request(self.proxy.client.recv())
self.assertEqual(self.proxy.request.state, HTTP_PARSER_STATE_COMPLETE)
self.assertEqual(self.proxy.server.addr, (b"httpbin.org", 80))
  
self.proxy.server.flush()
self.assertEqual(self.proxy.server.buffer_size(), 0)
  
data = self.proxy.server.recv()
while data:
self.proxy._process_response(data)
if self.proxy.response.state == HTTP_PARSER_STATE_COMPLETE:
break
data = self.proxy.server.recv()

self.assertEqual(self.proxy.response.state, HTTP_PARSER_STATE_COMPLETE)
self.assertEqual(int(self.proxy.response.code), 200)

def test_https_get(self):
self.proxy.client.conn.queue(CRLF.join([
b"CONNECT httpbin.org:80 HTTP/1.1",
b"Host: httpbin.org:80",
b"User-Agent: curl/7.27.0",
b"Proxy-Connection: Keep-Alive",
CRLF
]))
self.proxy._process_request(self.proxy.client.recv())
self.assertFalse(self.proxy.server == None)
self.assertEqual(self.proxy.client.buffer, self.proxy.connection_established_pkt)
  
parser = HttpParser(HTTP_RESPONSE_PARSER)
parser.parse(self.proxy.client.buffer)
self.assertEqual(parser.state, HTTP_PARSER_STATE_HEADERS_COMPLETE)
self.assertEqual(int(parser.code), 200)
  
self.proxy.client.flush()
self.assertEqual(self.proxy.client.buffer_size(), 0)
  
self.proxy.client.conn.queue(CRLF.join([
b"GET /user-agent HTTP/1.1",
b"Host: httpbin.org",
b"User-Agent: curl/7.27.0",
CRLF
]))
self.proxy._process_request(self.proxy.client.recv())
self.proxy.server.flush()
self.assertEqual(self.proxy.server.buffer_size(), 0)

parser = HttpParser(HTTP_RESPONSE_PARSER)
data = self.proxy.server.recv()
while data:
parser.parse(data)
if parser.state == HTTP_PARSER_STATE_COMPLETE:
break
data = self.proxy.server.recv()

self.assertEqual(parser.state, HTTP_PARSER_STATE_COMPLETE)
self.assertEqual(int(parser.code), 200)

def test_proxy_connection_failed(self):
with self.assertRaises(ProxyConnectionFailed):
self.proxy._process_request(CRLF.join([
b"GET http://unknown.domain HTTP/1.1",
b"Host: unknown.domain",
CRLF
]))

if _name_ == '_main_':
unittest.main()