diff --git a/docs/environment/variables.mdx b/docs/environment/variables.mdx index e76c469b2..4c634bd53 100644 --- a/docs/environment/variables.mdx +++ b/docs/environment/variables.mdx @@ -60,6 +60,8 @@ aws ssm put-parameter --region us-east-1 --name '//my-app\my-parameter' --type S It is recommended to prefix the parameter name with your application name, for example: `/my-app/my-parameter`. +SSM also allows to store a SecureString parameter, which is encrypted with AWS KMS. To use a SecureString, simply change the `--type` argument to `--type SecureString`. Bref takes care of decrypting the value. + ### Retrieving secrets You can inject a secret in an environment variable: diff --git a/layers.json b/layers.json index 14f14e2bf..b14462807 100644 --- a/layers.json +++ b/layers.json @@ -1,410 +1,410 @@ { "php-83": { - "ca-central-1": "6", - "eu-central-1": "6", - "eu-north-1": "6", - "eu-west-1": "6", - "eu-west-2": "6", - "eu-west-3": "6", - "sa-east-1": "6", - "us-east-1": "6", - "us-east-2": "6", - "us-west-1": "6", - "us-west-2": "6", - "ap-east-1": "6", - "ap-south-1": "6", - "ap-northeast-1": "6", - "ap-northeast-2": "6", - "ap-northeast-3": "6", - "ap-southeast-1": "6", - "ap-southeast-2": "6", - "eu-south-1": "6", - "eu-south-2": "6", - "af-south-1": "6", - "me-south-1": "6" + "ca-central-1": "13", + "eu-central-1": "13", + "eu-north-1": "13", + "eu-west-1": "13", + "eu-west-2": "13", + "eu-west-3": "13", + "sa-east-1": "13", + "us-east-1": "13", + "us-east-2": "13", + "us-west-1": "13", + "us-west-2": "13", + "ap-east-1": "13", + "ap-south-1": "13", + "ap-northeast-1": "13", + "ap-northeast-2": "13", + "ap-northeast-3": "13", + "ap-southeast-1": "13", + "ap-southeast-2": "13", + "eu-south-1": "13", + "eu-south-2": "13", + "af-south-1": "13", + "me-south-1": "13" }, "php-83-fpm": { - "ca-central-1": "6", - "eu-central-1": "6", - "eu-north-1": "6", - "eu-west-1": "6", - "eu-west-2": "6", - "eu-west-3": "6", - "sa-east-1": "6", - "us-east-1": "6", - "us-east-2": "6", - "us-west-1": "6", - "us-west-2": "6", - "ap-east-1": "6", - "ap-south-1": "6", - "ap-northeast-1": "6", - "ap-northeast-2": "6", - "ap-northeast-3": "6", - "ap-southeast-1": "6", - "ap-southeast-2": "6", - "eu-south-1": "6", - "eu-south-2": "6", - "af-south-1": "6", - "me-south-1": "6" + "ca-central-1": "13", + "eu-central-1": "13", + "eu-north-1": "13", + "eu-west-1": "13", + "eu-west-2": "13", + "eu-west-3": "13", + "sa-east-1": "13", + "us-east-1": "13", + "us-east-2": "13", + "us-west-1": "13", + "us-west-2": "13", + "ap-east-1": "13", + "ap-south-1": "13", + "ap-northeast-1": "13", + "ap-northeast-2": "13", + "ap-northeast-3": "13", + "ap-southeast-1": "13", + "ap-southeast-2": "13", + "eu-south-1": "13", + "eu-south-2": "13", + "af-south-1": "13", + "me-south-1": "13" }, "php-82": { - "ca-central-1": "50", - "eu-central-1": "50", - "eu-north-1": "50", - "eu-west-1": "50", - "eu-west-2": "50", - "eu-west-3": "50", - "sa-east-1": "50", - "us-east-1": "50", - "us-east-2": "50", - "us-west-1": "50", - "us-west-2": "50", - "ap-east-1": "50", - "ap-south-1": "50", - "ap-northeast-1": "50", - "ap-northeast-2": "50", - "ap-northeast-3": "50", - "ap-southeast-1": "50", - "ap-southeast-2": "50", - "eu-south-1": "50", - "eu-south-2": "49", - "af-south-1": "50", - "me-south-1": "50" + "ca-central-1": "57", + "eu-central-1": "57", + "eu-north-1": "57", + "eu-west-1": "57", + "eu-west-2": "57", + "eu-west-3": "57", + "sa-east-1": "57", + "us-east-1": "57", + "us-east-2": "57", + "us-west-1": "57", + "us-west-2": "57", + "ap-east-1": "57", + "ap-south-1": "57", + "ap-northeast-1": "57", + "ap-northeast-2": "57", + "ap-northeast-3": "57", + "ap-southeast-1": "57", + "ap-southeast-2": "57", + "eu-south-1": "57", + "eu-south-2": "56", + "af-south-1": "57", + "me-south-1": "57" }, "php-82-fpm": { - "ca-central-1": "50", - "eu-central-1": "50", - "eu-north-1": "50", - "eu-west-1": "50", - "eu-west-2": "50", - "eu-west-3": "50", - "sa-east-1": "50", - "us-east-1": "50", - "us-east-2": "50", - "us-west-1": "50", - "us-west-2": "50", - "ap-east-1": "50", - "ap-south-1": "50", - "ap-northeast-1": "50", - "ap-northeast-2": "50", - "ap-northeast-3": "50", - "ap-southeast-1": "50", - "ap-southeast-2": "50", - "eu-south-1": "50", - "eu-south-2": "49", - "af-south-1": "50", - "me-south-1": "50" + "ca-central-1": "57", + "eu-central-1": "57", + "eu-north-1": "57", + "eu-west-1": "57", + "eu-west-2": "57", + "eu-west-3": "57", + "sa-east-1": "57", + "us-east-1": "57", + "us-east-2": "57", + "us-west-1": "57", + "us-west-2": "57", + "ap-east-1": "57", + "ap-south-1": "57", + "ap-northeast-1": "57", + "ap-northeast-2": "57", + "ap-northeast-3": "57", + "ap-southeast-1": "57", + "ap-southeast-2": "57", + "eu-south-1": "57", + "eu-south-2": "56", + "af-south-1": "57", + "me-south-1": "57" }, "php-81": { - "ca-central-1": "61", - "eu-central-1": "61", - "eu-north-1": "61", - "eu-west-1": "61", - "eu-west-2": "61", - "eu-west-3": "61", - "sa-east-1": "61", - "us-east-1": "61", - "us-east-2": "61", - "us-west-1": "61", - "us-west-2": "61", - "ap-east-1": "53", - "ap-south-1": "60", - "ap-northeast-1": "60", - "ap-northeast-2": "60", - "ap-northeast-3": "60", - "ap-southeast-1": "60", - "ap-southeast-2": "60", - "eu-south-1": "53", - "eu-south-2": "50", - "af-south-1": "53", - "me-south-1": "53" + "ca-central-1": "68", + "eu-central-1": "68", + "eu-north-1": "68", + "eu-west-1": "68", + "eu-west-2": "68", + "eu-west-3": "68", + "sa-east-1": "68", + "us-east-1": "68", + "us-east-2": "68", + "us-west-1": "68", + "us-west-2": "68", + "ap-east-1": "60", + "ap-south-1": "67", + "ap-northeast-1": "67", + "ap-northeast-2": "67", + "ap-northeast-3": "67", + "ap-southeast-1": "67", + "ap-southeast-2": "67", + "eu-south-1": "60", + "eu-south-2": "57", + "af-south-1": "60", + "me-south-1": "60" }, "php-81-fpm": { - "ca-central-1": "60", - "eu-central-1": "60", - "eu-north-1": "61", - "eu-west-1": "61", - "eu-west-2": "60", - "eu-west-3": "60", - "sa-east-1": "60", - "us-east-1": "61", - "us-east-2": "60", - "us-west-1": "60", - "us-west-2": "61", - "ap-east-1": "53", - "ap-south-1": "59", - "ap-northeast-1": "60", - "ap-northeast-2": "59", - "ap-northeast-3": "59", - "ap-southeast-1": "59", - "ap-southeast-2": "59", - "eu-south-1": "52", - "eu-south-2": "49", - "af-south-1": "52", - "me-south-1": "52" + "ca-central-1": "67", + "eu-central-1": "67", + "eu-north-1": "68", + "eu-west-1": "68", + "eu-west-2": "67", + "eu-west-3": "67", + "sa-east-1": "67", + "us-east-1": "68", + "us-east-2": "67", + "us-west-1": "67", + "us-west-2": "68", + "ap-east-1": "60", + "ap-south-1": "66", + "ap-northeast-1": "67", + "ap-northeast-2": "66", + "ap-northeast-3": "66", + "ap-southeast-1": "66", + "ap-southeast-2": "66", + "eu-south-1": "59", + "eu-south-2": "56", + "af-south-1": "59", + "me-south-1": "59" }, "php-80": { - "ca-central-1": "64", - "eu-central-1": "63", - "eu-north-1": "64", - "eu-west-1": "64", - "eu-west-2": "64", - "eu-west-3": "64", - "sa-east-1": "64", - "us-east-1": "64", - "us-east-2": "64", - "us-west-1": "64", - "us-west-2": "64", - "ap-east-1": "54", - "ap-south-1": "63", - "ap-northeast-1": "61", - "ap-northeast-2": "60", - "ap-northeast-3": "61", - "ap-southeast-1": "60", - "ap-southeast-2": "62", - "eu-south-1": "54", - "eu-south-2": "50", - "af-south-1": "54", - "me-south-1": "54" + "ca-central-1": "71", + "eu-central-1": "70", + "eu-north-1": "71", + "eu-west-1": "71", + "eu-west-2": "71", + "eu-west-3": "71", + "sa-east-1": "71", + "us-east-1": "71", + "us-east-2": "71", + "us-west-1": "71", + "us-west-2": "71", + "ap-east-1": "61", + "ap-south-1": "70", + "ap-northeast-1": "68", + "ap-northeast-2": "67", + "ap-northeast-3": "68", + "ap-southeast-1": "67", + "ap-southeast-2": "69", + "eu-south-1": "61", + "eu-south-2": "57", + "af-south-1": "61", + "me-south-1": "61" }, "php-80-fpm": { - "ca-central-1": "61", - "eu-central-1": "61", - "eu-north-1": "61", - "eu-west-1": "61", - "eu-west-2": "61", - "eu-west-3": "61", - "sa-east-1": "61", - "us-east-1": "61", - "us-east-2": "61", - "us-west-1": "61", - "us-west-2": "61", - "ap-east-1": "53", - "ap-south-1": "60", - "ap-northeast-1": "60", - "ap-northeast-2": "60", - "ap-northeast-3": "60", - "ap-southeast-1": "60", - "ap-southeast-2": "60", - "eu-south-1": "53", - "eu-south-2": "50", - "af-south-1": "53", - "me-south-1": "53" + "ca-central-1": "68", + "eu-central-1": "68", + "eu-north-1": "68", + "eu-west-1": "68", + "eu-west-2": "68", + "eu-west-3": "68", + "sa-east-1": "68", + "us-east-1": "68", + "us-east-2": "68", + "us-west-1": "68", + "us-west-2": "68", + "ap-east-1": "60", + "ap-south-1": "67", + "ap-northeast-1": "67", + "ap-northeast-2": "67", + "ap-northeast-3": "67", + "ap-southeast-1": "67", + "ap-southeast-2": "67", + "eu-south-1": "60", + "eu-south-2": "57", + "af-south-1": "60", + "me-south-1": "60" }, "arm-php-83": { - "ca-central-1": "6", - "eu-central-1": "6", - "eu-north-1": "6", - "eu-west-1": "6", - "eu-west-2": "6", - "eu-west-3": "6", - "sa-east-1": "6", - "us-east-1": "6", - "us-east-2": "6", - "us-west-1": "6", - "us-west-2": "6", - "ap-east-1": "6", - "ap-south-1": "6", - "ap-northeast-1": "6", - "ap-northeast-2": "6", - "ap-northeast-3": "6", - "ap-southeast-1": "6", - "ap-southeast-2": "6", - "eu-south-1": "6", - "eu-south-2": "6", - "af-south-1": "6", - "me-south-1": "6" + "ca-central-1": "13", + "eu-central-1": "13", + "eu-north-1": "13", + "eu-west-1": "13", + "eu-west-2": "13", + "eu-west-3": "13", + "sa-east-1": "13", + "us-east-1": "13", + "us-east-2": "13", + "us-west-1": "13", + "us-west-2": "13", + "ap-east-1": "13", + "ap-south-1": "13", + "ap-northeast-1": "13", + "ap-northeast-2": "13", + "ap-northeast-3": "13", + "ap-southeast-1": "13", + "ap-southeast-2": "13", + "eu-south-1": "13", + "eu-south-2": "13", + "af-south-1": "13", + "me-south-1": "13" }, "arm-php-83-fpm": { - "ca-central-1": "6", - "eu-central-1": "6", - "eu-north-1": "6", - "eu-west-1": "6", - "eu-west-2": "6", - "eu-west-3": "6", - "sa-east-1": "6", - "us-east-1": "6", - "us-east-2": "6", - "us-west-1": "6", - "us-west-2": "6", - "ap-east-1": "6", - "ap-south-1": "6", - "ap-northeast-1": "6", - "ap-northeast-2": "6", - "ap-northeast-3": "6", - "ap-southeast-1": "6", - "ap-southeast-2": "6", - "eu-south-1": "6", - "eu-south-2": "6", - "af-south-1": "6", - "me-south-1": "6" + "ca-central-1": "13", + "eu-central-1": "13", + "eu-north-1": "13", + "eu-west-1": "13", + "eu-west-2": "13", + "eu-west-3": "13", + "sa-east-1": "13", + "us-east-1": "13", + "us-east-2": "13", + "us-west-1": "13", + "us-west-2": "13", + "ap-east-1": "13", + "ap-south-1": "13", + "ap-northeast-1": "13", + "ap-northeast-2": "13", + "ap-northeast-3": "13", + "ap-southeast-1": "13", + "ap-southeast-2": "13", + "eu-south-1": "13", + "eu-south-2": "13", + "af-south-1": "13", + "me-south-1": "13" }, "arm-php-82": { - "ca-central-1": "38", - "eu-central-1": "38", - "eu-north-1": "38", - "eu-west-1": "38", - "eu-west-2": "38", - "eu-west-3": "38", - "sa-east-1": "38", - "us-east-1": "38", - "us-east-2": "38", - "us-west-1": "38", - "us-west-2": "38", - "ap-east-1": "38", - "ap-south-1": "38", - "ap-northeast-1": "38", - "ap-northeast-2": "38", - "ap-northeast-3": "38", - "ap-southeast-1": "38", - "ap-southeast-2": "38", - "eu-south-1": "38", - "eu-south-2": "38", - "af-south-1": "38", - "me-south-1": "38" + "ca-central-1": "45", + "eu-central-1": "45", + "eu-north-1": "45", + "eu-west-1": "45", + "eu-west-2": "45", + "eu-west-3": "45", + "sa-east-1": "45", + "us-east-1": "45", + "us-east-2": "45", + "us-west-1": "45", + "us-west-2": "45", + "ap-east-1": "45", + "ap-south-1": "45", + "ap-northeast-1": "45", + "ap-northeast-2": "45", + "ap-northeast-3": "45", + "ap-southeast-1": "45", + "ap-southeast-2": "45", + "eu-south-1": "45", + "eu-south-2": "45", + "af-south-1": "45", + "me-south-1": "45" }, "arm-php-82-fpm": { - "ca-central-1": "38", - "eu-central-1": "38", - "eu-north-1": "38", - "eu-west-1": "38", - "eu-west-2": "38", - "eu-west-3": "38", - "sa-east-1": "38", - "us-east-1": "38", - "us-east-2": "38", - "us-west-1": "38", - "us-west-2": "38", - "ap-east-1": "38", - "ap-south-1": "38", - "ap-northeast-1": "38", - "ap-northeast-2": "38", - "ap-northeast-3": "38", - "ap-southeast-1": "38", - "ap-southeast-2": "38", - "eu-south-1": "38", - "eu-south-2": "38", - "af-south-1": "38", - "me-south-1": "38" + "ca-central-1": "45", + "eu-central-1": "45", + "eu-north-1": "45", + "eu-west-1": "45", + "eu-west-2": "45", + "eu-west-3": "45", + "sa-east-1": "45", + "us-east-1": "45", + "us-east-2": "45", + "us-west-1": "45", + "us-west-2": "45", + "ap-east-1": "45", + "ap-south-1": "45", + "ap-northeast-1": "45", + "ap-northeast-2": "45", + "ap-northeast-3": "45", + "ap-southeast-1": "45", + "ap-southeast-2": "45", + "eu-south-1": "45", + "eu-south-2": "45", + "af-south-1": "45", + "me-south-1": "45" }, "arm-php-81": { - "ca-central-1": "41", - "eu-central-1": "41", - "eu-north-1": "41", - "eu-west-1": "41", - "eu-west-2": "41", - "eu-west-3": "41", - "sa-east-1": "41", - "us-east-1": "41", - "us-east-2": "41", - "us-west-1": "41", - "us-west-2": "41", - "ap-east-1": "41", - "ap-south-1": "41", - "ap-northeast-1": "41", - "ap-northeast-2": "41", - "ap-northeast-3": "41", - "ap-southeast-1": "41", - "ap-southeast-2": "41", - "eu-south-1": "41", - "eu-south-2": "41", - "af-south-1": "41", - "me-south-1": "41" + "ca-central-1": "48", + "eu-central-1": "48", + "eu-north-1": "48", + "eu-west-1": "48", + "eu-west-2": "48", + "eu-west-3": "48", + "sa-east-1": "48", + "us-east-1": "48", + "us-east-2": "48", + "us-west-1": "48", + "us-west-2": "48", + "ap-east-1": "48", + "ap-south-1": "48", + "ap-northeast-1": "48", + "ap-northeast-2": "48", + "ap-northeast-3": "48", + "ap-southeast-1": "48", + "ap-southeast-2": "48", + "eu-south-1": "48", + "eu-south-2": "48", + "af-south-1": "48", + "me-south-1": "48" }, "arm-php-81-fpm": { - "ca-central-1": "41", - "eu-central-1": "41", - "eu-north-1": "41", - "eu-west-1": "41", - "eu-west-2": "41", - "eu-west-3": "41", - "sa-east-1": "41", - "us-east-1": "41", - "us-east-2": "41", - "us-west-1": "41", - "us-west-2": "41", - "ap-east-1": "41", - "ap-south-1": "41", - "ap-northeast-1": "41", - "ap-northeast-2": "41", - "ap-northeast-3": "41", - "ap-southeast-1": "41", - "ap-southeast-2": "41", - "eu-south-1": "41", - "eu-south-2": "41", - "af-south-1": "41", - "me-south-1": "41" + "ca-central-1": "48", + "eu-central-1": "48", + "eu-north-1": "48", + "eu-west-1": "48", + "eu-west-2": "48", + "eu-west-3": "48", + "sa-east-1": "48", + "us-east-1": "48", + "us-east-2": "48", + "us-west-1": "48", + "us-west-2": "48", + "ap-east-1": "48", + "ap-south-1": "48", + "ap-northeast-1": "48", + "ap-northeast-2": "48", + "ap-northeast-3": "48", + "ap-southeast-1": "48", + "ap-southeast-2": "48", + "eu-south-1": "48", + "eu-south-2": "48", + "af-south-1": "48", + "me-south-1": "48" }, "arm-php-80": { - "ca-central-1": "63", - "eu-central-1": "62", - "eu-north-1": "63", - "eu-west-1": "63", - "eu-west-2": "63", - "eu-west-3": "63", - "sa-east-1": "63", - "us-east-1": "63", - "us-east-2": "63", - "us-west-1": "63", - "us-west-2": "63", - "ap-east-1": "55", - "ap-south-1": "62", - "ap-northeast-1": "62", - "ap-northeast-2": "62", - "ap-northeast-3": "62", - "ap-southeast-1": "62", - "ap-southeast-2": "62", - "eu-south-1": "55", - "eu-south-2": "51", - "af-south-1": "55", - "me-south-1": "55" + "ca-central-1": "70", + "eu-central-1": "69", + "eu-north-1": "70", + "eu-west-1": "70", + "eu-west-2": "70", + "eu-west-3": "70", + "sa-east-1": "70", + "us-east-1": "70", + "us-east-2": "70", + "us-west-1": "70", + "us-west-2": "70", + "ap-east-1": "62", + "ap-south-1": "69", + "ap-northeast-1": "69", + "ap-northeast-2": "69", + "ap-northeast-3": "69", + "ap-southeast-1": "69", + "ap-southeast-2": "69", + "eu-south-1": "62", + "eu-south-2": "58", + "af-south-1": "62", + "me-south-1": "62" }, "arm-php-80-fpm": { - "ca-central-1": "62", - "eu-central-1": "61", - "eu-north-1": "62", - "eu-west-1": "62", - "eu-west-2": "61", - "eu-west-3": "61", - "sa-east-1": "61", - "us-east-1": "62", - "us-east-2": "62", - "us-west-1": "61", - "us-west-2": "62", - "ap-east-1": "54", - "ap-south-1": "60", - "ap-northeast-1": "61", - "ap-northeast-2": "60", - "ap-northeast-3": "60", - "ap-southeast-1": "60", - "ap-southeast-2": "60", - "eu-south-1": "53", - "eu-south-2": "50", - "af-south-1": "54", - "me-south-1": "53" + "ca-central-1": "69", + "eu-central-1": "68", + "eu-north-1": "69", + "eu-west-1": "69", + "eu-west-2": "68", + "eu-west-3": "68", + "sa-east-1": "68", + "us-east-1": "69", + "us-east-2": "69", + "us-west-1": "68", + "us-west-2": "69", + "ap-east-1": "61", + "ap-south-1": "67", + "ap-northeast-1": "68", + "ap-northeast-2": "67", + "ap-northeast-3": "67", + "ap-southeast-1": "67", + "ap-southeast-2": "67", + "eu-south-1": "60", + "eu-south-2": "57", + "af-south-1": "61", + "me-south-1": "60" }, "console": { - "ca-central-1": "60", - "eu-central-1": "60", - "eu-north-1": "60", - "eu-west-1": "60", - "eu-west-2": "60", - "eu-west-3": "60", - "sa-east-1": "60", - "us-east-1": "60", - "us-east-2": "60", - "us-west-1": "60", - "us-west-2": "60", - "ap-east-1": "52", - "ap-south-1": "59", - "ap-northeast-1": "59", - "ap-northeast-2": "59", - "ap-northeast-3": "59", - "ap-southeast-1": "59", - "ap-southeast-2": "59", - "eu-south-1": "52", - "eu-south-2": "49", - "af-south-1": "52", - "me-south-1": "52" + "ca-central-1": "67", + "eu-central-1": "67", + "eu-north-1": "67", + "eu-west-1": "67", + "eu-west-2": "67", + "eu-west-3": "67", + "sa-east-1": "67", + "us-east-1": "67", + "us-east-2": "67", + "us-west-1": "67", + "us-west-2": "67", + "ap-east-1": "59", + "ap-south-1": "66", + "ap-northeast-1": "66", + "ap-northeast-2": "66", + "ap-northeast-3": "66", + "ap-southeast-1": "66", + "ap-southeast-2": "66", + "eu-south-1": "59", + "eu-south-2": "56", + "af-south-1": "59", + "me-south-1": "59" } } \ No newline at end of file diff --git a/serverless.yml b/serverless.yml index 43244fa3d..3dc3d8a6d 100644 --- a/serverless.yml +++ b/serverless.yml @@ -38,25 +38,19 @@ functions: timeout: 5 # in seconds (API Gateway has a timeout of 29 seconds) events: - http: 'ANY /' + - httpApi: '*' psr7: handler: demo/psr7.php runtime: php-83 description: 'Bref HTTP demo with a PSR-7 handler' timeout: 5 # in seconds (API Gateway has a timeout of 29 seconds) + url: true events: - http: 'ANY /psr7' - httpApi: 'GET /psr7' environment: - BREF_LOOP_MAX: 100 - - http-api: - handler: demo/http.php - runtime: php-83-fpm - description: 'Bref HTTP demo' - timeout: 5 # in seconds (API Gateway has a timeout of 29 seconds) - events: - - httpApi: '*' + #BREF_LOOP_MAX: 100 console: handler: demo/console.php diff --git a/src/Bref.php b/src/Bref.php index 180cdbac6..06d93a52c 100644 --- a/src/Bref.php +++ b/src/Bref.php @@ -2,6 +2,7 @@ namespace Bref; +use Bref\Listener\EventDispatcher; use Bref\Runtime\FileHandlerLocator; use Closure; use Psr\Container\ContainerInterface; @@ -11,10 +12,14 @@ class Bref { private static ?Closure $containerProvider = null; private static ?ContainerInterface $container = null; + /** + * TODO deprecate hooks when the event dispatcher is stable. + */ private static array $hooks = [ 'beforeStartup' => [], 'beforeInvoke' => [], ]; + private static EventDispatcher $eventDispatcher; /** * Configure the container that provides Lambda handlers. @@ -26,6 +31,17 @@ public static function setContainer(Closure $containerProvider): void self::$containerProvider = $containerProvider; } + /** + * @internal This API is experimental and may change at any time. + */ + public static function events(): EventDispatcher + { + if (! isset(self::$eventDispatcher)) { + self::$eventDispatcher = new EventDispatcher; + } + return self::$eventDispatcher; + } + /** * Register a hook to be executed before the runtime starts. * diff --git a/src/ConsoleRuntime/Main.php b/src/ConsoleRuntime/Main.php index 7b7b0f16d..422817a02 100755 --- a/src/ConsoleRuntime/Main.php +++ b/src/ConsoleRuntime/Main.php @@ -19,6 +19,7 @@ public static function run(): void LazySecretsLoader::loadSecretEnvironmentVariables(); Bref::triggerHooks('beforeStartup'); + Bref::events()->beforeStartup(); $lambdaRuntime = LambdaRuntime::fromEnvironmentVariable('console'); @@ -28,6 +29,8 @@ public static function run(): void $lambdaRuntime->failInitialization("Handler `$handlerFile` doesn't exist", 'Runtime.NoSuchHandler'); } + Bref::events()->afterStartup(); + /** @phpstan-ignore-next-line */ while (true) { $lambdaRuntime->processNextEvent(function ($event, Context $context) use ($handlerFile): array { diff --git a/src/Event/Http/HttpRequestEvent.php b/src/Event/Http/HttpRequestEvent.php index c4cbff55a..736b23728 100644 --- a/src/Event/Http/HttpRequestEvent.php +++ b/src/Event/Http/HttpRequestEvent.php @@ -190,7 +190,11 @@ public function getCookies(): array $cookies = []; foreach ($cookieParts as $cookiePart) { - [$cookieName, $cookieValue] = explode('=', $cookiePart, 2); + $explode = explode('=', $cookiePart, 2); + if (count($explode) !== 2) { + continue; + } + [$cookieName, $cookieValue] = $explode; $cookies[$cookieName] = urldecode($cookieValue); } return $cookies; diff --git a/src/Event/Sqs/SqsRecord.php b/src/Event/Sqs/SqsRecord.php index 4c9db8058..300b27ebc 100644 --- a/src/Event/Sqs/SqsRecord.php +++ b/src/Event/Sqs/SqsRecord.php @@ -57,6 +57,17 @@ public function getReceiptHandle(): string return $this->record['receiptHandle']; } + /** + * Returns the name of the SQS queue that contains the message. + * Queue naming constraints: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/quotas-queues.html + */ + public function getQueueName(): string + { + $parts = explode(':', $this->record['eventSourceARN']); + + return $parts[count($parts) - 1]; + } + /** * Returns the record original data as an array. * diff --git a/src/FpmRuntime/FpmHandler.php b/src/FpmRuntime/FpmHandler.php index 2205966f8..6f7136184 100644 --- a/src/FpmRuntime/FpmHandler.php +++ b/src/FpmRuntime/FpmHandler.php @@ -136,7 +136,8 @@ public function handleRequest(HttpRequestEvent $event, Context $context): HttpRe $response = $this->client->readResponse($socketId, $timeoutDelayInMs); } catch (TimedoutException) { - echo "The PHP script timed out. Bref will now restart PHP-FPM to start from a clean slate and flush the PHP logs.\nTimeouts can happen for example when trying to connect to a remote API or database, if this happens continuously check for those.\nIf you are using a RDS database, read this: https://bref.sh/docs/environment/database.html#accessing-the-internet\n"; + $invocationId = $context->getAwsRequestId(); + echo "$invocationId The PHP script timed out. Bref will now restart PHP-FPM to start from a clean slate and flush the PHP logs.\nTimeouts can happen for example when trying to connect to a remote API or database, if this happens continuously check for those.\nIf you are using a RDS database, read this: https://bref.sh/docs/environment/database.html#accessing-the-internet\n"; /** * Restart FPM so that the blocked script is 100% terminated and that its logs are flushed to stderr. diff --git a/src/FpmRuntime/Main.php b/src/FpmRuntime/Main.php index d3241b5d1..fa462c113 100755 --- a/src/FpmRuntime/Main.php +++ b/src/FpmRuntime/Main.php @@ -22,6 +22,7 @@ public static function run(): void LazySecretsLoader::loadSecretEnvironmentVariables(); Bref::triggerHooks('beforeStartup'); + Bref::events()->beforeStartup(); $lambdaRuntime = LambdaRuntime::fromEnvironmentVariable('fpm'); @@ -38,6 +39,8 @@ public static function run(): void $lambdaRuntime->failInitialization(new RuntimeException('Error while starting PHP-FPM: ' . $e->getMessage(), 0, $e)); } + Bref::events()->afterStartup(); + /** @phpstan-ignore-next-line */ while (true) { $lambdaRuntime->processNextEvent($phpFpm); diff --git a/src/FunctionRuntime/Main.php b/src/FunctionRuntime/Main.php index f6925ca06..8d335ce8b 100644 --- a/src/FunctionRuntime/Main.php +++ b/src/FunctionRuntime/Main.php @@ -17,6 +17,7 @@ public static function run(): void LazySecretsLoader::loadSecretEnvironmentVariables(); Bref::triggerHooks('beforeStartup'); + Bref::events()->beforeStartup(); $lambdaRuntime = LambdaRuntime::fromEnvironmentVariable('function'); @@ -28,6 +29,8 @@ public static function run(): void $lambdaRuntime->failInitialization($e, 'Runtime.NoSuchHandler'); } + Bref::events()->afterStartup(); + $loopMax = getenv('BREF_LOOP_MAX') ?: 1; $loops = 0; while (true) { diff --git a/src/Listener/BrefEventSubscriber.php b/src/Listener/BrefEventSubscriber.php new file mode 100644 index 000000000..489c3cfbe --- /dev/null +++ b/src/Listener/BrefEventSubscriber.php @@ -0,0 +1,59 @@ +subscribers[] = $subscriber; + } + + /** + * Trigger the `beforeStartup` event. + * + * @internal This method is called by Bref and should not be called by user code. + */ + public function beforeStartup(): void + { + foreach ($this->subscribers as $listener) { + $listener->beforeStartup(); + } + } + + /** + * Trigger the `afterStartup` event. + * + * @internal This method is called by Bref and should not be called by user code. + */ + public function afterStartup(): void + { + foreach ($this->subscribers as $listener) { + $listener->afterStartup(); + } + } + + /** + * Trigger the `beforeInvoke` event. + * + * @internal This method is called by Bref and should not be called by user code. + */ + public function beforeInvoke( + callable | Handler | RequestHandlerInterface $handler, + mixed $event, + Context $context, + ): void { + foreach ($this->subscribers as $listener) { + $listener->beforeInvoke($handler, $event, $context); + } + } + + /** + * Trigger the `afterInvoke` event. + * + * @internal This method is called by Bref and should not be called by user code. + */ + public function afterInvoke( + callable | Handler | RequestHandlerInterface $handler, + mixed $event, + Context $context, + mixed $result, + \Throwable | null $error = null, + ): void { + foreach ($this->subscribers as $listener) { + $listener->afterInvoke($handler, $event, $context, $result, $error); + } + } +} diff --git a/src/Runtime/LambdaRuntime.php b/src/Runtime/LambdaRuntime.php index d1cd50e0b..f0b70f1ac 100755 --- a/src/Runtime/LambdaRuntime.php +++ b/src/Runtime/LambdaRuntime.php @@ -86,6 +86,7 @@ public function processNextEvent(Handler | RequestHandlerInterface | callable $h $this->setEnv('LAMBDA_INVOCATION_CONTEXT', json_encode($context, JSON_THROW_ON_ERROR)); Bref::triggerHooks('beforeInvoke'); + Bref::events()->beforeInvoke($handler, $event, $context); $this->ping(); @@ -93,9 +94,13 @@ public function processNextEvent(Handler | RequestHandlerInterface | callable $h $result = $this->invoker->invoke($handler, $event, $context); $this->sendResponse($context->getAwsRequestId(), $result); + + Bref::events()->afterInvoke($handler, $event, $context, $result); } catch (Throwable $e) { $this->signalFailure($context->getAwsRequestId(), $e); + Bref::events()->afterInvoke($handler, $event, $context, null, $e); + return false; } diff --git a/tests/Event/Http/CommonHttpTest.php b/tests/Event/Http/CommonHttpTest.php index 3e931a97b..b6cc0e34e 100644 --- a/tests/Event/Http/CommonHttpTest.php +++ b/tests/Event/Http/CommonHttpTest.php @@ -416,6 +416,17 @@ public function test request with cookies(int $version) ]); } + /** + * @dataProvider provide API Gateway versions + */ + public function test request with invalid cookies(int $version) + { + $this->fromFixture(__DIR__ . "/Fixture/ag-v$version-cookies-invalid.json"); + + // See https://stackoverflow.com/a/61695783/245552 + $this->assertCookies([], 'foo'); + } + /** * @dataProvider provide API Gateway versions */ @@ -497,7 +508,7 @@ abstract protected function assertBody(string $expected): void; abstract protected function assertContentType(?string $expected): void; - abstract protected function assertCookies(array $expected): void; + abstract protected function assertCookies(array $expected, string |null $expectedHeader = null): void; abstract protected function assertHeaders(array $expected): void; diff --git a/tests/Event/Http/Fixture/ag-v1-cookies-invalid.json b/tests/Event/Http/Fixture/ag-v1-cookies-invalid.json new file mode 100644 index 000000000..5bcfcde0d --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v1-cookies-invalid.json @@ -0,0 +1,53 @@ +{ + "version": "1.0", + "resource": "/path", + "path": "/path", + "httpMethod": "GET", + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "Cookie": "foo" + }, + "queryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "requestContext": { + "resourceId": "xxxxxx", + "resourcePath": "/path", + "httpMethod": "PUT", + "extendedRequestId": "XXXXXX-xxxxxxxx=", + "requestTime": "24/Nov/2019:18:55:08 +0000", + "path": "/path", + "accountId": "123400000000", + "protocol": "HTTP/1.1", + "stage": "dev", + "domainPrefix": "dev", + "requestTimeEpoch": 1574621708700, + "requestId": "ffffffff-ffff-4fff-ffff-ffffffffffff", + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "sourceIp": "1.1.1.1", + "principalOrgId": null, + "accessKey": null, + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "PostmanRuntime/7.20.1", + "user": null + }, + "domainName": "example.org", + "apiId": "xxxxxxxxxx" + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/Event/Http/Fixture/ag-v2-cookies-invalid.json b/tests/Event/Http/Fixture/ag-v2-cookies-invalid.json new file mode 100644 index 000000000..1e4908fe2 --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v2-cookies-invalid.json @@ -0,0 +1,41 @@ +{ + "version": "2.0", + "routeKey": "ANY /path", + "rawPath": "/path", + "rawQueryString": "", + "cookies": ["foo"], + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "queryStringParameters": null, + "stageVariables": null, + "requestContext": { + "accountId": "123400000000", + "apiId": "xxxxxxxxxx", + "domainName": "example.org", + "domainPrefix": "0000000000", + "http": { + "method": "GET", + "path": "/path", + "protocol": "HTTP/1.1", + "sourceIp": "1.1.1.1", + "userAgent": "PostmanRuntime/7.20.1" + }, + "requestId": "JTHoQgr2oAMEPMg=", + "routeId": "47matwk", + "routeKey": "ANY /path", + "stage": "$default", + "time": "24/Nov/2019:18:55:08 +0000", + "timeEpoch": 1574621708700 + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/Event/Http/HttpRequestEventTest.php b/tests/Event/Http/HttpRequestEventTest.php index 20d7ec9c5..d1f2f516d 100644 --- a/tests/Event/Http/HttpRequestEventTest.php +++ b/tests/Event/Http/HttpRequestEventTest.php @@ -27,15 +27,18 @@ protected function assertContentType(?string $expected): void } } - protected function assertCookies(array $expected): void + protected function assertCookies(array $expected, string |null $expectedHeader = null): void { $this->assertEquals($expected, $this->event->getCookies()); // Also check that the cookies are available in the HTTP headers (they should be) - $expectedHeader = array_map(function (string $value, string $key): string { - return $key . '=' . urlencode($value); - }, $expected, array_keys($expected)); - $this->assertEquals(implode('; ', $expectedHeader), $this->event->getHeaders()['cookie'][0] ?? ''); + if ($expectedHeader === null) { + $expectedHeader = array_map(function (string $value, string $key): string { + return $key . '=' . urlencode($value); + }, $expected, array_keys($expected)); + $expectedHeader = implode('; ', $expectedHeader); + } + $this->assertEquals($expectedHeader, $this->event->getHeaders()['cookie'][0] ?? ''); } protected function assertHeaders(array $expected): void diff --git a/tests/Event/Http/Psr7BridgeTest.php b/tests/Event/Http/Psr7BridgeTest.php index 869a7e347..e2ab8de1a 100644 --- a/tests/Event/Http/Psr7BridgeTest.php +++ b/tests/Event/Http/Psr7BridgeTest.php @@ -48,7 +48,7 @@ protected function assertContentType(?string $expected): void $this->assertEquals($expected, $this->request->getHeaderLine('Content-Type')); } - protected function assertCookies(array $expected): void + protected function assertCookies(array $expected, string |null $expectedHeader = null): void { $this->assertEquals($expected, $this->request->getCookieParams()); } diff --git a/tests/Event/Sqs/SqsRecordTest.php b/tests/Event/Sqs/SqsRecordTest.php new file mode 100644 index 000000000..b83f190ff --- /dev/null +++ b/tests/Event/Sqs/SqsRecordTest.php @@ -0,0 +1,18 @@ +assertSame($sqsRecord->getQueueName(), 'my-queue'); + } +} diff --git a/tests/FpmRuntime/FpmHandlerTest.php b/tests/FpmRuntime/FpmHandlerTest.php index 388803894..1515150f6 100644 --- a/tests/FpmRuntime/FpmHandlerTest.php +++ b/tests/FpmRuntime/FpmHandlerTest.php @@ -777,6 +777,42 @@ public function test request with cookies(int $version) ]); } + /** + * @dataProvider provide API Gateway versions + */ + public function test request with invalid cookies(int $version) + { + $event = [ + 'version' => '1.0', + 'httpMethod' => 'GET', + 'headers' => [ + 'Cookie' => 'foo', + ], + ]; + $this->assertGlobalVariables($event, [ + '$_GET' => [], + '$_POST' => [], + '$_FILES' => [], + '$_COOKIE' => [ + 'foo' => '', + ], + '$_REQUEST' => [], + '$_SERVER' => [ + 'REQUEST_URI' => '/', + 'PHP_SELF' => '/', + 'PATH_INFO' => '/', + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => '', + 'HTTP_COOKIE' => 'foo', + 'CONTENT_LENGTH' => '0', + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', + 'LAMBDA_INVOCATION_CONTEXT' => json_encode($this->fakeContext), + 'LAMBDA_REQUEST_CONTEXT' => '[]', + ], + 'HTTP_RAW_BODY' => '', + ]); + } + /** * @dataProvider provide API Gateway versions */ diff --git a/tests/HttpRequestProxyTest.php b/tests/HttpRequestProxyTest.php index 4164546ad..725f1c1e2 100644 --- a/tests/HttpRequestProxyTest.php +++ b/tests/HttpRequestProxyTest.php @@ -47,6 +47,8 @@ public function test POST request with multipart file uploads(int $version public function test request with cookies(int $version); + public function test request with invalid cookies(int $version); + public function test POST request with base64 encoded body(int $version); public function test PUT request(int $version); diff --git a/tests/Listener/EventDispatcherTest.php b/tests/Listener/EventDispatcherTest.php new file mode 100644 index 000000000..701753bfb --- /dev/null +++ b/tests/Listener/EventDispatcherTest.php @@ -0,0 +1,31 @@ +subscribe($subscriber); + + $eventDispatcher->beforeStartup(); + $this->assertTrue($subscriber->invokedBeforeStartup); + + $handler = fn () => null; + $event = new stdClass; + $context = Context::fake(); + $eventDispatcher->beforeInvoke($handler, $event, $context); + $this->assertEquals([$handler, $event, $context], $subscriber->invokedBeforeInvoke); + + $result = new stdClass; + $eventDispatcher->afterInvoke($handler, $event, $context, $result); + $this->assertEquals([$handler, $event, $context, $result, null], $subscriber->invokedAfterInvoke); + } +} diff --git a/tests/Listener/FakeSubscriber.php b/tests/Listener/FakeSubscriber.php new file mode 100644 index 000000000..446db1126 --- /dev/null +++ b/tests/Listener/FakeSubscriber.php @@ -0,0 +1,33 @@ +invokedBeforeStartup = true; + } + + /** + * @param mixed ...$params + */ + public function beforeInvoke(...$params): void + { + $this->invokedBeforeInvoke = $params; + } + + /** + * @param mixed ...$params + */ + public function afterInvoke(...$params): void + { + $this->invokedAfterInvoke = $params; + } +} diff --git a/website/src/components/home/sponsors.jsx b/website/src/components/home/sponsors.jsx index 4ce56a581..a02c64cf4 100644 --- a/website/src/components/home/sponsors.jsx +++ b/website/src/components/home/sponsors.jsx @@ -2,7 +2,6 @@ import GoldSponsor from './sponsors/gold-sponsor'; import craftLogo from './sponsors/logo-craft-cms.png'; import tidewaysLogo from './sponsors/logo-tideways.svg'; import myBuilderLogo from './sponsors/logo-mybuilder.svg'; -import shippyProLogo from './sponsors/logo-shippypro.png'; import nullLogo from './sponsors/logo-null.png'; import awsLogo from './sponsors/logo-aws.svg'; import jetbrainsLogo from './sponsors/logo-jetbrains.svg'; @@ -10,6 +9,7 @@ import laravelLogo from './sponsors/logo-laravel.svg'; import depotLogo from './sponsors/logo-depot.svg'; import secumailerLogo from './sponsors/logo-secumailer.svg'; import ecomailLogo from './sponsors/logo-ecomail.png'; +import spreakerLogo from './sponsors/logo-spreaker.svg'; import PremiumSponsor from './sponsors/premium-sponsor'; export default function Sponsors() { @@ -26,9 +26,9 @@ export default function Sponsors() { - - + +

diff --git a/website/src/components/home/sponsors/logo-shippypro.png b/website/src/components/home/sponsors/logo-shippypro.png deleted file mode 100644 index 9bdd2021c..000000000 Binary files a/website/src/components/home/sponsors/logo-shippypro.png and /dev/null differ diff --git a/website/src/components/home/sponsors/logo-spreaker.svg b/website/src/components/home/sponsors/logo-spreaker.svg new file mode 100644 index 000000000..5dd75d864 --- /dev/null +++ b/website/src/components/home/sponsors/logo-spreaker.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/src/github/sponsors.js b/website/src/github/sponsors.js index 8cebeba1b..19589abf0 100644 --- a/website/src/github/sponsors.js +++ b/website/src/github/sponsors.js @@ -21,16 +21,6 @@ const nonGitHubSponsors = [ }, isOneTimePayment: false, }, - { - isActive: true, - sponsorEntity: { - __typename: 'Organization', - login: 'ShippyPro', - name: 'ShippyPro', - websiteUrl: 'https://www.shippypro.com/?ref=bref.sh', - }, - isOneTimePayment: false, - }, { isActive: true, sponsorEntity: {