Statistics
| Branch: | Tag: | Revision:

root / snf-django-lib / snf_django / lib / api / proxy / __init__.py @ 142133fb

History | View | Annotate | Download (3.3 kB)

1 33c84784 Sofia Papagiannaki
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2 33c84784 Sofia Papagiannaki
#
3 33c84784 Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 33c84784 Sofia Papagiannaki
# without modification, are permitted provided that the following
5 33c84784 Sofia Papagiannaki
# conditions are met:
6 33c84784 Sofia Papagiannaki
#
7 33c84784 Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 33c84784 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 33c84784 Sofia Papagiannaki
#      disclaimer.
10 33c84784 Sofia Papagiannaki
#
11 33c84784 Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 33c84784 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 33c84784 Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 33c84784 Sofia Papagiannaki
#      provided with the distribution.
15 33c84784 Sofia Papagiannaki
#
16 33c84784 Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 33c84784 Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 33c84784 Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 33c84784 Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 33c84784 Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 33c84784 Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 33c84784 Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 33c84784 Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 33c84784 Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 33c84784 Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 33c84784 Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 33c84784 Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 33c84784 Sofia Papagiannaki
#
29 33c84784 Sofia Papagiannaki
# The views and conclusions contained in the software and
30 33c84784 Sofia Papagiannaki
# documentation are those of the authors and should not be
31 33c84784 Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 33c84784 Sofia Papagiannaki
# or implied, of GRNET S.A.
33 33c84784 Sofia Papagiannaki
34 33c84784 Sofia Papagiannaki
from django.http import HttpResponse
35 33c84784 Sofia Papagiannaki
36 fed0b230 Christos Stavrakakis
from objpool.http import PooledHTTPConnection
37 33c84784 Sofia Papagiannaki
38 33c84784 Sofia Papagiannaki
from .utils import fix_header, forward_header
39 33c84784 Sofia Papagiannaki
40 33c84784 Sofia Papagiannaki
import urllib
41 33c84784 Sofia Papagiannaki
import urlparse
42 33c84784 Sofia Papagiannaki
43 142133fb Kostas Papadimitriou
# We use proxy to delegate requests to another domain. Sending host specific
44 142133fb Kostas Papadimitriou
# headers (Host, Cookie) may cause confusion to the server we proxy to.
45 142133fb Kostas Papadimitriou
#
46 142133fb Kostas Papadimitriou
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
47 142133fb Kostas Papadimitriou
# Connection and MUST NOT be communicated by proxies over further connections
48 142133fb Kostas Papadimitriou
EXCLUDE_HEADERS = ['Host', 'Cookie', 'Connection']
49 142133fb Kostas Papadimitriou
50 33c84784 Sofia Papagiannaki
51 33c84784 Sofia Papagiannaki
def proxy(request, target):
52 33c84784 Sofia Papagiannaki
    kwargs = {}
53 33c84784 Sofia Papagiannaki
54 33c84784 Sofia Papagiannaki
    # prepare headers
55 33c84784 Sofia Papagiannaki
    headers = dict(map(lambda (k, v): fix_header(k, v),
56 33c84784 Sofia Papagiannaki
                   filter(lambda (k, v): forward_header(k),
57 33c84784 Sofia Papagiannaki
                          request.META.iteritems())))
58 33c84784 Sofia Papagiannaki
59 142133fb Kostas Papadimitriou
    # set X-Forwarded-For, if already set, pass it through, otherwise set it
60 142133fb Kostas Papadimitriou
    # to the current request remote address
61 142133fb Kostas Papadimitriou
    SOURCE_IP = request.META.get('REMOTE_ADDR', None)
62 142133fb Kostas Papadimitriou
    if SOURCE_IP and not 'X-Forwarded-For' in headers:
63 142133fb Kostas Papadimitriou
        headers['X-Forwarded-For'] = SOURCE_IP
64 142133fb Kostas Papadimitriou
65 142133fb Kostas Papadimitriou
    # request.META remains cleanup
66 142133fb Kostas Papadimitriou
    for k in headers.keys():
67 142133fb Kostas Papadimitriou
        if '_' in k:
68 142133fb Kostas Papadimitriou
            headers.pop(k)
69 142133fb Kostas Papadimitriou
70 142133fb Kostas Papadimitriou
    for k in EXCLUDE_HEADERS:
71 142133fb Kostas Papadimitriou
        headers.pop(k, None)
72 142133fb Kostas Papadimitriou
73 33c84784 Sofia Papagiannaki
    kwargs['headers'] = headers
74 33c84784 Sofia Papagiannaki
    kwargs['body'] = request.raw_post_data
75 33c84784 Sofia Papagiannaki
76 33c84784 Sofia Papagiannaki
    p = urlparse.urlparse(target)
77 33c84784 Sofia Papagiannaki
    with PooledHTTPConnection(p.netloc, p.scheme) as conn:
78 33c84784 Sofia Papagiannaki
        conn.request(
79 33c84784 Sofia Papagiannaki
            request.method,
80 33c84784 Sofia Papagiannaki
            '?'.join([request.path, urllib.urlencode(request.GET)]),
81 33c84784 Sofia Papagiannaki
            **kwargs)
82 33c84784 Sofia Papagiannaki
        response = conn.getresponse()
83 33c84784 Sofia Papagiannaki
84 33c84784 Sofia Papagiannaki
        # turn httplib.HttpResponse to django.http.Response
85 33c84784 Sofia Papagiannaki
        length = response.getheader('content-length', None)
86 33c84784 Sofia Papagiannaki
        data = response.read(length)
87 33c84784 Sofia Papagiannaki
        status = int(response.status)
88 33c84784 Sofia Papagiannaki
        return HttpResponse(data, status=status)