1 import os
2 localDir = os.path.dirname(__file__)
3 import sys
4 import threading
5 import time
6
7 import cherrypy
8 from cherrypy._cpcompat import copykeys, HTTPConnection, HTTPSConnection
9 from cherrypy.lib import sessions
10 from cherrypy.lib.httputil import response_codes
11
12
18
19 cherrypy.tools.allow = cherrypy.Tool('on_start_resource', http_methods_allowed)
20
21
23
24 class Root:
25
26 _cp_config = {'tools.sessions.on': True,
27 'tools.sessions.storage_type': 'ram',
28 'tools.sessions.storage_path': localDir,
29 'tools.sessions.timeout': (1.0 / 60),
30 'tools.sessions.clean_freq': (1.0 / 60),
31 }
32
33 def clear(self):
34 cherrypy.session.cache.clear()
35 clear.exposed = True
36
37 def data(self):
38 cherrypy.session['aha'] = 'foo'
39 return repr(cherrypy.session._data)
40 data.exposed = True
41
42 def testGen(self):
43 counter = cherrypy.session.get('counter', 0) + 1
44 cherrypy.session['counter'] = counter
45 yield str(counter)
46 testGen.exposed = True
47
48 def testStr(self):
49 counter = cherrypy.session.get('counter', 0) + 1
50 cherrypy.session['counter'] = counter
51 return str(counter)
52 testStr.exposed = True
53
54 def setsessiontype(self, newtype):
55 self.__class__._cp_config.update(
56 {'tools.sessions.storage_type': newtype})
57 if hasattr(cherrypy, "session"):
58 del cherrypy.session
59 cls = getattr(sessions, newtype.title() + 'Session')
60 if cls.clean_thread:
61 cls.clean_thread.stop()
62 cls.clean_thread.unsubscribe()
63 del cls.clean_thread
64 setsessiontype.exposed = True
65 setsessiontype._cp_config = {'tools.sessions.on': False}
66
67 def index(self):
68 sess = cherrypy.session
69 c = sess.get('counter', 0) + 1
70 time.sleep(0.01)
71 sess['counter'] = c
72 return str(c)
73 index.exposed = True
74
75 def keyin(self, key):
76 return str(key in cherrypy.session)
77 keyin.exposed = True
78
79 def delete(self):
80 cherrypy.session.delete()
81 sessions.expire()
82 return "done"
83 delete.exposed = True
84
85 def delkey(self, key):
86 del cherrypy.session[key]
87 return "OK"
88 delkey.exposed = True
89
90 def blah(self):
91 return self._cp_config['tools.sessions.storage_type']
92 blah.exposed = True
93
94 def iredir(self):
95 raise cherrypy.InternalRedirect('/blah')
96 iredir.exposed = True
97
98 def restricted(self):
99 return cherrypy.request.method
100 restricted.exposed = True
101 restricted._cp_config = {'tools.allow.on': True,
102 'tools.allow.methods': ['GET']}
103
104 def regen(self):
105 cherrypy.tools.sessions.regenerate()
106 return "logged in"
107 regen.exposed = True
108
109 def length(self):
110 return str(len(cherrypy.session))
111 length.exposed = True
112
113 def session_cookie(self):
114
115 cherrypy.session.load()
116 return cherrypy.session.id
117 session_cookie.exposed = True
118 session_cookie._cp_config = {
119 'tools.sessions.path': '/session_cookie',
120 'tools.sessions.name': 'temp',
121 'tools.sessions.persistent': False}
122
123 cherrypy.tree.mount(Root())
124
125
126 from cherrypy.test import helper
127
128
130 setup_server = staticmethod(setup_server)
131
137
139 self.getPage('/setsessiontype/ram')
140 self.getPage('/clear')
141
142
143
144 self.getPage('/data')
145 self.assertBody("{'aha': 'foo'}")
146 c = self.cookies[0]
147 self.getPage('/data', self.cookies)
148 self.assertEqual(self.cookies[0], c)
149
150 self.getPage('/testStr')
151 self.assertBody('1')
152 cookie_parts = dict([p.strip().split('=')
153 for p in self.cookies[0][1].split(";")])
154
155 self.assertEqual(set(cookie_parts.keys()),
156 set(['session_id', 'expires', 'Path']))
157 self.getPage('/testGen', self.cookies)
158 self.assertBody('2')
159 self.getPage('/testStr', self.cookies)
160 self.assertBody('3')
161 self.getPage('/data', self.cookies)
162 self.assertBody("{'aha': 'foo', 'counter': 3}")
163 self.getPage('/length', self.cookies)
164 self.assertBody('2')
165 self.getPage('/delkey?key=counter', self.cookies)
166 self.assertStatus(200)
167
168 self.getPage('/setsessiontype/file')
169 self.getPage('/testStr')
170 self.assertBody('1')
171 self.getPage('/testGen', self.cookies)
172 self.assertBody('2')
173 self.getPage('/testStr', self.cookies)
174 self.assertBody('3')
175 self.getPage('/delkey?key=counter', self.cookies)
176 self.assertStatus(200)
177
178
179 time.sleep(2)
180 self.getPage('/')
181 self.assertBody('1')
182 self.getPage('/length', self.cookies)
183 self.assertBody('1')
184
185
186 self.getPage('/keyin?key=counter', self.cookies)
187 self.assertBody("True")
188 cookieset1 = self.cookies
189
190
191 self.getPage('/')
192 self.getPage('/length', self.cookies)
193 self.assertBody('2')
194
195
196 self.getPage('/delete', self.cookies)
197 self.assertBody("done")
198 self.getPage('/delete', cookieset1)
199 self.assertBody("done")
200 f = lambda: [
201 x for x in os.listdir(localDir) if x.startswith('session-')]
202 self.assertEqual(f(), [])
203
204
205 self.getPage('/')
206 f = lambda: [
207 x for x in os.listdir(localDir) if x.startswith('session-')]
208 self.assertNotEqual(f(), [])
209 time.sleep(2)
210 self.assertEqual(f(), [])
211
215
219
248
249
250
251
252
253 ts = []
254 for c in range(client_thread_count):
255 data_dict[c] = 0
256 t = threading.Thread(target=request, args=(c,))
257 ts.append(t)
258 t.start()
259
260 for t in ts:
261 t.join()
262
263 hitcount = max(data_dict.values())
264 expected = 1 + (client_thread_count * request_count)
265
266 for e in errors:
267 print(e)
268 self.assertEqual(hitcount, expected)
269
275
277
278 self.getPage('/testStr')
279
280 id = self.cookies[0][1].split(";", 1)[0].split("=", 1)[1]
281 path = os.path.join(localDir, "session-" + id)
282 os.unlink(path)
283 self.getPage('/testStr', self.cookies)
284
296
298 self.getPage('/testStr')
299
300 id1 = self.cookies[0][1].split(";", 1)[0].split("=", 1)[1]
301 self.getPage('/regen')
302 self.assertBody('logged in')
303 id2 = self.cookies[0][1].split(";", 1)[0].split("=", 1)[1]
304 self.assertNotEqual(id1, id2)
305
306 self.getPage('/testStr')
307
308 id1 = self.cookies[0][1].split(";", 1)[0].split("=", 1)[1]
309 self.getPage('/testStr',
310 headers=[
311 ('Cookie',
312 'session_id=maliciousid; '
313 'expires=Sat, 27 Oct 2017 04:18:28 GMT; Path=/;')])
314 id2 = self.cookies[0][1].split(";", 1)[0].split("=", 1)[1]
315 self.assertNotEqual(id1, id2)
316 self.assertNotEqual(id2, 'maliciousid')
317
319 self.getPage('/setsessiontype/ram')
320 self.getPage('/clear')
321 self.getPage('/session_cookie')
322
323 cookie_parts = dict([p.strip().split('=')
324 for p in self.cookies[0][1].split(";")])
325
326 self.assertEqual(set(cookie_parts.keys()), set(['temp', 'Path']))
327 id1 = cookie_parts['temp']
328 self.assertEqual(copykeys(sessions.RamSession.cache), [id1])
329
330
331 self.getPage('/session_cookie', self.cookies)
332 cookie_parts = dict([p.strip().split('=')
333 for p in self.cookies[0][1].split(";")])
334
335 self.assertEqual(set(cookie_parts.keys()), set(['temp', 'Path']))
336 self.assertBody(id1)
337 self.assertEqual(copykeys(sessions.RamSession.cache), [id1])
338
339
340 self.getPage('/session_cookie')
341
342 cookie_parts = dict([p.strip().split('=')
343 for p in self.cookies[0][1].split(";")])
344
345 self.assertEqual(set(cookie_parts.keys()), set(['temp', 'Path']))
346
347 id2 = cookie_parts['temp']
348 self.assertNotEqual(id1, id2)
349 self.assertEqual(set(sessions.RamSession.cache.keys()),
350 set([id1, id2]))
351
352
353 time.sleep(2.5)
354 cache = copykeys(sessions.RamSession.cache)
355 if cache:
356 if cache == [id2]:
357 self.fail("The second session did not time out.")
358 else:
359 self.fail("Unknown session id in cache: %r", cache)
360
361
362 import socket
363 try:
364 import memcache
365
366 host, port = '127.0.0.1', 11211
367 for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
368 socket.SOCK_STREAM):
369 af, socktype, proto, canonname, sa = res
370 s = None
371 try:
372 s = socket.socket(af, socktype, proto)
373
374
375 s.settimeout(1.0)
376 s.connect((host, port))
377 s.close()
378 except socket.error:
379 if s:
380 s.close()
381 raise
382 break
383 except (ImportError, socket.error):
389 else:
391 setup_server = staticmethod(setup_server)
392
420
422 client_thread_count = 5
423 request_count = 30
424
425
426 self.getPage("/")
427 self.assertBody("1")
428 cookies = self.cookies
429
430 data_dict = {}
431
432 def request(index):
433 for i in range(request_count):
434 self.getPage("/", cookies)
435
436
437 if not self.body.isdigit():
438 self.fail(self.body)
439 data_dict[index] = v = int(self.body)
440
441
442
443 ts = []
444 for c in range(client_thread_count):
445 data_dict[c] = 0
446 t = threading.Thread(target=request, args=(c,))
447 ts.append(t)
448 t.start()
449
450 for t in ts:
451 t.join()
452
453 hitcount = max(data_dict.values())
454 expected = 1 + (client_thread_count * request_count)
455 self.assertEqual(hitcount, expected)
456
462
475