{
  "description": "Set of VCLs required to integrate Datadome services. Please note for full functionality Fastly support needs to enable proper handling of POST requests. Do not enable unless this has been done.",
  "id": "datadome_integration",
  "name": "DataDome Bot Detection integration",
  "properties": [
    {
      "label": "API Key",
      "name": "datadome_api_key",
      "type": "string",
      "description": "API Key",
      "required": true
    }, {
      "label": "Exclusion regex",
      "name": "datadome_exclusion_ext",
      "type": "string",
      "description": "The regex that will be applied to req.url.path",
      "default": "(?i)\\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map)$",
      "required": true
    }, {
      "label": "Connection timeout",
      "name": "datadome_connect_timeout",
      "type": "integer",
      "description": "How long to wait for a timeout in milliseconds.",
      "default": "300",
      "required": true
    }, {
      "label": "First byte timeout",
      "name": "datadome_first_byte_timeout",
      "type": "integer",
      "description": "How long to wait for the first byte in milliseconds.",
      "default": "100",
      "required": true
    }, {
      "label": "Between bytes timeout",
      "name": "datadome_between_bytes_timeout",
      "type": "integer",
      "description": "How long to wait between bytes in milliseconds.",
      "default": "100",
      "required": true
    }, {
      "label": "Logging Endpoint for Debugging (Optional)",
      "name": "logging_endpoint",
      "type": "string",
      "description": "Name of a logging endpoint that has been already set up in Fastly.",
      "required": false
    }
  ],
  "test": {
    "origins": [
      "https://httpbin.org"
    ],
    "reqUrl": "/sourcePath"
  },
  "vcl": [
    {
      "priority": 7,
      "template": "sub set_origin_header {\n  if (req.backend.is_origin) {\n    if (req.backend == datadome) {\n        # Remove all unexpected headers\n        header.filter_except(bereq, \"x-datadome-params\", \"accept-charset\", \"accept-language\", \"x-requested-with\", \"x-fl-productid\", \"x-flapi-session-id\", \"fastly-orig-accept-encoding\", \"cache-control\", \"client-id\", \"connection\", \"pragma\", \"accept\", \"headers-list\", \"host\", \"origin\", \"server-hostname\", \"server-name\", \"x-forwarded-for\", \"user-agent\", \"referer\", \"request\", \"content-type\", \"from\", \"true-client-ip\", \"via\", \"x-real-ip\", \"sec-ch-device-memory\", \"sec-ch-ua\", \"sec-ch-ua-arch\", \"sec-ch-ua-full-version-list\", \"sec-ch-ua-mobile\", \"sec-ch-ua-model\", \"sec-ch-ua-platform\", \"sec-fetch-dest\", \"sec-fetch-mode\", \"sec-fetch-site\", \"sec-fetch-user\");\n        set bereq.http.x-datadome-params:key = \"{{datadome_api_key}}\";\n        set bereq.http.x-datadome-params:requestmodulename = \"FastlyMagento\";\n        set bereq.http.x-datadome-params:moduleversion = \"2.19.4\";\n        set bereq.http.x-datadome-params:timerequest = time.start.usec;\n        set bereq.http.x-datadome-params:servername = server.identity;\n        set bereq.http.x-datadome-params:serverregion = server.region;\n        set bereq.http.x-datadome-params:ip = urlencode(client.ip);\n        set bereq.http.x-forwarded-proto = urlencode(req.protocol);\n        set bereq.http.x-datadome-params:authorizationlen = std.strlen(req.http.authorization);\n        # Truncating Headers - Start\n        set bereq.http.accept-charset = substr(req.http.accept-charset, 0, 128);\n        set bereq.http.accept-language = substr(req.http.accept-language, 0, 256);\n        set bereq.http.x-requested-with = substr(req.http.x-requested-with, 0, 128);\n        set bereq.http.x-fl-productid = substr(req.http.x-fl-productid, 0, 64);\n        set bereq.http.x-flapi-session-id = substr(req.http.x-flapi-session-id, 0, 64);\n        set bereq.http.fastly-orig-accept-encoding = substr(req.http.fastly-orig-accept-encoding, 0, 128);\n        set bereq.http.cache-control = substr(req.http.cache-control, 0, 128);\n        set bereq.http.client-id = substr(req.http.client-id, 0, 128);\n        set bereq.http.connection = substr(req.http.connection, 0, 128);\n        set bereq.http.pragma = substr(req.http.pragma, 0, 128);\n        set bereq.http.accept = substr(req.http.accept, 0, 512);\n        set bereq.http.headers-list = substr(req.http.headers-list, 0, 512);\n        set bereq.http.host = substr(req.http.host, 0, 512);\n        set bereq.http.origin = substr(req.http.origin, 0, 512);\n        set bereq.http.server-hostname = substr(req.http.server-hostname, 0, 512);\n        set bereq.http.server-name = substr(req.http.server-name, 0, 512);\n        if( std.strlen(req.http.x-forwarded-for) \u003e 512 ) {\n            # Truncate from the end\n            set bereq.http.x-forwarded-for = substr(req.http.x-forwarded-for, -512);\n        } else {\n            set bereq.http.x-forwarded-for = req.http.x-forwarded-for;\n        }\n        set bereq.http.user-agent = substr(req.http.user-agent, 0, 768);\n        set bereq.http.referer = substr(req.http.referer, 0, 1024);\n        set bereq.http.request = substr(req.http.request, 0, 2048);\n        set bereq.http.content-type = substr(req.http.content-type, 0, 64);\n        set bereq.http.from = substr(req.http.from, 0, 128);\n        set bereq.http.true-client-ip = substr(req.http.true-client-ip, 0, 128);\n        set bereq.http.via = substr(req.http.via, 0, 256);\n        set bereq.http.x-real-ip = substr(req.http.x-real-ip, 0, 128);\n        set bereq.http.sec-ch-device-memory = substr(req.http.sec-ch-device-memory, 0, 8);\n        set bereq.http.sec-ch-ua = substr(req.http.sec-ch-ua, 0, 128);\n        set bereq.http.sec-ch-ua-arch = substr(req.http.sec-ch-ua-arch, 0, 16);\n        set bereq.http.sec-ch-ua-full-version-list = substr(req.http.sec-ch-ua-full-version-list, 0, 256);\n        set bereq.http.sec-ch-ua-mobile = substr(req.http.sec-ch-ua-mobile, 0, 8);\n        set bereq.http.sec-ch-ua-model = substr(req.http.sec-ch-ua-model, 0, 128);\n        set bereq.http.sec-ch-ua-platform = substr(req.http.sec-ch-ua-platform, 0, 32);\n        set bereq.http.sec-fetch-dest = substr(req.http.sec-fetch-dest, 0, 32);\n        set bereq.http.sec-fetch-mode = substr(req.http.sec-fetch-mode, 0, 32);\n        set bereq.http.sec-fetch-site = substr(req.http.sec-fetch-site, 0, 64);\n        set bereq.http.sec-fetch-user = substr(req.http.sec-fetch-user, 0, 8);\n        # Truncating Headers - End\n        if (req.http.x-datadome-clientid) {\n            set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.x-datadome-clientid, 0, 128));\n            set bereq.http.x-datadome-x-set-cookie = \"true\";\n        } else {\n            set bereq.http.x-datadome-params:clientid = urlencode(substr(req.http.cookie:datadome, 0, 128));\n        }\n        set bereq.http.x-datadome-params:cookieslen = std.strlen(req.http.cookie);\n        # enforce gzip encoding between Fastly and DataDome\n        set bereq.http.accept-encoding = \"gzip\";\n    } else {\n        # prevent leak of the key\n        unset bereq.http.x-datadome-params;\n    }\n  }\n}\n\nbackend datadome {\n    .host = \"api-fastly.datadome.co\";\n    .port = \"8443\";\n    .connect_timeout = {{datadome_connect_timeout}}ms;\n    .first_byte_timeout = {{datadome_between_bytes_timeout}}ms;\n    .between_bytes_timeout = {{datadome_between_bytes_timeout}}ms;\n    .max_connections = 200;\n    .ssl = true;\n    .dynamic = true;\n    .probe = {\n        .request = \"HEAD /.well-known/healthcheck-datadome HTTP/1.1\" \"Host: api-fastly.datadome.co\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n        .expected_response = 200;\n        .initial = 5;\n        .interval = 2s;\n        .threshold = 1;\n        .timeout = 2s;\n        .window = 5;\n      }\n}",
      "type": "init"
    },
    {
      "priority": 7,
      "template": "if (req.backend == datadome) {\n  declare local var.status STRING;\n  set var.status = beresp.status;\n  # check that it is real ApiServer response\n  if (var.status != beresp.http.x-datadomeresponse) {\n    restart;\n  }\n  unset beresp.http.x-datadomeresponse;\n  # copy datadome headers\n  set req.http.x-datadome-headers-pairs:x-datadome-headers = urlencode(beresp.http.x-datadome-headers);\n\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-set-cookie( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-set-cookie = urlencode(beresp.http.x-set-cookie);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-server( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-datadome-server = urlencode(beresp.http.x-datadome-server);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-datadome = urlencode(beresp.http.x-datadome);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+content-type( |$)+\") {\n    set req.http.x-datadome-headers-pairs:content-type = urlencode(beresp.http.content-type);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+charset( |$)+\") {\n    set req.http.x-datadome-headers-pairs:charset = urlencode(beresp.http.charset);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+cache-control( |$)+\") {\n    set req.http.x-datadome-headers-pairs:cache-control = urlencode(beresp.http.cache-control);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+pragma( |$)+\") {\n    set req.http.x-datadome-headers-pairs:pragma = urlencode(beresp.http.pragma);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-credentials( |$)+\") {\n    set req.http.x-datadome-headers-pairs:access-control-allow-credentials = urlencode(beresp.http.access-control-allow-credentials);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-expose-headers( |$)+\") {\n    set req.http.x-datadome-headers-pairs:access-control-expose-headers = urlencode(beresp.http.access-control-expose-headers);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-origin( |$)+\") {\n    set req.http.x-datadome-headers-pairs:access-control-allow-origin = urlencode(beresp.http.access-control-allow-origin);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-datadome-cid( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-datadome-cid = urlencode(beresp.http.x-datadome-cid);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-b( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-dd-b = urlencode(beresp.http.x-dd-b);\n  }\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n    set req.http.x-datadome-headers-pairs:x-dd-type = urlencode(beresp.http.x-dd-type);\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n    set req.http.x-dd-type = beresp.http.x-dd-type;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n    set req.http.x-datadome-botname = beresp.http.x-datadome-botname;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n    set req.http.x-datadome-botfamily = beresp.http.x-datadome-botfamily;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n    set req.http.x-datadome-isbot = beresp.http.x-datadome-isbot;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n    set req.http.x-datadome-captchapassed = beresp.http.x-datadome-captchapassed;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n    set req.http.x-datadome-devicecheckpassed = beresp.http.x-datadome-devicecheckpassed;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n    set req.http.x-datadome-traffic-rule-response = beresp.http.x-datadome-traffic-rule-response;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n    set req.http.x-datadome-captchaurl = beresp.http.x-datadome-captchaurl;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n    set req.http.x-datadome-requestid = beresp.http.x-datadome-requestid;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n    set req.http.x-datadome-score = beresp.http.x-datadome-score;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n    set req.http.x-datadome-ruletype = beresp.http.x-datadome-ruletype;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n    set req.http.x-datadome-matchedmodels = beresp.http.x-datadome-matchedmodels;\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n    set req.http.x-datadome-sessionid = beresp.http.x-datadome-sessionid;\n  }\n  # don\u0027t forget about ApiServer\u0027s cookies\n  if (beresp.http.x-datadome-headers ~ \"(?i)(^| )+set-cookie( |$)+\") {\n    set req.http.x-datadome-headers-pairs:set-cookie = urlencode(beresp.http.set-cookie);\n  }\n\n  # Continue only if ApiServer returns expected blocked status\n  if (beresp.status != 403 \u0026\u0026 beresp.status != 401 \u0026\u0026 beresp.status != 301 \u0026\u0026 beresp.status != 302) {\n    unset beresp.http.x-datadome-headers;\n    unset beresp.http.x-datadome-request-headers;\n    set req.http.x-datadome-cookie = beresp.http.x-datadome-cookie; # Allow Session Feature\n    restart;\n  }\n\n  # ok, it is banned request, cleanup it a bit\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-dd-type( |$)+\") {\n      unset beresp.http.x-dd-type;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botname( |$)+\") {\n      unset beresp.http.x-datadome-botname;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-botfamily( |$)+\") {\n      unset beresp.http.x-datadome-botfamily;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-isbot( |$)+\") {\n      unset beresp.http.x-datadome-isbot;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchapassed( |$)+\") {\n      unset beresp.http.x-datadome-captchapassed;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-devicecheckpassed( |$)+\") {\n      unset beresp.http.x-datadome-devicecheckpassed;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-traffic-rule-response( |$)+\") {\n      unset beresp.http.x-datadome-traffic-rule-response;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-captchaurl( |$)+\") {\n      unset beresp.http.x-datadome-captchaurl;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-requestid( |$)+\") {\n      unset beresp.http.x-datadome-requestid;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-score( |$)+\") {\n      unset beresp.http.x-datadome-score;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-ruletype( |$)+\") {\n      unset beresp.http.x-datadome-ruletype;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-matchedmodels( |$)+\") {\n      unset beresp.http.x-datadome-matchedmodels;\n    }\n  }\n  if (beresp.http.x-datadome-request-headers ~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n    if (beresp.http.x-datadome-headers !~ \"(?i)(^| )+x-datadome-sessionid( |$)+\") {\n      unset beresp.http.x-datadome-sessionid;\n    }\n  }\n  unset beresp.http.x-datadome-headers;\n  unset beresp.http.x-datadome-request-headers;\n}",
      "type": "fetch"
    },
    {
      "priority": 7,
      "template": "if (req.backend == datadome) {\n  restart;\n}",
      "type": "error"
    },
    {
      "priority": 7,
      "template": "# copy datadome headers if it isn\u0027t datadome request\nif (fastly.ff.visits_this_service == 0 \u0026\u0026 req.backend != datadome) {\n  declare local var.x-datadome-headers STRING;\n  set var.x-datadome-headers = urldecode(req.http.x-datadome-headers-pairs:x-datadome-headers);\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-set-cookie( |$)+\") {\n    set resp.http.x-set-cookie = urldecode(req.http.x-datadome-headers-pairs:x-set-cookie);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-datadome-server( |$)+\") {\n    set resp.http.x-datadome-server = urldecode(req.http.x-datadome-headers-pairs:x-datadome-server);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-datadome( |$)+\") {\n    set resp.http.x-datadome = urldecode(req.http.x-datadome-headers-pairs:x-datadome);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+content-type( |$)+\") {\n    set resp.http.content-type = urldecode(req.http.x-datadome-headers-pairs:content-type);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+charset( |$)+\") {\n    set resp.http.charset = urldecode(req.http.x-datadome-headers-pairs:charset);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+cache-control( |$)+\") {\n    set resp.http.cache-control = urldecode(req.http.x-datadome-headers-pairs:cache-control);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+pragma( |$)+\") {\n    set resp.http.pragma = urldecode(req.http.x-datadome-headers-pairs:pragma);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-credentials( |$)+\") {\n    set resp.http.access-control-allow-credentials = urldecode(req.http.x-datadome-headers-pairs:access-control-allow-credentials);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+access-control-expose-headers( |$)+\") {\n    set resp.http.access-control-expose-headers = urldecode(req.http.x-datadome-headers-pairs:access-control-expose-headers);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+access-control-allow-origin( |$)+\") {\n    set resp.http.access-control-allow-origin = urldecode(req.http.x-datadome-headers-pairs:access-control-allow-origin);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-datadome-cid( |$)+\") {\n    set resp.http.x-datadome-cid = urldecode(req.http.x-datadome-headers-pairs:x-datadome-cid);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-dd-b( |$)+\") {\n    set resp.http.x-dd-b = urldecode(req.http.x-datadome-headers-pairs:x-dd-b);\n  }\n  if (var.x-datadome-headers ~ \"(?i)(^| )+x-dd-type( |$)+\") {\n    set resp.http.x-dd-type = urldecode(req.http.x-datadome-headers-pairs:x-dd-type);\n  }\n  # Allow Session Feature\n  if (resp.http.x-datadome-cookie) {\n    add resp.http.set-cookie = resp.http.x-datadome-cookie;\n    if (req.http.x-datadome-clientid) {\n        set resp.http.x-set-cookie = resp.http.x-datadome-cookie;\n    }\n    unset resp.http.x-datadome-cookie;\n  } elseif (var.x-datadome-headers ~ \"(?i)(^| )+set-cookie( |$)+\") {\n    # don\u0027t forget about ApiServer\u0027s cookies\n    add resp.http.set-cookie = urldecode(req.http.x-datadome-headers-pairs:set-cookie);\n  }\n}",
      "type": "deliver"
    },
    {
      "priority": 7,
      "template": "\n  {{#if logging_endpoint}}\n  ## Debug DataDome\n  log {\"syslog \"} req.service_id {\" {{logging_endpoint}} :: \"}\n      \" timestamp=%22\" now\n      \"%22 client_ip=\" req.http.Fastly-Client-IP\n      \" request=\" req.method\n      \" url=%22\" cstr_escape(req.url.path)\n      \"%22 restarts=\" req.restarts\n      \" DataDomeDebug=\" \"Before_DataDome\"\n      \" fastlyFF=\" fastly.ff.visits_this_service;\n  ##\n  {{/if}}# Configure the regular expression below to match URLs that\n# should be checked by DataDome\nif (fastly.ff.visits_this_service == 0 \u0026\u0026 req.restarts == 0 \u0026\u0026 req.method != \"FASTLYPURGE\" \u0026\u0026 !(req.url.path ~ \"{{datadome_exclusion_ext}}\" \u0026\u0026 (req.method == \"GET\" || req.method == \"HEAD\"))) {\n\n  set req.backend = datadome;\n  unset req.http.x-datadome-params;\n  # Configure the string below to include your DataDome API key\n  set req.http.x-datadome-params:method = urlencode(req.method);\n  set req.http.x-datadome-params:postparamlen = urlencode(req.http.content-length);\n  set req.method = \"GET\";\n  set req.http.x-datadome-params:tlsprotocol = urlencode(tls.client.protocol);\n  set req.http.x-datadome-params:tlscipherslist = urlencode(tls.client.ciphers_list);\n  set req.http.x-datadome-params:tlsextensionslist = urlencode(tls.client.tlsexts_list);\n  set req.http.x-datadome-params:ja3 = urlencode(tls.client.ja3_md5);\n  {{#if logging_endpoint}}\n  ## Debug DataDome\n  log {\"syslog \"} req.service_id {\" {{logging_endpoint}} :: \"}\n      \" timestamp=%22\" now\n      \"%22 client_ip=\" req.http.Fastly-Client-IP\n      \" request=\" req.method\n      \" host=\" req.http.host\n      \" url=%22\" cstr_escape(req.url)\n      \"%22 request_referer=%22\" cstr_escape(req.http.Referer)\n      \"%22 request_user_agent=%22\" cstr_escape(req.http.User-Agent)\n      \"%22 request_accept_language=%22\" cstr_escape(req.http.Accept-Language)\n      \"%22 request_accept_charset=%22\" cstr_escape(req.http.Accept-Charset)\n      \"%22 contentLength=\" req.http.Content-Length\n      \" restarts=\" req.restarts\n      \" DataDomeDebug=\" \"To_DataDome\"\n      \" fastlyFF=\" fastly.ff.visits_this_service;\n  ##\n  {{/if}}\n  return (pass);\n} else {\n  if (req.http.x-datadome-params:method) {\n    set req.method = urldecode(req.http.x-datadome-params:method);\n    # After a restart, clustering is disabled. This re-enables it.\n    set req.http.fastly-force-shield = \"1\";\n  }\n  unset req.http.x-datadome-params;\n  {{#if logging_endpoint}}\n  ## Debug DataDome\n  log {\"syslog \"} req.service_id {\" {{logging_endpoint}} :: \"}\n      \" timestamp=%22\" now\n      \"%22 client_ip=\" req.http.Fastly-Client-IP\n      \" request=\" req.method\n      \" host=\" req.http.host\n      \" url=%22\" cstr_escape(req.url)\n      \"%22 request_referer=%22\" cstr_escape(req.http.Referer)\n      \"%22 request_user_agent=%22\" cstr_escape(req.http.User-Agent)\n      \"%22 request_accept_language=%22\" cstr_escape(req.http.Accept-Language)\n      \"%22 request_accept_charset=%22\" cstr_escape(req.http.Accept-Charset)\n      \"%22 contentLength=\" req.http.Content-Length\n      \" restarts=\" req.restarts\n      \" DataDomeDebug=\" \"Bypass_DataDome\"\n      \" fastlyFF=\" fastly.ff.visits_this_service;\n  ##\n  {{/if}}\n}\n\n# we\u0027re using the first restart for datadome, update a part of fastly code\n# we can\u0027t replace whole macros because we haven\u0027t got any idea about backends\nif (req.restarts == 1) {\n  if (!req.http.x-timer) {\n    set req.http.x-timer = \"S\" time.start.sec \".\" time.start.usec_frac;\n  }\n  set req.http.x-timer = req.http.x-timer \",VS0\";\n}\n\nset var.fastly_req_do_shield = (req.restarts \u003c= 1);",
      "type": "recv"
    },
    {
      "priority": 7,
      "template": "call set_origin_header;",
      "type": "miss"
    },
    {
      "priority": 7,
      "template": "call set_origin_header;",
      "type": "pass"
    }
  ],
  "version": "2.19.4"
}
