I'm maintaining someone else's old CherryPy code, and have an interesting situation I'm trying to understand. Consider this code which demonstrates it:
import cherrypy
class HelloWorld(object):
def index(self, name):
html = """<form method="post">
<input type="text" name="name" value="%s" /></form>
Hello %s!""" % (name, name)
return html
index.exposed = True
cherrypy.quickstart(HelloWorld())
Run it with python hello.py
and go to http://127.0.0.1:8080/?name=foo. The output is a text input box with "foo" followed by "Hello foo!".
But if I edit the text in the box and replace it with "bar" and hit enter (submitting the form), the result is not "bar" in the input box and "Hello bar!" below but (apologies for ascii art input box):
+---------------------+
| [u'foo', u'bar'] |
+---------------------+
Hello [u'foo', u'bar']!
It seems that CherryPy is combining the URL querystring "name" argument value with the form "name" value submitted in the body of the POST request and providing a list with the two values to the exposed index() method.
From what I can tell of the code I'm maintaining, it didn't always work this way. So that leads to my two questions:
(I'm not intimately familiar with the CherryPy documentation, but I couldn't find the answer there.)
I don't think it was the change in 3.x series. You can directly access GET and POST params like in the following snippet. However using unique names is more advised and less error-prone way.
import urlparse
import cherrypy
class HelloWorld:
@cherrypy.expose
def index(self, name):
postParams = cherrypy.request.body.params
getParams = urlparse.parse_qs(cherrypy.request.query_string)
print(postParams, getParams)
# ({u'name': u'bar'}, {'name': ['foo']})
Good research @TimB. By skipping through the codebase I couldn't find where the thing happens. And yes CherryPy 3.2+ is like the series on its own.
CherryPy is quite configurable, and your case is not an exception, when you're able to deal with its notions. Specifically you can write a CherryPy tool to override the mixed request params with POST params. It's just a few lines.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urlparse
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
},
'/' : {
'tools.postoverride.on' : True,
}
}
def postOverride():
cherrypy.request.params.update(cherrypy.request.body.params)
cherrypy.tools.postoverride = cherrypy.Tool('before_handler', postOverride)
class HelloWorld:
@cherrypy.expose
def index(self, name):
html = """<form method="post">
<input type="text" name="name" value="%s" /></form>
Hello %s!""" % (name, name)
return html
if __name__ == '__main__':
cherrypy.quickstart(HelloWorld(), '/', config)