If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

I came to the subsequent (work in progress) solution that consists of only a controller:

# require libs
# coding: utf8

import requests

@auth.requires_login()
def index():

    # 1. It seams that relative path "./" is interpreted differently by web2py
    # if the called url contains a / (slash) at the end or not.
    # so when libraries (js and css) are called with relative path can happen that
    # the required parameter for retrieving the host from db sometime is considered
    # and sometimes not.
    start = 0
    if not request.env.http_referer is None and request.env.http_referer.startswith(URL(scheme=True, host=True)):
        # in those cases libraries (js and css) are loaded by the main html page called
        # and the needed id is not considered in the interpretation of the relative path
            path_referer = request.env.http_referer.lstrip(URL(scheme=True, host=True)).split('/') 
            dm_id = int(path_referer[0])
            start = int(str(dm_id)==request.args(0))
    else:
        dm_id = int(request.args.pop(0))
        
    if session.proxy is None:
        session.proxy = {}
    if not dm_id in session.proxy:
        session.proxy[dm_id] = Storage(
            # Custom solution:
            # Hosts are stored in DB but I don't want a query for every call so
            # I reduce the queries temporarily storing the result in session.
            # Hosts are stored under the key "host" of the json field "info"
            # inside the table "p_data_manager".
            host = db.p_data_manager[dm_id].info['host'],
#             cookies = request.cookies.copy()
        )

    # I compose the url to call
    host = session.proxy[dm_id].host
    protocol = 'https' if request.is_https else 'http'
    url = '%(protocol)s://%(host)s:8100' % locals()
    location = '/'.join(request.args[start:])
    if location:
        url += '/%s' % location

    res = requests.request(request.env.request_method.upper(), url,
        data = dict(request.vars),
        allow_redirects = False,
        # 2. In this way cookies are correctly managed and passed between the
        # client and the server and back again transparently to the user
        headers = dict(cookie=request.cookies)
        #              ^^^^^^ NOT "cookies"
    )

    for k,v in (res.cookies or {}).iteritems():
        response.cookies[k] = v.strip('\"')
        response.cookies[k]['path'] = '/'

    if res.status_code == 200:
        for k,v in res.headers.items():
            if k not in ('content-length', 'content-encoding', ):
                response.headers[k.title()] = v
        return res.content
    elif res.status_code in (302, 303, ):
        redirect(URL(args=[dm_id])+res.headers['location'], how=res.status_code)
    else:
        raise HTTP(res.status_code)
  • Now the big lack is that I need even to proxy cookies. I thougth they could be managed between my proxy and the called server or in a (probably) more used solution proxing them between the client and the server. (DONE. See note 2. in the code)
  • There are still open question even if I apparently solve in the code:
    1. why there's a possible different interpretation of the relative path "./" in the HTML code?
      it seams it can include my arguments if I add a slash at the end or point just to the current controller function (see note 1 in the code)

Comments (0)


Hosting graciously provided by:
Python Anywhere