Best way to make subapps with Traversal

Ok so I have my apps, that takes requests from root / Almost everything is using traversal.

But i'd like to make on top of that site a rest api.

So I'm off with two choices. I either separate the that in two different apps and put that rest application to : rest.site.com, Or I can move it to site.com/rest/*traversal

If I'm doing "/rest/*traversal", I guess I'll have to add a route called rest_traversal where the traversal path will be *traversal with the route /rest/*traversal. I did that once for an admin page.

I was wondering if there was a cleanest way to do that. I tried to use virtual_root, but as I understand virtual_root is actually getting added to the path for traversal.

like having virtual_root = /cms and requesting /fun will create the following path /cms/fun

I on the other hand wish to have /cms/fun turned into /fun

Answers


If you're using traversal already, why not just use it to return your "rest API root" object when Pyramid traverses to /rest/? From there, everything will work naturally.

class ApplicationRoot(object):

    def __getitem__(self, name):
        if name == "rest":
            return RestAPIRoot(parent=self, name=name)
        ...

If your "application tree" and "API tree" have the same children and you want to have different views registered for them depending on which branch of the tree the child is located in, you can use containment view predicate to register your API views, so they will only match when the child is inside the "API branch":

containment

This value should be a reference to a Python class or interface that a parent object in the context resource’s lineage must provide in order for this view to be found and called. The resources in your resource tree must be “location-aware” to use this feature.

If containment is not supplied, the interfaces and classes in the lineage are not considered when deciding whether or not to invoke the view callable.

Another approach would be not to build a separate "API tree" but to use your "main" application's "URI-space" as RESTful API. The only problem with this is that GET and possibly POST request methods are already "taken" on your resources and mapped to your "normal" views which return HTML or consume HTTP form POSTs. There are numerous ways to work around this:

  • register the API views with a separate name, so, say GET /users/123 would return HTML and GET /users/123/json would return a JSON object. Similarly, POST /users/123 would expect HTTP form to be posted and POST /users/123/json would expect JSON. A nice thing about this approach is that you can easily add, say, an XML serializer at GET /users/123/xml.

  • use custom view predicates so GET /users/123 and GET /users/123?format=json are routed to different views. Actually, there's a built-in request_param predicate for that since Pyramid 1.2

  • use xhr predicate to differentiate requests based on HTTP_X_REQUESTED_WITH header or accept predicate to differentiate on HTTP_ACCEPT header


I know this has been answered already, but in case someone arrives here looking for another possible way to make "subapps" and using them in pyramid, I wanted to point out that some interesting things can be done with pyramid.wsgi

"""
example of wsgiapp decorator usage
http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/api/wsgi.html
"""

from pyramid.wsgi import wsgiapp2, wsgiapp
from pyramid.config import Configurator
from webob import Request, Response
import pprint

# define some apps


def wsgi_echo(environ, start_response):
    """pretty print out the environ"""
    response = Response(body=pprint.pformat({k: v for k, v in environ.items()
                                             if k not in ["wsgi.errors",
                                                          "wsgi.input",
                                                          "SCRIPT_NAME"]}))
    return response(environ, start_response)


print Request.blank("/someurl").send(wsgi_echo).body


# convert wsgi app to a pyramid view callable
pyramid_echo = wsgiapp(wsgi_echo)
pyramid_echo_2 = wsgiapp2(wsgi_echo)

# wire up a pyramid application

config = Configurator()
config.add_view(pyramid_echo, name="foo")  # /foo
config.add_view(pyramid_echo, name="bar")  # /bar
config.add_view(pyramid_echo_2, name="foo_2")  # /foo
config.add_view(pyramid_echo_2, name="bar_2")  # /bar
pyramid_app = config.make_wsgi_app()

#call some urls
foo_body = Request.blank("/foo").send(pyramid_app).body
bar_body = Request.blank("/bar").send(pyramid_app).body
foo_body_2 = Request.blank("/foo_2").send(pyramid_app).body
bar_body_2 = Request.blank("/bar_2").send(pyramid_app).body

# both should be different because we arrived at 2 different urls
assert foo_body != bar_body, "bodies should not be equal"

# should be equal because wsgiapp2 fixes stuff before calling
# application in fact there's an additional SCRIPT_NAME in the
# environment that we are filtering out
assert foo_body_2 == bar_body_2, "bodies should be equal"

# so how to pass the path along? like /foo/fuuuu should come back
# /fuuuu does it
foo_body = Request.blank("/foo_2/fuuuu").send(pyramid_app).body
assert "'/fuuuu'," in foo_body, "path didn't get passed along"


# tldr: a wsgi app that is decorated with wsgiapp2 will recieve data
# as if it was mounted at "/", any url generation it has to do should
# take into account the SCRIPT_NAME variable that may arrive in the
# environ when it is called

Need Your Help

wicket PageParameters encoding

java wicket

My project is under eclipse, Tomcat, Spring, Hibernate. In my web app when I try go to enother webPage :

Simple get API call in jQuery

javascript jquery json web

I have a url to which I need to make a get call. The url returns the following JSON response when run in POSTMAN.