Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/trunk/cherrypy/test/test_objectmapping.py

Revision 2030 (checked in by lakin, 2 months ago)

#733 - Return a 404 when query parameters passed to a handler are incorect. Similarly return a 404 when path atoms are incorrectly passed to a handler. Alternatively return a 400 when body params are incorrectly passed to a handler. Includes tests.

  • Property svn:eol-style set to native
Line 
1 from cherrypy.test import test
2 test.prefer_parent_path()
3
4 import cherrypy
5
6
7 script_names = ["", "/foo", "/users/fred/blog", "/corp/blog"]
8
9 def setup_server():
10     class Root:
11         def index(self, name="world"):
12             return name
13         index.exposed = True
14        
15         def foobar(self):
16             return "bar"
17         foobar.exposed = True
18        
19         def default(self, *params):
20             return "default:" + repr(params)
21         default.exposed = True
22        
23         def other(self):
24             return "other"
25         other.exposed = True
26        
27         def extra(self, *p):
28             return repr(p)
29         extra.exposed = True
30        
31         def redirect(self):
32             raise cherrypy.HTTPRedirect('dir1/', 302)
33         redirect.exposed = True
34        
35         def notExposed(self):
36             return "not exposed"
37        
38         def confvalue(self):
39             return cherrypy.request.config.get("user")
40         confvalue.exposed = True
41    
42     def mapped_func(self, ID=None):
43         return "ID is %s" % ID
44     mapped_func.exposed = True
45     setattr(Root, "Von B\xfclow", mapped_func)
46    
47    
48     class Exposing:
49         def base(self):
50             return "expose works!"
51         cherrypy.expose(base)
52         cherrypy.expose(base, "1")
53         cherrypy.expose(base, "2")
54    
55     class ExposingNewStyle(object):
56         def base(self):
57             return "expose works!"
58         cherrypy.expose(base)
59         cherrypy.expose(base, "1")
60         cherrypy.expose(base, "2")
61    
62    
63     class Dir1:
64         def index(self):
65             return "index for dir1"
66         index.exposed = True
67        
68         def myMethod(self):
69             return "myMethod from dir1, path_info is:" + repr(cherrypy.request.path_info)
70         myMethod.exposed = True
71         myMethod._cp_config = {'tools.trailing_slash.extra': True}
72        
73         def default(self, *params):
74             return "default for dir1, param is:" + repr(params)
75         default.exposed = True
76
77
78     class Dir2:
79         def index(self):
80             return "index for dir2, path is:" + cherrypy.request.path_info
81         index.exposed = True
82        
83         def script_name(self):
84             return cherrypy.tree.script_name()
85         script_name.exposed = True
86        
87         def cherrypy_url(self):
88             return cherrypy.url("/extra")
89         cherrypy_url.exposed = True
90        
91         def posparam(self, *vpath):
92             return "/".join(vpath)
93         posparam.exposed = True
94    
95    
96     class Dir3:
97         def default(self):
98             return "default for dir3, not exposed"
99    
100     class Dir4:
101         def index(self):
102             return "index for dir4, not exposed"
103    
104     class DefNoIndex:
105         def default(self, *args):
106             raise cherrypy.HTTPRedirect("contact")
107         default.exposed = True
108    
109     # MethodDispatcher code
110     class ByMethod:
111         exposed = True
112        
113         def __init__(self, *things):
114             self.things = list(things)
115        
116         def GET(self):
117             return repr(self.things)
118        
119         def POST(self, thing):
120             self.things.append(thing)
121    
122     class Collection:
123         default = ByMethod('a', 'bit')
124    
125     Root.exposing = Exposing()
126     Root.exposingnew = ExposingNewStyle()
127     Root.dir1 = Dir1()
128     Root.dir1.dir2 = Dir2()
129     Root.dir1.dir2.dir3 = Dir3()
130     Root.dir1.dir2.dir3.dir4 = Dir4()
131     Root.defnoindex = DefNoIndex()
132     Root.bymethod = ByMethod('another')
133     Root.collection = Collection()
134    
135     d = cherrypy.dispatch.MethodDispatcher()
136     for url in script_names:
137         conf = {'/': {'user': (url or "/").split("/")[-2]},
138                 '/bymethod': {'request.dispatch': d},
139                 '/collection': {'request.dispatch': d},
140                 }
141         cherrypy.tree.mount(Root(), url, conf)
142    
143     cherrypy.config.update({'environment': "test_suite"})
144    
145    
146     class Isolated:
147         def index(self):
148             return "made it!"
149         index.exposed = True
150    
151     cherrypy.tree.mount(Isolated(), "/isolated")
152    
153     class AnotherApp:
154        
155         exposed = True
156        
157         def GET(self):
158             return "milk"
159    
160     cherrypy.tree.mount(AnotherApp(), "/app", {'/': {'request.dispatch': d}})
161
162
163 from cherrypy.test import helper
164
165 class ObjectMappingTest(helper.CPWebCase):
166    
167     def testObjectMapping(self):
168         for url in script_names:
169             prefix = self.script_name = url
170            
171             self.getPage('/')
172             self.assertBody('world')
173            
174             self.getPage("/dir1/myMethod")
175             self.assertBody("myMethod from dir1, path_info is:'/dir1/myMethod'")
176            
177             self.getPage("/this/method/does/not/exist")
178             self.assertBody("default:('this', 'method', 'does', 'not', 'exist')")
179            
180             self.getPage("/extra/too/much")
181             self.assertBody("('too', 'much')")
182            
183             self.getPage("/other")
184             self.assertBody('other')
185            
186             self.getPage("/notExposed")
187             self.assertBody("default:('notExposed',)")
188            
189             self.getPage("/dir1/dir2/")
190             self.assertBody('index for dir2, path is:/dir1/dir2/')
191            
192             # Test omitted trailing slash (should be redirected by default).
193             self.getPage("/dir1/dir2")
194             self.assertStatus((302, 303))
195             self.assertHeader('Location', '%s/dir1/dir2/' % self.base())
196            
197             # Test extra trailing slash (should be redirected if configured).
198             self.getPage("/dir1/myMethod/")
199             self.assertStatus((302, 303))
200             self.assertHeader('Location', '%s/dir1/myMethod' % self.base())
201            
202             # Test that default method must be exposed in order to match.
203             self.getPage("/dir1/dir2/dir3/dir4/index")
204             self.assertBody("default for dir1, param is:('dir2', 'dir3', 'dir4', 'index')")
205            
206             # Test *vpath when default() is defined but not index()
207             # This also tests HTTPRedirect with default.
208             self.getPage("/defnoindex")
209             self.assertStatus((302, 303))
210             self.assertHeader('Location', '%s/contact' % self.base())
211             self.getPage("/defnoindex/")
212             self.assertStatus((302, 303))
213             self.assertHeader('Location', '%s/defnoindex/contact' % self.base())
214             self.getPage("/defnoindex/page")
215             self.assertStatus((302, 303))
216             self.assertHeader('Location', '%s/defnoindex/contact' % self.base())
217            
218             self.getPage("/redirect")
219             self.assertStatus('302 Found')
220             self.assertHeader('Location', '%s/dir1/' % self.base())
221            
222             # Test that we can use URL's which aren't all valid Python identifiers
223             # This should also test the %XX-unquoting of URL's.
224             self.getPage("/Von%20B%fclow?ID=14")
225             self.assertBody("ID is 14")
226            
227             # Test that %2F in the path doesn't get unquoted too early;
228             # that is, it should not be used to separate path components.
229             # See ticket #393.
230             self.getPage("/page%2Fname")
231             self.assertBody("default:('page/name',)")
232            
233             self.getPage("/dir1/dir2/script_name")
234             self.assertBody(url)
235             self.getPage("/dir1/dir2/cherrypy_url")
236             self.assertBody("%s/extra" % self.base())
237            
238             # Test that configs don't overwrite each other from diferent apps
239             self.getPage("/confvalue")
240             self.assertBody((url or "/").split("/")[-2])
241        
242         self.script_name = ""
243        
244         # Test absoluteURI's in the Request-Line
245         self.getPage('http://127.0.0.1/')
246         self.assertBody('world')
247        
248         # Test that the "isolated" app doesn't leak url's into the root app.
249         # If it did leak, Root.default() would answer with
250         #   "default:('isolated', 'doesnt', 'exist')".
251         self.getPage("/isolated/")
252         self.assertStatus("200 OK")
253         self.assertBody("made it!")
254         self.getPage("/isolated/doesnt/exist")
255         self.assertStatus("404 Not Found")
256        
257         # Make sure /foobar maps to Root.foobar and not to the app
258         # mounted at /foo. See http://www.cherrypy.org/ticket/573
259         self.getPage("/foobar")
260         self.assertBody("bar")
261    
262     def testPositionalParams(self):
263         self.getPage("/dir1/dir2/posparam/18/24/hut/hike")
264         self.assertBody("18/24/hut/hike")
265        
266         # intermediate index methods should not receive posparams;
267         # only the "final" index method should do so.
268         self.getPage("/dir1/dir2/5/3/sir")
269         self.assertBody("default for dir1, param is:('dir2', '5', '3', 'sir')")
270        
271         # test that extra positional args raises an 404 Not Found
272         # See http://www.cherrypy.org/ticket/733.
273         self.getPage("/dir1/dir2/script_name/extra/stuff")
274         self.assertStatus(404)
275    
276     def testExpose(self):
277         # Test the cherrypy.expose function/decorator
278         self.getPage("/exposing/base")
279         self.assertBody("expose works!")
280        
281         self.getPage("/exposing/1")
282         self.assertBody("expose works!")
283        
284         self.getPage("/exposing/2")
285         self.assertBody("expose works!")
286        
287         self.getPage("/exposingnew/base")
288         self.assertBody("expose works!")
289        
290         self.getPage("/exposingnew/1")
291         self.assertBody("expose works!")
292        
293         self.getPage("/exposingnew/2")
294         self.assertBody("expose works!")
295    
296     def testMethodDispatch(self):
297         self.getPage("/bymethod")
298         self.assertBody("['another']")
299         self.assertHeader('Allow', 'GET, HEAD, POST')
300        
301         self.getPage("/bymethod", method="HEAD")
302         self.assertBody("")
303         self.assertHeader('Allow', 'GET, HEAD, POST')
304        
305         self.getPage("/bymethod", method="POST", body="thing=one")
306         self.assertBody("")
307         self.assertHeader('Allow', 'GET, HEAD, POST')
308        
309         self.getPage("/bymethod")
310         self.assertBody("['another', 'one']")
311         self.assertHeader('Allow', 'GET, HEAD, POST')
312        
313         self.getPage("/bymethod", method="PUT")
314         self.assertErrorPage(405)
315         self.assertHeader('Allow', 'GET, HEAD, POST')
316        
317         # Test default with posparams
318         self.getPage("/collection/silly", method="POST")
319         self.getPage("/collection", method="GET")
320         self.assertBody("['a', 'bit', 'silly']")
321        
322         # Test custom dispatcher set on app root (see #737).
323         self.getPage("/app")
324         self.assertBody("milk")
325
326
327 if __name__ == "__main__":
328     setup_server()
329     helper.testmain()
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets