Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

(feat)deprectation: add deprecation headers #540

Merged
merged 4 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions httpobs/website/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
from httpobs.website.decorators import add_response_headers, sanitized_api_response
from httpobs.website.decorators import (
add_response_headers,
add_sunset_headers,
check_for_deprecation_override_header,
sanitized_api_response,
)

__all__ = ['add_response_headers', 'sanitized_api_response']
__all__ = [
'add_response_headers',
'sanitized_api_response',
'add_sunset_headers',
'check_for_deprecation_override_header',
]
23 changes: 22 additions & 1 deletion httpobs/website/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
from httpobs.conf import API_ALLOW_VERBOSE_STATS_FROM_PUBLIC, API_COOLDOWN, DEVELOPMENT_MODE
from httpobs.scanner import scan
from httpobs.scanner.grader import GRADES, get_score_description
from httpobs.website import add_response_headers, sanitized_api_response
from httpobs.website import (
add_response_headers,
add_sunset_headers,
check_for_deprecation_override_header,
sanitized_api_response,
)
from httpobs.website.utils import valid_hostname

api = Blueprint('api', __name__)
Expand All @@ -20,6 +25,8 @@


@api.route('/api/v1/analyze', methods=['GET', 'OPTIONS', 'POST'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
@sanitized_api_response
def api_post_scan_hostname():
Expand Down Expand Up @@ -119,6 +126,8 @@ def api_post_scan_hostname():

# TODO: Deprecate this and replace with __stats__ once website is updated
@api.route('/api/v1/getGradeDistribution', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
def api_get_grade_totals():
totals = database.select_star_from('grade_distribution')
Expand All @@ -130,6 +139,8 @@ def api_get_grade_totals():


@api.route('/api/v1/getHostHistory', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
def api_get_host_history():
# Get the hostname
Expand Down Expand Up @@ -163,6 +174,8 @@ def api_get_host_history():


@api.route('/api/v1/getRecentScans', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
def api_get_recent_scans():
try:
Expand All @@ -184,6 +197,8 @@ def api_get_recent_scans():

# TODO: Deprecate
@api.route('/api/v1/getScannerStates', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
def api_get_scanner_states():
stats = database.select_scan_scanner_statistics(verbose=False)
Expand All @@ -192,6 +207,8 @@ def api_get_scanner_states():


@api.route('/api/v1/__stats__', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
def api_get_scanner_stats():
pretty = True if request.args.get('pretty', '').lower() == 'true' else False
Expand Down Expand Up @@ -259,6 +276,8 @@ def api_get_scanner_stats():


@api.route('/api/v1/getScanResults', methods=['GET', 'OPTIONS'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers(cors=True)
@sanitized_api_response
def api_get_scan_results():
Expand Down Expand Up @@ -288,6 +307,8 @@ def api_get_scan_results():


@api.route('/contribute.json', methods=['GET'])
@add_sunset_headers()
@check_for_deprecation_override_header
@add_response_headers()
def contribute_json():
__dirname = os.path.abspath(os.path.dirname(__file__))
Expand Down
49 changes: 49 additions & 0 deletions httpobs/website/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,55 @@
from flask import jsonify, make_response, request


def add_sunset_headers():
"""
Adds a "Sunset" header to the response
"""

def decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
resp = make_response(fn(*args, **kwargs))
resp.headers['Sunset'] = 'Thu, 31 Oct 2024 23:59:59 GMT'
return resp

return wrapper

return decorator


def check_for_deprecation_override_header(fn):
"""
Checks for the "X-Deprecation-Override" header and sets the response accordingly:
- If the header is set to "yes", it will return the response as normal
- If the header is set to anything else, it will return a 410 Gone response
"""

@wraps(fn)
def wrapper(*args, **kwargs):
if request.headers.get('X-Deprecation-Override', 'no').lower() == 'yes':
return fn(*args, **kwargs)
else:
return make_response(
"""
This API has been deprecated and is no longer available.
Please use https://observatory-api.mdn.mozilla.net/.
For details about the new endpint, see
https://github.com/mdn/mdn-http-observatory/blob/main/README.md#post-apiv2scan.

If you really want to continue with this endpoint for now,
please add a header to your request in the form of

X-Deprecation-Override: yes

Be aware that this API will go away without further warning on Oct 31, 2024.
""",
410,
)

return wrapper


def add_response_headers(headers=None, default_headers=None, cors=False):
"""
Adds a bunch of headers to the Flask responses
Expand Down
3 changes: 2 additions & 1 deletion httpobs/website/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from flask import Flask

from httpobs.conf import API_PORT, API_PROPAGATE_EXCEPTIONS, DEVELOPMENT_MODE
from httpobs.website import add_response_headers
from httpobs.website import add_response_headers, add_sunset_headers
from httpobs.website.api import api
from httpobs.website.monitoring import monitoring_api

Expand All @@ -21,6 +21,7 @@ def __exit_with(msg: str) -> None:


@app.route('/')
@add_sunset_headers()
@add_response_headers()
def main() -> str:
return 'Welcome to the HTTP Observatory!'
Expand Down
Loading