From 6c0ba9c3a5fdcf681f8c726d831b368ed8d70c8f Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Wed, 27 Jan 2021 16:09:43 +0100 Subject: [PATCH] Add gzip and etags #100 --- project/__init__.py | 4 ++++ project/api/dump/resources.py | 4 ++-- project/api/event/resources.py | 10 +++++----- project/api/event_category/resources.py | 4 ++-- project/api/event_date/resources.py | 8 ++++---- project/api/event_reference/resources.py | 4 ++-- project/api/image/resources.py | 4 ++-- project/api/location/resources.py | 4 ++-- project/api/organization/resources.py | 18 +++++++++--------- project/api/organizer/resources.py | 4 ++-- project/api/place/resources.py | 4 ++-- project/api/resources.py | 17 +++++++++++++++++ requirements.txt | 1 + 13 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 project/api/resources.py diff --git a/project/__init__.py b/project/__init__.py index b7e720d..3c87974 100644 --- a/project/__init__.py +++ b/project/__init__.py @@ -15,6 +15,7 @@ from flask_restful import Api from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin from flask_apispec.extension import FlaskApiSpec +from flask_gzip import Gzip # Create app app = Flask(__name__) @@ -39,6 +40,9 @@ app.config["SECURITY_PASSWORD_SALT"] = os.environ.get( "SECURITY_PASSWORD_SALT", "146585145368132386173505678016728509634" ) +# Gzip +gzip = Gzip(app) + # Cache pathes cache_env = os.environ.get("CACHE_PATH", "tmp") cache_path = ( diff --git a/project/api/dump/resources.py b/project/api/dump/resources.py index 00a0334..7e5d284 100644 --- a/project/api/dump/resources.py +++ b/project/api/dump/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.schemas import NoneSchema from project.api.dump.schemas import DumpResponseSchema -class DumpResource(MethodResource): +class DumpResource(BaseResource): @doc( summary="Dump model definition", description="Always returns 404 because the endpoint is just for response definition of the dump data file. Go to the developers page to learn how to download the dump data file.", diff --git a/project/api/event/resources.py b/project/api/event/resources.py index 075fb2e..99bbec1 100644 --- a/project/api/event/resources.py +++ b/project/api/event/resources.py @@ -1,6 +1,6 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc, use_kwargs -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.event.schemas import ( EventSchema, EventListRequestSchema, @@ -18,7 +18,7 @@ from project.services.event_search import EventSearchParams from sqlalchemy.orm import lazyload, load_only -class EventListResource(MethodResource): +class EventListResource(BaseResource): @doc(summary="List events", tags=["Events"]) @use_kwargs(EventListRequestSchema, location=("query")) @marshal_with(EventListResponseSchema) @@ -27,14 +27,14 @@ class EventListResource(MethodResource): return pagination -class EventResource(MethodResource): +class EventResource(BaseResource): @doc(summary="Get event", tags=["Events"]) @marshal_with(EventSchema) def get(self, id): return get_event_with_details_or_404(id) -class EventDatesResource(MethodResource): +class EventDatesResource(BaseResource): @doc(summary="List dates for event", tags=["Events", "Event Dates"]) @use_kwargs(EventDateListRequestSchema, location=("query")) @marshal_with(EventDateListResponseSchema) @@ -48,7 +48,7 @@ class EventDatesResource(MethodResource): ) -class EventSearchResource(MethodResource): +class EventSearchResource(BaseResource): @doc(summary="Search for events", tags=["Events"]) @use_kwargs(EventSearchRequestSchema, location=("query")) @marshal_with(EventSearchResponseSchema) diff --git a/project/api/event_category/resources.py b/project/api/event_category/resources.py index 272e0be..d0ca029 100644 --- a/project/api/event_category/resources.py +++ b/project/api/event_category/resources.py @@ -1,6 +1,6 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc, use_kwargs -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.event_category.schemas import ( EventCategoryListRequestSchema, EventCategoryListResponseSchema, @@ -8,7 +8,7 @@ from project.api.event_category.schemas import ( from project.models import EventCategory -class EventCategoryListResource(MethodResource): +class EventCategoryListResource(BaseResource): @doc(summary="List event categories", tags=["Event Categories"]) @use_kwargs(EventCategoryListRequestSchema, location=("query")) @marshal_with(EventCategoryListResponseSchema) diff --git a/project/api/event_date/resources.py b/project/api/event_date/resources.py index 878d4c4..1f809e3 100644 --- a/project/api/event_date/resources.py +++ b/project/api/event_date/resources.py @@ -1,6 +1,6 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc, use_kwargs -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.event_date.schemas import ( EventDateSchema, EventDateListRequestSchema, @@ -14,7 +14,7 @@ from project.services.event_search import EventSearchParams from sqlalchemy.orm import defaultload, lazyload -class EventDateListResource(MethodResource): +class EventDateListResource(BaseResource): @doc(summary="List event dates", tags=["Event Dates"]) @use_kwargs(EventDateListRequestSchema, location=("query")) @marshal_with(EventDateListResponseSchema) @@ -23,7 +23,7 @@ class EventDateListResource(MethodResource): return pagination -class EventDateResource(MethodResource): +class EventDateResource(BaseResource): @doc(summary="Get event date", tags=["Event Dates"]) @marshal_with(EventDateSchema) def get(self, id): @@ -32,7 +32,7 @@ class EventDateResource(MethodResource): ).get_or_404(id) -class EventDateSearchResource(MethodResource): +class EventDateSearchResource(BaseResource): @doc(summary="Search for event dates", tags=["Event Dates"]) @use_kwargs(EventDateSearchRequestSchema, location=("query")) @marshal_with(EventDateSearchResponseSchema) diff --git a/project/api/event_reference/resources.py b/project/api/event_reference/resources.py index 2326151..adc5d79 100644 --- a/project/api/event_reference/resources.py +++ b/project/api/event_reference/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.event_reference.schemas import EventReferenceSchema from project.models import EventReference -class EventReferenceResource(MethodResource): +class EventReferenceResource(BaseResource): @doc(summary="Get event reference", tags=["Event References"]) @marshal_with(EventReferenceSchema) def get(self, id): diff --git a/project/api/image/resources.py b/project/api/image/resources.py index b8e6ab9..25cb5b6 100644 --- a/project/api/image/resources.py +++ b/project/api/image/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.image.schemas import ImageSchema from project.models import Image -class ImageResource(MethodResource): +class ImageResource(BaseResource): @doc(summary="Get image", tags=["Images"]) @marshal_with(ImageSchema) def get(self, id): diff --git a/project/api/location/resources.py b/project/api/location/resources.py index 101d771..2e3d2e9 100644 --- a/project/api/location/resources.py +++ b/project/api/location/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.location.schemas import LocationSchema from project.models import Location -class LocationResource(MethodResource): +class LocationResource(BaseResource): @doc(summary="Get location", tags=["Locations"]) @marshal_with(LocationSchema) def get(self, id): diff --git a/project/api/organization/resources.py b/project/api/organization/resources.py index 698d7c5..fa8dea6 100644 --- a/project/api/organization/resources.py +++ b/project/api/organization/resources.py @@ -1,6 +1,6 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc, use_kwargs -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.organization.schemas import ( OrganizationSchema, OrganizationListRequestSchema, @@ -37,14 +37,14 @@ from project.services.admin_unit import ( ) -class OrganizationResource(MethodResource): +class OrganizationResource(BaseResource): @doc(summary="Get organization", tags=["Organizations"]) @marshal_with(OrganizationSchema) def get(self, id): return AdminUnit.query.get_or_404(id) -class OrganizationEventDateSearchResource(MethodResource): +class OrganizationEventDateSearchResource(BaseResource): @doc( summary="Search for event dates of organization", description="Includes events that organization is referencing.", @@ -63,7 +63,7 @@ class OrganizationEventDateSearchResource(MethodResource): return pagination -class OrganizationEventSearchResource(MethodResource): +class OrganizationEventSearchResource(BaseResource): @doc(summary="Search for events of organization", tags=["Organizations", "Events"]) @use_kwargs(EventSearchRequestSchema, location=("query")) @marshal_with(EventSearchResponseSchema) @@ -78,7 +78,7 @@ class OrganizationEventSearchResource(MethodResource): return pagination -class OrganizationListResource(MethodResource): +class OrganizationListResource(BaseResource): @doc(summary="List organizations", tags=["Organizations"]) @use_kwargs(OrganizationListRequestSchema, location=("query")) @marshal_with(OrganizationListResponseSchema) @@ -88,7 +88,7 @@ class OrganizationListResource(MethodResource): return pagination -class OrganizationOrganizerListResource(MethodResource): +class OrganizationOrganizerListResource(BaseResource): @doc( summary="List organizers of organization", tags=["Organizations", "Organizers"] ) @@ -102,7 +102,7 @@ class OrganizationOrganizerListResource(MethodResource): return pagination -class OrganizationPlaceListResource(MethodResource): +class OrganizationPlaceListResource(BaseResource): @doc(summary="List places of organization", tags=["Organizations", "Places"]) @use_kwargs(PlaceListRequestSchema, location=("query")) @marshal_with(PlaceListResponseSchema) @@ -114,7 +114,7 @@ class OrganizationPlaceListResource(MethodResource): return pagination -class OrganizationIncomingEventReferenceListResource(MethodResource): +class OrganizationIncomingEventReferenceListResource(BaseResource): @doc( summary="List incoming event references of organization", tags=["Organizations", "Event References"], @@ -128,7 +128,7 @@ class OrganizationIncomingEventReferenceListResource(MethodResource): return pagination -class OrganizationOutgoingEventReferenceListResource(MethodResource): +class OrganizationOutgoingEventReferenceListResource(BaseResource): @doc( summary="List outgoing event references of organization", tags=["Organizations", "Event References"], diff --git a/project/api/organizer/resources.py b/project/api/organizer/resources.py index 56d8170..c917f91 100644 --- a/project/api/organizer/resources.py +++ b/project/api/organizer/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.organizer.schemas import OrganizerSchema from project.models import EventOrganizer -class OrganizerResource(MethodResource): +class OrganizerResource(BaseResource): @doc(summary="Get organizer", tags=["Organizers"]) @marshal_with(OrganizerSchema) def get(self, id): diff --git a/project/api/place/resources.py b/project/api/place/resources.py index 6efb627..912151b 100644 --- a/project/api/place/resources.py +++ b/project/api/place/resources.py @@ -1,11 +1,11 @@ from project.api import add_api_resource from flask_apispec import marshal_with, doc -from flask_apispec.views import MethodResource +from project.api.resources import BaseResource from project.api.place.schemas import PlaceSchema from project.models import EventPlace -class PlaceResource(MethodResource): +class PlaceResource(BaseResource): @doc(summary="Get place", tags=["Places"]) @marshal_with(PlaceSchema) def get(self, id): diff --git a/project/api/resources.py b/project/api/resources.py new file mode 100644 index 0000000..49cba35 --- /dev/null +++ b/project/api/resources.py @@ -0,0 +1,17 @@ +from flask import request +from flask_apispec.views import MethodResource +from functools import wraps + + +def etag_cache(func): + @wraps(func) + def wrapper(*args, **kwargs): + response = func(*args, **kwargs) + response.add_etag() + return response.make_conditional(request) + + return wrapper + + +class BaseResource(MethodResource): + decorators = [etag_cache] diff --git a/requirements.txt b/requirements.txt index ec071a0..e6f74d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,6 +31,7 @@ Flask-BabelEx==0.9.4 Flask-Bootstrap==3.3.7.1 Flask-Cors==3.0.9 Flask-Dance==3.2.0 +Flask-gzip==0.2 Flask-Login==0.5.0 Flask-Mail==0.9.1 flask-marshmallow==0.14.0