From 957cc9e9083292347b8b9c6d976b8b150bd69f48 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Tue, 20 Feb 2024 05:03:13 +0100 Subject: [PATCH 1/5] feat:#19 added nginx rate limit and cache --- reverseproxy.conf | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/reverseproxy.conf b/reverseproxy.conf index 383aeeb..8be866b 100644 --- a/reverseproxy.conf +++ b/reverseproxy.conf @@ -21,6 +21,8 @@ http { map $request_method $cache_bypass { default 0; POST 1; + PUT 1; + DELETE 1; } client_body_temp_path /opt/bitnami/nginx/tmp/client_temp; @@ -36,6 +38,31 @@ http { proxy_cache_use_stale timeout updating; proxy_ignore_headers Cache-Control Expires Set-Cookie; + proxy_buffering on; + proxy_buffers 8 16k; + proxy_buffer_size 16k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 64k; + proxy_max_temp_file_size 1024m; + + geo $admin { + default 1; + 10.0.0.0/8 0; # Private Network + 192.168.0.0/24 0; # Localhost Network + 141.57.0.0/16 0; # HTWK Leipzig Network + 172.18.0.0/24 0; # Docker Internal Network + } + + map $admin $limit_key { + 0 ""; + 1 $binary_remote_addr; + } + + # Limit the number of requests per IP + limit_req_zone $limit_key zone=feed:20m rate=10r/m; + limit_req_zone $limit_key zone=createFeed:10m rate=1r/m; + limit_req_zone $limit_key zone=modules:10m rate=3r/m; + server { listen 80; server_name frontend; @@ -65,10 +92,89 @@ http { proxy_cache_lock on; proxy_cache_use_stale timeout updating; add_header X-Proxy-Cache $upstream_cache_status; + limit_req zone=modules burst=5 nodelay; + } + + location /api/rooms { + proxy_pass http://htwkalender-backend:8090; + client_max_body_size 20m; + proxy_connect_timeout 600s; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + proxy_cache_bypass 0; + proxy_no_cache 0; + proxy_cache mcache; # mcache=RAM + proxy_cache_valid 200 301 302 30m; + proxy_cache_valid 403 404 5m; + proxy_cache_lock on; + proxy_cache_use_stale timeout updating; + add_header X-Proxy-Cache $upstream_cache_status; + limit_req zone=modules burst=5 nodelay; + } + + location /api/schedule { + proxy_pass http://htwkalender-backend:8090; + client_max_body_size 20m; + proxy_connect_timeout 600s; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + proxy_cache_bypass 0; + proxy_no_cache 0; + proxy_cache mcache; # mcache=RAM + proxy_cache_valid 200 301 302 30m; + proxy_cache_valid 403 404 5m; + proxy_cache_lock on; + proxy_cache_use_stale timeout updating; + add_header X-Proxy-Cache $upstream_cache_status; + limit_req zone=modules burst=5 nodelay; + } + + location /api/courses { + proxy_pass http://htwkalender-backend:8090; + client_max_body_size 20m; + proxy_connect_timeout 600s; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + proxy_cache_bypass 0; + proxy_no_cache 0; + proxy_cache mcache; # mcache=RAM + proxy_cache_valid 200 301 302 30m; + proxy_cache_valid 403 404 5m; + proxy_cache_lock on; + proxy_cache_use_stale timeout updating; + add_header X-Proxy-Cache $upstream_cache_status; + limit_req zone=modules burst=5 nodelay; + } + + location /api/feed { + proxy_pass http://htwkalender-backend:8090; + client_max_body_size 2m; + proxy_connect_timeout 600s; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + limit_req zone=feed burst=10 nodelay; + } + + location /api/createFeed { + proxy_pass http://htwkalender-backend:8090; + client_max_body_size 2m; + proxy_connect_timeout 600s; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + limit_req zone=createFeed burst=1 nodelay; } location /_ { proxy_pass http://htwkalender-backend:8090; + # if user is not 0 in admin list, return 404 + if ($admin) { + return 404 "Not Found"; + } } location / { From 475b5f9ce0c251f0083cb11c26dfc97e5b716d0c Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Wed, 21 Feb 2024 01:15:06 +0100 Subject: [PATCH 2/5] feat:#19 added old dev docker setup for local development --- backend/Dockerfile | 23 +++++++++++++++++++++++ docker-compose.yml | 6 +++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 415fce4..0e53b2e 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -29,3 +29,26 @@ COPY --chown=$USER:$USER --from=build /htwkalender ./ EXPOSE 8090 ENTRYPOINT ["./htwkalender", "serve"] + + +FROM golang:1.21.6 AS dev + +# Set the Current Working Directory inside the container +WORKDIR /htwkalender + +# Copy go mod and sum files +COPY go.mod go.sum ./ +RUN go mod download + +# Copy the source from the current directory to the Working Directory inside the container +COPY *.go ./ +COPY . . + +# Build the Go app +RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender + +# Expose port 8090 to the outside world +EXPOSE 8090 + +# Entry point +ENTRYPOINT ["./htwkalender", "serve"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index cffeaa5..e7ff1a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,13 +5,13 @@ services: build: dockerfile: Dockerfile context: ./backend - target: prod + target: dev # prod command: "--http=0.0.0.0:8090 --dir=/htwkalender/data/pb_data" - # open port 8090 ports: - "8090:8090" volumes: - - pb_data:/htwkalender/data + - pb_data:/htwkalender/data # for production with volume + # - ./backend/pb_data:/pb_data # for development with bind mount from project directory htwkalender-frontend: build: From cd7b00f997ac85a9d74328d2d8add6f220e3c67a Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Wed, 21 Feb 2024 02:40:18 +0100 Subject: [PATCH 3/5] feat:#19 added toast for too many requests --- frontend/src/api/createFeed.ts | 32 ++++++++++++----------- frontend/src/components/RenameModules.vue | 23 +++++++++++++--- frontend/src/i18n/translations/de.json | 4 ++- frontend/src/i18n/translations/en.json | 4 ++- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/frontend/src/api/createFeed.ts b/frontend/src/api/createFeed.ts index 9c4c4aa..2c89049 100644 --- a/frontend/src/api/createFeed.ts +++ b/frontend/src/api/createFeed.ts @@ -1,22 +1,24 @@ import { Module } from "../model/module.ts"; export async function createIndividualFeed(modules: Module[]): Promise { - let token = ""; - - await fetch("/api/createFeed", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(modules), - }) - .then((response) => { - return response.json(); - }) - .then((response) => { - token = response; + try { + const response = await fetch("/api/createFeed", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(modules), }); - return token; + + if (response.status === 429 || response.status === 500 || response.status != 200) { + return Promise.reject(response.statusText); + } + + return await response.json(); + } catch (error) { + // Catch possible errors and return an unfilled promise + return Promise.reject(error); + } } interface FeedResponse { diff --git a/frontend/src/components/RenameModules.vue b/frontend/src/components/RenameModules.vue index df6361b..17f2eee 100644 --- a/frontend/src/components/RenameModules.vue +++ b/frontend/src/components/RenameModules.vue @@ -8,6 +8,7 @@ import ModuleTemplateDialog from "./ModuleTemplateDialog.vue"; import { onlyWhitespace } from "../helpers/strings.ts"; import { useI18n } from "vue-i18n"; import { Module } from "@/model/module.ts"; +import { useToast } from "primevue/usetoast"; const { t } = useI18n({ useScope: "global" }); const store = moduleStore(); @@ -33,10 +34,26 @@ const columns = computed(() => [ { field: "Reminder", header: t("renameModules.reminder") }, ]); +const toast = useToast(); + async function finalStep() { - const token: string = await createIndividualFeed(store.getAllModules()); - tokenStore().setToken(token); - await router.push("/calendar-link"); + const createFeed: Promise= createIndividualFeed(store.getAllModules()); + + // Check if createFeed Promise is resolved + createFeed.then(async (token: string) => { + tokenStore().setToken(token); + await router.push("/calendar-link"); + }); + + // if createFeed Promise is rejected + createFeed.catch(() => { + toast.add({ + severity: "error", + summary: t("renameModules.error"), + detail: t("renameModules.TooManyRequests"), + life: 3000, + }); + }); } diff --git a/frontend/src/i18n/translations/de.json b/frontend/src/i18n/translations/de.json index cef6dc4..f073849 100644 --- a/frontend/src/i18n/translations/de.json +++ b/frontend/src/i18n/translations/de.json @@ -110,7 +110,9 @@ "reminder": "Erinnerung", "enableAllNotifications": "Alle Benachrichtigungen aktivieren", "subTitle": "Konfigurieren Sie die ausgewählten Module nach Ihren Wünschen.", - "nextStep": "Speichern" + "nextStep": "Speichern", + "error": "Fehler", + "TooManyRequests": "Zu viele Anfragen um einen Kalender zu erstellen. Bitte versuchen Sie es später erneut." }, "moduleTemplateDialog": { "explanationOne": "Hier können Module nach Wunsch umbenannt werden, welche dann als Anzeigename im Kalender dargestellt werden.", diff --git a/frontend/src/i18n/translations/en.json b/frontend/src/i18n/translations/en.json index ac33f7a..d082f39 100644 --- a/frontend/src/i18n/translations/en.json +++ b/frontend/src/i18n/translations/en.json @@ -110,7 +110,9 @@ "reminder": "reminder", "enableAllNotifications": "enable all notifications", "subTitle": "configure your selected modules to your liking", - "nextStep": "save" + "nextStep": "save", + "error": "error", + "TooManyRequests": "too many requests for creating a calendar in a short time" }, "moduleTemplateDialog": { "explanationOne": "Here you can rename your modules to your liking. This will be the name of the event in your calendar.", From 8f17671bed1eeea483185901be4db3200d28c73d Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Wed, 21 Feb 2024 02:40:52 +0100 Subject: [PATCH 4/5] fix:#19 re-added src mount for frontend development --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index e7ff1a0..6e3e589 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,8 @@ services: # open port 8000 ports: - "8000:8000" + volumes: + - ./frontend/src:/app/src rproxy: image: bitnami/nginx:1.25 From b481f5d94b1a639e52e18ebc6f0e6f0064d28f85 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Wed, 21 Feb 2024 02:41:30 +0100 Subject: [PATCH 5/5] fix:#19 updated limit req status for createFeed --- reverseproxy.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reverseproxy.conf b/reverseproxy.conf index 8be866b..ae07c4b 100644 --- a/reverseproxy.conf +++ b/reverseproxy.conf @@ -160,13 +160,15 @@ http { } location /api/createFeed { + limit_req zone=createFeed nodelay; + # return limit request error + limit_req_status 429; proxy_pass http://htwkalender-backend:8090; client_max_body_size 2m; proxy_connect_timeout 600s; proxy_read_timeout 600s; proxy_send_timeout 600s; send_timeout 600s; - limit_req zone=createFeed burst=1 nodelay; } location /_ {