Mercurial > p > roundup > code
comparison test/rest_common.py @ 5674:6dc4dba1c225
REST: Use If-Match header for incoming requests
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Mon, 25 Mar 2019 21:23:52 +0100 |
| parents | 6b6bc8d31caf |
| children | b8e8b1b3ec77 |
comparison
equal
deleted
inserted
replaced
| 5673:6b6bc8d31caf | 5674:6dc4dba1c225 |
|---|---|
| 373 self.assertEqual(etag, "6adf97f83acf6453d4a6a4b1070f3754") | 373 self.assertEqual(etag, "6adf97f83acf6453d4a6a4b1070f3754") |
| 374 | 374 |
| 375 def testEtagProcessing(self): | 375 def testEtagProcessing(self): |
| 376 ''' | 376 ''' |
| 377 Etags can come from two places: | 377 Etags can come from two places: |
| 378 ETag http header | 378 If-Match http header |
| 379 @etags value posted in the form | 379 @etags value posted in the form |
| 380 | 380 |
| 381 Both will be checked if availble. If either one | 381 Both will be checked if availble. If either one |
| 382 fails, the etag check will fail. | 382 fails, the etag check will fail. |
| 383 | 383 |
| 399 cgi.MiniFieldStorage('data', 'Joe Doe Doe'), | 399 cgi.MiniFieldStorage('data', 'Joe Doe Doe'), |
| 400 ] | 400 ] |
| 401 | 401 |
| 402 if mode == 'header': | 402 if mode == 'header': |
| 403 print("Mode = %s"%mode) | 403 print("Mode = %s"%mode) |
| 404 self.headers = {'etag': etag} | 404 self.headers = {'if-match': etag} |
| 405 elif mode == 'etag': | 405 elif mode == 'etag': |
| 406 print("Mode = %s"%mode) | 406 print("Mode = %s"%mode) |
| 407 form.list.append(cgi.MiniFieldStorage('@etag', etag)) | 407 form.list.append(cgi.MiniFieldStorage('@etag', etag)) |
| 408 elif mode == 'both': | 408 elif mode == 'both': |
| 409 print("Mode = %s"%mode) | 409 print("Mode = %s"%mode) |
| 410 self.headers = {'etag': etag} | 410 self.headers = {'etag': etag} |
| 411 form.list.append(cgi.MiniFieldStorage('@etag', etag)) | 411 form.list.append(cgi.MiniFieldStorage('@etag', etag)) |
| 412 elif mode == 'brokenheader': | 412 elif mode == 'brokenheader': |
| 413 print("Mode = %s"%mode) | 413 print("Mode = %s"%mode) |
| 414 self.headers = {'etag': 'bad'} | 414 self.headers = {'if-match': 'bad'} |
| 415 form.list.append(cgi.MiniFieldStorage('@etag', etag)) | 415 form.list.append(cgi.MiniFieldStorage('@etag', etag)) |
| 416 elif mode == 'brokenetag': | 416 elif mode == 'brokenetag': |
| 417 print("Mode = %s"%mode) | 417 print("Mode = %s"%mode) |
| 418 self.headers = {'etag': etag} | 418 self.headers = {'if-match': etag} |
| 419 form.list.append(cgi.MiniFieldStorage('@etag', 'bad')) | 419 form.list.append(cgi.MiniFieldStorage('@etag', 'bad')) |
| 420 elif mode == 'none': | 420 elif mode == 'none': |
| 421 print( "Mode = %s"%mode) | 421 print( "Mode = %s"%mode) |
| 422 else: | 422 else: |
| 423 self.fail("unknown mode found") | 423 self.fail("unknown mode found") |
| 449 "REQUEST_METHOD": "PUT" | 449 "REQUEST_METHOD": "PUT" |
| 450 } | 450 } |
| 451 headers={"accept": "application/json", | 451 headers={"accept": "application/json", |
| 452 "content-type": env['CONTENT_TYPE'], | 452 "content-type": env['CONTENT_TYPE'], |
| 453 "content-length": env['CONTENT_LENGTH'], | 453 "content-length": env['CONTENT_LENGTH'], |
| 454 "etag": etag | 454 "if-match": etag |
| 455 } | 455 } |
| 456 self.headers=headers | 456 self.headers=headers |
| 457 # we need to generate a FieldStorage the looks like | 457 # we need to generate a FieldStorage the looks like |
| 458 # FieldStorage(None, None, 'string') rather than | 458 # FieldStorage(None, None, 'string') rather than |
| 459 # FieldStorage(None, None, []) | 459 # FieldStorage(None, None, []) |
| 476 # TEST #2 | 476 # TEST #2 |
| 477 # Set joe's 'realname' using json data. | 477 # Set joe's 'realname' using json data. |
| 478 # simulate: /rest/data/user/<id>/realname | 478 # simulate: /rest/data/user/<id>/realname |
| 479 # use etag in payload | 479 # use etag in payload |
| 480 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 480 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 481 body=s2b('{ "@etag": "%s", "data": "Joe Doe 2" }'%etag) | 481 etagb = etag.strip ('"') |
| 482 body=s2b('{ "@etag": "\\"%s\\"", "data": "Joe Doe 2" }'%etagb) | |
| 482 env = { "CONTENT_TYPE": "application/json", | 483 env = { "CONTENT_TYPE": "application/json", |
| 483 "CONTENT_LENGTH": len(body), | 484 "CONTENT_LENGTH": len(body), |
| 484 "REQUEST_METHOD": "PUT", | 485 "REQUEST_METHOD": "PUT", |
| 485 } | 486 } |
| 486 self.headers=None # have FieldStorage get len from env. | 487 self.headers=None # have FieldStorage get len from env. |
| 490 environ=env) | 491 environ=env) |
| 491 self.server.client.request.headers.get=self.get_header | 492 self.server.client.request.headers.get=self.get_header |
| 492 | 493 |
| 493 headers={"accept": "application/json", | 494 headers={"accept": "application/json", |
| 494 "content-type": env['CONTENT_TYPE'], | 495 "content-type": env['CONTENT_TYPE'], |
| 495 "etag": etag | 496 "if-match": etag |
| 496 } | 497 } |
| 497 self.headers=headers # set for dispatch | 498 self.headers=headers # set for dispatch |
| 498 | 499 |
| 499 results = self.server.dispatch('PUT', | 500 results = self.server.dispatch('PUT', |
| 500 "/rest/data/user/%s/realname"%self.joeid, | 501 "/rest/data/user/%s/realname"%self.joeid, |
| 514 # use etag from header | 515 # use etag from header |
| 515 # | 516 # |
| 516 # Also use GET on the uri via the dispatch to retrieve | 517 # Also use GET on the uri via the dispatch to retrieve |
| 517 # the results from the db. | 518 # the results from the db. |
| 518 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 519 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 519 headers={"etag": etag, | 520 headers={"if-match": etag, |
| 520 "accept": "application/json", | 521 "accept": "application/json", |
| 521 } | 522 } |
| 522 form = cgi.FieldStorage() | 523 form = cgi.FieldStorage() |
| 523 form.list = [ | 524 form.list = [ |
| 524 cgi.MiniFieldStorage('data', 'Joe Doe'), | 525 cgi.MiniFieldStorage('data', 'Joe Doe'), |
| 551 stored_results = self.server.get_element('user', self.joeid, | 552 stored_results = self.server.get_element('user', self.joeid, |
| 552 self.empty_form) | 553 self.empty_form) |
| 553 self.assertEqual(self.dummy_client.response_code, 200) | 554 self.assertEqual(self.dummy_client.response_code, 200) |
| 554 | 555 |
| 555 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 556 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 556 body=s2b('{ "address": "demo2@example.com", "@etag": "%s"}'%etag) | 557 etagb = etag.strip ('"') |
| 558 body=s2b('{ "address": "demo2@example.com", "@etag": "\\"%s\\""}'%etagb) | |
| 557 env = { "CONTENT_TYPE": "application/json", | 559 env = { "CONTENT_TYPE": "application/json", |
| 558 "CONTENT_LENGTH": len(body), | 560 "CONTENT_LENGTH": len(body), |
| 559 "REQUEST_METHOD": "PATCH" | 561 "REQUEST_METHOD": "PATCH" |
| 560 } | 562 } |
| 561 headers={"accept": "application/json", | 563 headers={"accept": "application/json", |
| 578 self.assertEqual(results['data']['attributes']['address'], | 580 self.assertEqual(results['data']['attributes']['address'], |
| 579 'demo2@example.com') | 581 'demo2@example.com') |
| 580 | 582 |
| 581 # and set it back reusing env and headers from last test | 583 # and set it back reusing env and headers from last test |
| 582 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 584 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 583 body=s2b('{ "address": "%s", "@etag": "%s"}'%( | 585 etagb = etag.strip ('"') |
| 586 body=s2b('{ "address": "%s", "@etag": "\\"%s\\""}'%( | |
| 584 stored_results['data']['attributes']['address'], | 587 stored_results['data']['attributes']['address'], |
| 585 etag)) | 588 etagb)) |
| 586 # reuse env and headers from prior test. | 589 # reuse env and headers from prior test. |
| 587 body_file=BytesIO(body) # FieldStorage needs a file | 590 body_file=BytesIO(body) # FieldStorage needs a file |
| 588 form = client.BinaryFieldStorage(body_file, | 591 form = client.BinaryFieldStorage(body_file, |
| 589 headers=headers, | 592 headers=headers, |
| 590 environ=env) | 593 environ=env) |
| 663 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 666 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 664 form.list = [ | 667 form.list = [ |
| 665 cgi.MiniFieldStorage('data', 'Joe Doe Doe'), | 668 cgi.MiniFieldStorage('data', 'Joe Doe Doe'), |
| 666 ] | 669 ] |
| 667 | 670 |
| 668 self.headers = {'etag': etag } # use etag in header | 671 self.headers = {'if-match': etag } # use etag in header |
| 669 results = self.server.put_attribute( | 672 results = self.server.put_attribute( |
| 670 'user', self.joeid, 'realname', form | 673 'user', self.joeid, 'realname', form |
| 671 ) | 674 ) |
| 672 self.assertEqual(self.dummy_client.response_code, 200) | 675 self.assertEqual(self.dummy_client.response_code, 200) |
| 673 results = self.server.get_attribute( | 676 results = self.server.get_attribute( |
