From 2fb96729a478aa2d39e5225a556c77a3432711ad Mon Sep 17 00:00:00 2001 From: Vincent Robert Date: Fri, 27 Sep 2024 16:24:23 +0200 Subject: [PATCH] update in the package config with Shopware 6.6 --- shopware/fastly-meta/6.6/bin/setup-fastly.sh | 136 ++++++++++++++++++ .../6.6/config/fastly/deliver/default.vcl | 12 ++ .../6.6/config/fastly/fetch/default.vcl | 22 +++ .../6.6/config/fastly/hash/default.vcl | 6 + .../6.6/config/fastly/hit/default.vcl | 11 ++ .../6.6/config/fastly/recv/default.vcl | 75 ++++++++++ .../6.6/config/packages/fastly.yaml | 15 ++ shopware/fastly-meta/6.6/manifest.json | 11 ++ shopware/fastly-meta/6.6/post-install.txt | 2 + 9 files changed, 290 insertions(+) create mode 100755 shopware/fastly-meta/6.6/bin/setup-fastly.sh create mode 100644 shopware/fastly-meta/6.6/config/fastly/deliver/default.vcl create mode 100644 shopware/fastly-meta/6.6/config/fastly/fetch/default.vcl create mode 100644 shopware/fastly-meta/6.6/config/fastly/hash/default.vcl create mode 100644 shopware/fastly-meta/6.6/config/fastly/hit/default.vcl create mode 100644 shopware/fastly-meta/6.6/config/fastly/recv/default.vcl create mode 100644 shopware/fastly-meta/6.6/config/packages/fastly.yaml create mode 100644 shopware/fastly-meta/6.6/manifest.json create mode 100644 shopware/fastly-meta/6.6/post-install.txt diff --git a/shopware/fastly-meta/6.6/bin/setup-fastly.sh b/shopware/fastly-meta/6.6/bin/setup-fastly.sh new file mode 100755 index 00000000..2c2f627f --- /dev/null +++ b/shopware/fastly-meta/6.6/bin/setup-fastly.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +# fail on error +set -e + +if [[ -z "$FASTLY_API_TOKEN" ]]; then + echo "Environment variable FASTLY_API_TOKEN is not set. Skipping" + exit 0 +fi + +if [[ -z "$FASTLY_SERVICE_ID" ]]; then + echo "Environment variable FASTLY_SERVICE_ID is not set. Skipping" + exit 0 +fi + +CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +PROJECT_ROOT="${PROJECT_ROOT:-"$(dirname "$CWD")"}" + +cd "$PROJECT_ROOT" + +created_version=0 + +create_version_if_not_done() { + if [[ "$created_version" == "1" ]]; then + return + fi + + echo "Creating version from active version" + fastly service-version clone --version=active + created_version=1 +} + +get_md5() +{ + if builtin command -v md5 > /dev/null; then + echo "$1" | md5 + elif builtin command -v md5sum > /dev/null ; then + echo "$1" | md5sum | awk '{print $1}' + else + echo "Neither md5 nor md5sum were found in the PATH" + return 1 + fi + + return 0 +} + +install_fastly_cli() { + if [[ -f "/tmp/fastly/fastly" ]]; then + export PATH="/tmp/fastly:$PATH" + return + fi + + mkdir -p /tmp/fastly + + arch=$(uname -m) + os="linux" + version="v10.6.4" + + if [[ "$arch" == "x86_64" ]]; then + arch="amd64" + fi + + if [[ "$OSTYPE" == "darwin"* ]]; then + os="darwin" + fi + + echo "Detected OS: ${os} and architecture: ${arch}" + + file="https://github.com/fastly/cli/releases/download/${version}/fastly_${version}_${os}-${arch}.tar.gz" + + echo "Downloading ${file}" + + curl -L "${file}" | tar xz -C /tmp/fastly/ + export PATH="/tmp/fastly:$PATH" +} + +install_fastly_cli + +# Fastly tries to write into /app on platformsh and this throws an error +export HOME=/tmp + +for sub in ./config/fastly/*; do + if ! find "$sub" -name '*.vcl' | grep . >/dev/null; then + # No VCL files in "$sub"; moving on to the next dir + continue + fi + for vcl in "$sub"/*.vcl; do + trigger=$(basename "$vcl" .vcl) + priority=$(echo "$trigger" | awk -F '.' '$2 ~ /^[0-9]+$/ { print $2 }') + if test -z "$priority"; then + priority="100" + else + trigger=$(basename "$trigger" ".$priority") + fi + vcl_type=$(basename "$sub") + + # For backward compatibility, default VCLs doesn't include trigger in their name + if [[ "$trigger" == "default" ]]; then + name="shopware_${vcl_type}" + else + name="shopware_${vcl_type}_${trigger}" + fi + + echo "Found VCL snippet $trigger of type $vcl_type with priority $priority" + + if fastly vcl snippet describe --version=active "--name=$name" > /dev/null; then + # The snippet exists on remote + localContent=$(cat "$vcl") + localContentMd5=$(get_md5 "$localContent") + + remoteContent=$(fastly vcl snippet describe --version=active "--name=$name" --json | jq -r '.Content') + remoteContentMd5=$(get_md5 "$remoteContent") + + if [[ "$localContentMd5" != "$remoteContentMd5" ]]; then + echo "Snippet ${name} has changed. Updating" + + create_version_if_not_done + + fastly vcl snippet update "--name=$name" "--content=${vcl}" "--type=${vcl_type}" "--priority=${priority}" --version=latest + else + echo "Snippet ${name} is up to date" + fi + else + create_version_if_not_done + + fastly vcl snippet create "--name=$name" "--content=${vcl}" "--type=${vcl_type}" "--priority=${priority}" --version=latest + fi + done +done + + +if [[ "$created_version" == "1" ]]; then + echo "Activating latest version" + + fastly service-version activate --version latest +fi diff --git a/shopware/fastly-meta/6.6/config/fastly/deliver/default.vcl b/shopware/fastly-meta/6.6/config/fastly/deliver/default.vcl new file mode 100644 index 00000000..8e60bce7 --- /dev/null +++ b/shopware/fastly-meta/6.6/config/fastly/deliver/default.vcl @@ -0,0 +1,12 @@ +# Remove the exact PHP Version from the response for more security (e.g. 404 pages) +unset resp.http.x-powered-by; + +# We use fastly.ff.visits_this_service to avoid running this logic on shield nodes. We only need to +# run it on edge nodes +if (fastly.ff.visits_this_service == 0 && resp.http.sw-invalidation-states) { + # invalidation headers are only for internal use + unset resp.http.sw-invalidation-states; + + ## we don't want the client to cache + set resp.http.Cache-Control = "no-cache, private"; +} diff --git a/shopware/fastly-meta/6.6/config/fastly/fetch/default.vcl b/shopware/fastly-meta/6.6/config/fastly/fetch/default.vcl new file mode 100644 index 00000000..6b718b5c --- /dev/null +++ b/shopware/fastly-meta/6.6/config/fastly/fetch/default.vcl @@ -0,0 +1,22 @@ +# Pass immediately if x-pass is present +if (req.http.x-pass) { + return (pass); +} + +# remove set cookie headers to make responses cachable +if (beresp.http.cache-control ~ "public") { + unset beresp.http.set-cookie; +} + +if (beresp.http.Cache-Control ~ "private|no-cache|no-store") { + set req.http.Fastly-Cachetype = "PRIVATE"; + return (pass); +} + +# If the object is coming with no Expires, Surrogate-Control or Cache-Control headers we assume it's a misconfiguration +# and should not cache it. This is to prevent inadventently caching private data +if (!beresp.http.Expires && !beresp.http.Surrogate-Control ~ "max-age" && !beresp.http.Cache-Control ~ "(s-maxage|max-age)") { + # Varnish sets default TTL if none of the headers above are present. If not set we want to make sure we don't cache it + set beresp.ttl = 3600s; + return(pass); +} diff --git a/shopware/fastly-meta/6.6/config/fastly/hash/default.vcl b/shopware/fastly-meta/6.6/config/fastly/hash/default.vcl new file mode 100644 index 00000000..e9e93c5b --- /dev/null +++ b/shopware/fastly-meta/6.6/config/fastly/hash/default.vcl @@ -0,0 +1,6 @@ +# Consider Shopware http cache cookies +if (req.http.cookie:sw-cache-hash) { + set req.hash += req.http.cookie:sw-cache-hash; +} elseif (req.http.cookie:sw-currency) { + set req.hash += req.http.cookie:sw-currency; +} \ No newline at end of file diff --git a/shopware/fastly-meta/6.6/config/fastly/hit/default.vcl b/shopware/fastly-meta/6.6/config/fastly/hit/default.vcl new file mode 100644 index 00000000..0d061925 --- /dev/null +++ b/shopware/fastly-meta/6.6/config/fastly/hit/default.vcl @@ -0,0 +1,11 @@ +if (req.http.cookie:sw-states) { + set req.http.states = req.http.cookie:sw-states; + + if (req.http.states ~ "logged-in" && obj.http.sw-invalidation-states ~ "logged-in" ) { + return (pass); + } + + if (req.http.states ~ "cart-filled" && obj.http.sw-invalidation-states ~ "cart-filled" ) { + return (pass); + } +} \ No newline at end of file diff --git a/shopware/fastly-meta/6.6/config/fastly/recv/default.vcl b/shopware/fastly-meta/6.6/config/fastly/recv/default.vcl new file mode 100644 index 00000000..31f2bad7 --- /dev/null +++ b/shopware/fastly-meta/6.6/config/fastly/recv/default.vcl @@ -0,0 +1,75 @@ +# Don't allow clients to force a pass +if (req.restarts == 0) { + unset req.http.x-pass; +} + +# Enable Fastly authentification for single purges +set req.http.Fastly-Purge-Requires-Auth = "1"; + +# Mitigate httpoxy application vulnerability, see: https://httpoxy.org/ +unset req.http.Proxy; + +# Strip query strings only needed by browser javascript. Customize to used tags. +if (req.url != req.url.path) { + set req.url = querystring.filter(req.url, + "pk_campaign" + querystring.filtersep() + + "piwik_campaign" + querystring.filtersep() + + "pk_kwd" + querystring.filtersep() + + "piwik_kwd" + querystring.filtersep() + + "pk_keyword" + querystring.filtersep() + + "pixelId" + querystring.filtersep() + + "kwid" + querystring.filtersep() + + "kw" + querystring.filtersep() + + "adid" + querystring.filtersep() + + "chl" + querystring.filtersep() + + "dv" + querystring.filtersep() + + "nk" + querystring.filtersep() + + "pa" + querystring.filtersep() + + "camid" + querystring.filtersep() + + "adgid" + querystring.filtersep() + + "cx" + querystring.filtersep() + + "ie" + querystring.filtersep() + + "cof" + querystring.filtersep() + + "siteurl" + querystring.filtersep() + + "utm_source" + querystring.filtersep() + + "utm_medium" + querystring.filtersep() + + "utm_campaign" + querystring.filtersep() + + "_ga" + querystring.filtersep() + + "gclid" + ); +} + +# Normalize query arguments +set req.url = querystring.sort(req.url); + +# Make sure that the client ip is forward to the client. +if (req.http.x-forwarded-for) { + set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + req.http.Fastly-Client-IP; +} else { + set req.http.X-Forwarded-For = req.http.Fastly-Client-IP; +} + +# Don't cache Authenticate & Authorization +if (req.http.Authenticate || req.http.Authorization) { + set req.http.x-pass = "1"; +} + +# Always pass these paths directly to php without caching +# Note: virtual URLs might bypass this rule (e.g. /en/checkout) +if (req.url.path ~ "^/(checkout|account|admin|api|csrf)(/.*)?$") { + set req.http.x-pass = "1"; +} + +# Excludes requests from caching which contain the "affiliateCode" query parameter. +# Otherwise requests which are already cached but now +# contain the "affiliateCode" query parameter are loaded from cache. +# AffiliateTrackingListener::checkAffiliateTracking() would not be called +# and the affiliate code is not stored properly in the session. +if (std.strlen(querystring.get(req.url, "affiliateCode")) > 0) { + set req.http.x-pass = "1"; +} + +# Disable stale_while_revalidate feature on SHIELD node to avoid caching issue when both soft-purges and shieding are used. +if (fastly.ff.visits_this_service > 0) { + set req.max_stale_while_revalidate = 0s; +} diff --git a/shopware/fastly-meta/6.6/config/packages/fastly.yaml b/shopware/fastly-meta/6.6/config/packages/fastly.yaml new file mode 100644 index 00000000..a60d99a9 --- /dev/null +++ b/shopware/fastly-meta/6.6/config/packages/fastly.yaml @@ -0,0 +1,15 @@ +when@prod: + shopware: + # Uncomment all to enable soft purge + http_cache: + # Allow to serve the out-dated cache for 300 seconds + # stale_while_revalidate: 300 + # Allow to serve the out-dated cache for an hour if the origin server is offline + # stale_if_error: 3600 + reverse_proxy: + enabled: true + fastly: + enabled: true + api_key: '%env(FASTLY_API_TOKEN)%' + service_id: '%env(FASTLY_SERVICE_ID)%' + soft_purge: '1' diff --git a/shopware/fastly-meta/6.6/manifest.json b/shopware/fastly-meta/6.6/manifest.json new file mode 100644 index 00000000..26dffc5f --- /dev/null +++ b/shopware/fastly-meta/6.6/manifest.json @@ -0,0 +1,11 @@ +{ + "aliases": ["fastly"], + "copy-from-recipe": { + "config/": "%CONFIG_DIR%/", + "bin/": "%BIN_DIR%/" + }, + "env": { + "FASTLY_API_TOKEN": "EXAMPLE_TOKEN", + "FASTLY_SERVICE_ID": "EXAMPLE_SERVICE" + } +} diff --git a/shopware/fastly-meta/6.6/post-install.txt b/shopware/fastly-meta/6.6/post-install.txt new file mode 100644 index 00000000..60560a56 --- /dev/null +++ b/shopware/fastly-meta/6.6/post-install.txt @@ -0,0 +1,2 @@ + * Add your FASTLY_API_TOKEN and FASTLY_SERVICE_ID into .env + * Run setup-fastly.sh to deploy the Fastly vcl files