|
26 | 26 | from uuid import uuid1 |
27 | 27 |
|
28 | 28 | import flask |
| 29 | +from flask import abort |
29 | 30 | from flask import request |
30 | 31 | from flask import Blueprint |
31 | 32 |
|
@@ -369,7 +370,9 @@ def create_api_blueprint(self, name, model, methods=READONLY_METHODS, |
369 | 370 | serializer=None, deserializer=None, |
370 | 371 | includes=None, allow_to_many_replacement=False, |
371 | 372 | allow_delete_from_to_many_relationships=False, |
372 | | - allow_client_generated_ids=False): |
| 373 | + allow_client_generated_ids=False, |
| 374 | + hide_disallowed_endpoints=False, |
| 375 | + hide_unauthenticated_endpoints=False): |
373 | 376 | """Creates and returns a ReSTful API interface as a blueprint, but does |
374 | 377 | not register it on any :class:`flask.Flask` application. |
375 | 378 |
|
@@ -565,6 +568,19 @@ def create_api_blueprint(self, name, model, methods=READONLY_METHODS, |
565 | 568 | this be a UUID. This is ``False`` by default. For more information, see |
566 | 569 | :ref:`creating`. |
567 | 570 |
|
| 571 | + If `hide_disallowed_endpoints` is ``True``, requests to |
| 572 | + disallowed methods (that is, methods not specified in |
| 573 | + `methods`), which would normally yield a :http:statuscode:`405` |
| 574 | + response, will yield a :http:statuscode:`404` response |
| 575 | + instead. If `hide_unauthenticated_endpoints` is ``True``, |
| 576 | + requests to endpoints for which the user has not authenticated |
| 577 | + (as specified in the `authentication_required_for` and |
| 578 | + `authentication_function` arguments) will also be masked by |
| 579 | + :http:statuscode:`404` instead of :http:statuscode:`403`. These |
| 580 | + options may be used as a simple form of "security through |
| 581 | + obscurity", by (slightly) hindering users from discovering where |
| 582 | + an endpoint exists. |
| 583 | +
|
568 | 584 | """ |
569 | 585 | # Perform some sanity checks on the provided keyword arguments. |
570 | 586 | if only is not None and exclude is not None: |
@@ -727,9 +743,20 @@ def create_api_blueprint(self, name, model, methods=READONLY_METHODS, |
727 | 743 | blueprint.add_url_rule(eval_endpoint, methods=eval_methods, |
728 | 744 | view_func=eval_api_view) |
729 | 745 |
|
| 746 | + if hide_disallowed_endpoints: |
| 747 | + @blueprint.errorhandler(405) |
| 748 | + def return_404(error): |
| 749 | + abort(404) |
| 750 | + |
| 751 | + if hide_unauthenticated_endpoints: |
| 752 | + @blueprint.errorhandler(403) |
| 753 | + def return_404(error): |
| 754 | + abort(404) |
| 755 | + |
730 | 756 | # Finally, record that this APIManager instance has created an API for |
731 | 757 | # the specified model. |
732 | 758 | self.created_apis_for[model] = APIInfo(collection_name, blueprint.name) |
| 759 | + |
733 | 760 | return blueprint |
734 | 761 |
|
735 | 762 | def create_api(self, *args, **kw): |
|
0 commit comments