Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

Commit

Permalink
iss #24: [tmp] proxied response (in progress...)
Browse files Browse the repository at this point in the history
  • Loading branch information
maizy committed Nov 17, 2014
1 parent 5e60049 commit 1788fcb
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 9 deletions.
27 changes: 27 additions & 0 deletions examples/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,33 @@
"delay": 15, // seconds
"response": "so long",
"code": 503
},

//proxy some requests to upstream
{
"path_regexp": "^/proxy/(.*)",
"response_proxy": "http://example.com/path/$1"
},

//proxy request with some delay
{
"path_regexp": "^/slow_proxy/(.*)/(.*)$",
"response_proxy": "http://example.com/otherpath/$1/$2",
"delay": 10 //seconds
},

//proxy with some response headers replaced to config defined
{
"path_regexp": "^/fixed_proxy/(.*)/(.*)$",
"response_proxy": "http://example.com/otherpath/$1/$2",
"headers": {
"Server": "MyServer/0.1"
}
},
{
"path_regexp": "^/fixed_proxy2/(.*)$",
"response_proxy": "http://example.com/otherpath/$1",
"headers_file": "page1.headers"
}
]
}
70 changes: 61 additions & 9 deletions zaglushka.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import httplib
import time
from copy import deepcopy
from os import path
from collections import namedtuple

Expand All @@ -14,6 +15,7 @@
from tornado.options import define, options
from tornado.httpserver import HTTPServer
from tornado.httputil import HTTPHeaders
from tornado.httpclient import AsyncHTTPClient, HTTPRequest

logger = logging.getLogger('zaglushka')

Expand Down Expand Up @@ -67,14 +69,7 @@ def __init__(self, raw_config, config_full_path):
rules.append(Rule(matcher, responder))
else:
logger.warn('Unable to build matcher from url spec #{}, skipping'.format(num))
default_response = static_response(
body='',
headers_func=build_static_headers_func({
'X-Zaglushka-Default-Response': 'true',
}),
code=httplib.NOT_FOUND
)
rules.append(Rule(always_match, default_response))
rules.append(Rule(always_match, default_response()))
self.rules = rules
self.stubs_base_path = stubs_base_path

Expand Down Expand Up @@ -183,6 +178,16 @@ def _body_func(handler, ready_cb):
**stub_kwargs)


def default_response():
return static_response(
body='',
headers_func=build_static_headers_func({
'X-Zaglushka-Default-Response': 'true',
}),
code=httplib.NOT_FOUND
)


def filebased_response(full_path, headers_func, warn_func=None, **stub_kwargs):

def _body_func(handler, ready_cb):
Expand All @@ -200,6 +205,51 @@ def _body_func(handler, ready_cb):
**stub_kwargs)


def proxied_response(url_pattern, proxy_url, headers_func, warn_func=None, **stub_kwargs):

try:
url_regexp = re.compile(url_pattern)
except re.error as e:
if warn_func is not None:
warn_func('Unable to compile url pattern "{}": {}'.format(url_pattern, e))
return default_response()

def _body_func(handler, ready_cb):
match = url_regexp.search(handler.request.uri)
if match is None:
handler.set_header('X-Zaglushka-Failed-Response', 'true')
return ready_cb()
url = proxy_url
for i, group in enumerate(match.groups()):
url = url.replace('${}'.format(i), group)
http_client = handler.application.settings['http_client']
request = HTTPRequest(url, method=handler.request.method, headers=handler.request.headers,
body=handler.request.body, follow_redirects=False)

def _on_proxied_request_ready(response):
# TODO: delay ? what about - нужно не сложить а смержить
# TODO: 599 response ?
if response.code == 599: # special tornado status code
pass
headers_before = deepcopy(handler.headers)
handler.write(response.body)
for header, value in response.headers.iteritems():
handler.add_header(header, value)
# replace with headers from config if any
for header, _ in headers_before.get_all():
handler.clear_header(header)
for value in headers_before.get_list(header):
handler.add_header(header, value)
handler.set_status(response.code)
ready_cb()

http_client.fetch(request, callback=_on_proxied_request_ready)

return ResponseStub(headers_func=headers_func,
body_func=_body_func,
**stub_kwargs)


def choose_headers_func(spec, base_stubs_path):
paths = set()
if 'headers' in spec:
Expand Down Expand Up @@ -386,10 +436,12 @@ def compute_etag(self):


def build_app(zaglushka_config, debug=False):
http_client = AsyncHTTPClient()
return Application(
handlers=[(r'.*', StubHandler)],
debug=debug,
zaglushka_config=zaglushka_config
zaglushka_config=zaglushka_config,
http_client=http_client
)


Expand Down

0 comments on commit 1788fcb

Please sign in to comment.