Statistics
| Branch: | Tag: | Revision:

root / snf-django-lib / snf_django / lib / api / proxy / __init__.py @ 5ad8eca1

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 5ad8eca1 Kostas Papadimitriou
from synnefo.lib import join_urls
39 5ad8eca1 Kostas Papadimitriou
40 33c84784 Sofia Papagiannaki
from .utils import fix_header, forward_header
41 33c84784 Sofia Papagiannaki
42 33c84784 Sofia Papagiannaki
import urllib
43 33c84784 Sofia Papagiannaki
import urlparse
44 33c84784 Sofia Papagiannaki
45 142133fb Kostas Papadimitriou
# We use proxy to delegate requests to another domain. Sending host specific
46 142133fb Kostas Papadimitriou
# headers (Host, Cookie) may cause confusion to the server we proxy to.
47 142133fb Kostas Papadimitriou
#
48 142133fb Kostas Papadimitriou
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
49 142133fb Kostas Papadimitriou
# Connection and MUST NOT be communicated by proxies over further connections
50 142133fb Kostas Papadimitriou
EXCLUDE_HEADERS = ['Host', 'Cookie', 'Connection']
51 142133fb Kostas Papadimitriou
52 33c84784 Sofia Papagiannaki
53 33c84784 Sofia Papagiannaki
def proxy(request, target):
54 33c84784 Sofia Papagiannaki
    kwargs = {}
55 33c84784 Sofia Papagiannaki
56 33c84784 Sofia Papagiannaki
    # prepare headers
57 33c84784 Sofia Papagiannaki
    headers = dict(map(lambda (k, v): fix_header(k, v),
58 33c84784 Sofia Papagiannaki
                   filter(lambda (k, v): forward_header(k),
59 33c84784 Sofia Papagiannaki
                          request.META.iteritems())))
60 33c84784 Sofia Papagiannaki
61 142133fb Kostas Papadimitriou
    # set X-Forwarded-For, if already set, pass it through, otherwise set it
62 142133fb Kostas Papadimitriou
    # to the current request remote address
63 142133fb Kostas Papadimitriou
    SOURCE_IP = request.META.get('REMOTE_ADDR', None)
64 142133fb Kostas Papadimitriou
    if SOURCE_IP and not 'X-Forwarded-For' in headers:
65 142133fb Kostas Papadimitriou
        headers['X-Forwarded-For'] = SOURCE_IP
66 142133fb Kostas Papadimitriou
67 142133fb Kostas Papadimitriou
    # request.META remains cleanup
68 142133fb Kostas Papadimitriou
    for k in headers.keys():
69 142133fb Kostas Papadimitriou
        if '_' in k:
70 142133fb Kostas Papadimitriou
            headers.pop(k)
71 142133fb Kostas Papadimitriou
72 142133fb Kostas Papadimitriou
    for k in EXCLUDE_HEADERS:
73 142133fb Kostas Papadimitriou
        headers.pop(k, None)
74 142133fb Kostas Papadimitriou
75 33c84784 Sofia Papagiannaki
    kwargs['headers'] = headers
76 33c84784 Sofia Papagiannaki
    kwargs['body'] = request.raw_post_data
77 33c84784 Sofia Papagiannaki
78 33c84784 Sofia Papagiannaki
    p = urlparse.urlparse(target)
79 5ad8eca1 Kostas Papadimitriou
    path = join_urls(p.path, request.path)
80 33c84784 Sofia Papagiannaki
    with PooledHTTPConnection(p.netloc, p.scheme) as conn:
81 33c84784 Sofia Papagiannaki
        conn.request(
82 33c84784 Sofia Papagiannaki
            request.method,
83 5ad8eca1 Kostas Papadimitriou
            '?'.join([path, urllib.urlencode(request.GET)]), **kwargs)
84 33c84784 Sofia Papagiannaki
        response = conn.getresponse()
85 33c84784 Sofia Papagiannaki
86 33c84784 Sofia Papagiannaki
        # turn httplib.HttpResponse to django.http.Response
87 33c84784 Sofia Papagiannaki
        length = response.getheader('content-length', None)
88 33c84784 Sofia Papagiannaki
        data = response.read(length)
89 33c84784 Sofia Papagiannaki
        status = int(response.status)
90 33c84784 Sofia Papagiannaki
        return HttpResponse(data, status=status)