Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default the root view in cherrypy

In some source code I am writing, I am able to make a request such as:

http://proxy.metaperl.org/index/bitgold-rw1

And have it redirect successfully.

However, I want to remove index from the URL and have it still redirect by using the index() method. I tried renaming index() to default() after reading about Dispatching, but it still does not allow me to have a URL like this:

http://proxy.metaperl.org/bitgold-rw1

It tries to find a method named bitgold-rw1 instead of using the default method to resolve the request, gving me the error:

NotFound: (404, "The path '/bitgold-rw1' was not found.")

The WSGI startup file looks like this:

# -*- python -*-

# core
import os
import sys

# 3rd party
import cherrypy

# local
def full_path(*extra):
    return os.path.join(os.path.dirname(__file__), *extra)

sys.path.insert(0, full_path())
import config
import myapp

application = cherrypy.Application(
    myapp.Root(),
    "/",
    config.config)
like image 882
Terrence Brannon Avatar asked Sep 03 '15 06:09

Terrence Brannon


3 Answers

As mentioned by @ralhei @saaj default method is the key if you do not want to deal with dispatchers in cherrypy. I tried the code below and working as you want

class Root(object):

    @cherrypy.expose
    def index(self, tag):
        redirect_url = db.urls[tag]
        ip = cherrypy.request.headers['Remote-Addr']
        request_url = 'http://ipinfo.io/{0}/country'.format(ip)
        r = requests.get(request_url)
        country = r.text.strip()
        raise cherrypy.HTTPRedirect(redirect_url)

    @cherrypy.expose
    def default(self,tag):
        return self.index(tag)
like image 141
Ozan Avatar answered Nov 08 '22 14:11

Ozan


Renaming to default is not enough. It needs to be callable at least with variadic arguments, *args, to receive path segments. Like this:

#!/usr/bin/env python3


import cherrypy


config = {
  'global' : {
    'server.socket_host' : '127.0.0.1',
    'server.socket_port' : 8080,
    'server.thread_pool' : 8
  }
}


class Root:

  @cherrypy.expose
  def default(self, *args, **kwargs):
    cherrypy.log('{0}, {1}'.format(args, kwargs))
    return 'OK'


if __name__ == '__main__':
  cherrypy.quickstart(Root(), '/', config)

Then it will catch things like http://127.0.0.1:8080/bitgold-rw1/ and also like http://127.0.0.1:8080/bitgold-rw1/foo/bar.

And btw, if it's about MVC it's a controller, not a view.

like image 2
saaj Avatar answered Nov 08 '22 13:11

saaj


if you rename your index method to 'default' in your Root class this should work.

Add the line

cherrypy.quickstart(Root())

at the bottom of myapp.py and run it with 'python myapp.py' your server should startup and listen on port 8080. Making a request to http://localhost:8080/bitgold-rw1 works for me, it complains that I'm not a US citizen which I guess is fine ;-)

like image 1
ralhei Avatar answered Nov 08 '22 12:11

ralhei