how to make a sub_application request in parent_application?

145 Views Asked by At

I have two web application: parent_app and sub_app

say that, http://www.some.com/parent.png will be handled by parent_app.

if it is refererd in another website, parent_app get a HTTP_REFERER, say that is http://www.other.com/path?query=value,

I want a sub_app take this HTTP_REFERER's path and query_string as his own path and query_string, and return the result to parent_app, so ,parent_app's url won't be changed, the visitors brower won't get a 303 jump either.

sub.py:

import web
class Sub(object):
    def GET(self):
        return web.input().query             # I want it to be 'value', from "query=value"
urls = (r'/path', 'Sub')
sub_app = web.application(urls, locals())

parent.py:

import web
from sub import sub_app
class Parent(object):
    def GET(self):
        return sub_app.request('/path?query=value').data  #=========(1)
urls = (
    r'/parent.png', 'Parent',
    r'', sub_app
    )
parent_app = web.application(urls, locals())

and run:

>>>python parent.py

when I visit 'http://www.some.com/parent.png'?

I get these errors:

Traceback (most recent call last):
  File "/home/netroyal/Documents/program/studame/web/wsgiserver/__init__.py", line 1245, in communicate
    req.respond()
  File "/home/netroyal/Documents/program/studame/web/wsgiserver/__init__.py", line 775, in respond
    self.server.gateway(self).respond()
  File "/home/netroyal/Documents/program/studame/web/wsgiserver/__init__.py", line 2018, in respond
    response = self.req.server.wsgi_app(self.env, self.start_response)
  File "/home/netroyal/Documents/program/studame/web/httpserver.py", line 306, in __call__
    return self.app(environ, xstart_response)
  File "/home/netroyal/Documents/program/studame/web/httpserver.py", line 274, in __call__
    return self.app(environ, start_response)
  File "/home/netroyal/Documents/program/studame/web/application.py", line 279, in wsgi
    result = self.handle_with_processors()
  File "/home/netroyal/Documents/program/studame/web/application.py", line 249, in handle_with_processors
    return process(self.processors)
  File "/home/netroyal/Documents/program/studame/web/application.py", line 246, in process
    raise self.internalerror()
  File "/home/netroyal/Documents/program/studame/web/application.py", line 473, in internalerror
    parent = self.get_parent_app()
  File "/home/netroyal/Documents/program/studame/web/application.py", line 458, in get_parent_app
    if self in web.ctx.app_stack:
AttributeError: 'ThreadedDict' object has no attribute 'app_stack'

/home/netroyal/Documents/program/studame/web/ is the web.py package path.

so, how can I make (1) running correctly?

I want to get the same result like (1) runs in shell:

>>> import web
>>> class Sub(object):
...     def GET(self):
...         return web.input().query
>>> urls = ('/path', 'Sub')
>>> sub_app = web.application(urls, locals())
>>> sub_app.request('/path?query=value').data             #=========(1)'
'value'
>>> 

I know, I can use

web.seeother('/path?query=value') 

to make visitors see the result, but I do not want the browser jump to another url.

I think

urllib2.urlopen('http://www.some.com/path?query=value') 

will work, but is there a better way to do it in a single request?

thank you for any help!-----for reading this,too ! ==========================================Edit======================================

OK, after some code hacking, I solved a part of my problem:

I add a simulation.py:

import web, re
class Simulation(object):
    def __init__(self, urls, fvars):
        self._urls = urls
        self._fvars = fvars
    def request(self, localpart='/', method='GET', data=None, host='0.0.0.0:8080', headers=None, https=False):   
        #nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn    
        # get path and args(parameters from new url)
        try:
            path, query = localpart.split('?', 1)
        except:
            path, query = (localpart, '')
        # get all arguments: args(parameters)
        parts = query.split('&')
        args = {}
        for part in parts:
            try:
                name, value = part.split('=')
            except:
                pass
            else:
                args[name] = value
        #uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
        patterns = [self._urls[2*i] for i in range(0, len(self._urls)/2)]
        for i in range(0, len(patterns)):
            result = re.match(patterns[i], path)
            if result:
                web.input = lambda: web.storage(args)
                Worker = self._fvars[self._urls[2*i + 1]]
                return Worker().GET(*result.groups())
        #----------------------------------------------------------------------------------------
        raise web.notfound()

and in sub.py:

from simulation import *
class Sub(object):
    def GET(self):
        return web.input().query             # I want it to be 'value', from "query=value"
urls = (r'/path', 'Sub')
sub_app = web.application(urls, locals())
sub_sim = Simulation(urls, locals())         # new class to run request in parent_app

adn in parent.py:

import web
from sub import sub_app, sub_sim               #sub_sim is new
class Parent(object):
    def GET(self):
        return sub_sim.request('/path?query=value')  # sub_app changed to sub_sim, and no (.data)
urls = (
    r'/parent.png', 'Parent',
    r'', sub_app
    )
parent_app = web.application(urls, locals())

and I can use '/sub' to visit sub_app too, keep it a standalone application.

I solved my problem, not perfectly,but some kind of hard. I think I will just use it, when I have more time, I will find another way. if you have a better solution, please tell me, thanks.

Best regards.

========================================= I feel like I was speaking to myself, where is people?

0

There are 0 best solutions below