diff --git a/docker/README.md b/docker/README.md index 76c47a09..699c1c75 100644 --- a/docker/README.md +++ b/docker/README.md @@ -113,6 +113,7 @@ This is the complete list of supported env vars: * `WEB_WORKER_NUM`: The amount of concurrent http requests this shlink instance will be able to server. Defaults to 16. * `TASK_WORKER_NUM`: The amount of concurrent background tasks this shlink instance will be able to execute. Defaults to 16. * `VISITS_WEBHOOKS`: A comma-separated list of URLs that will receive a `POST` request when a short URL receives a visit. +* `DEFAULT_SHORT_CODES_LENGTH`: The length you want generated short codes to have. It defaults to 5 and has to be at least 4, so any value smaller than that will fall back to 4. * `REDIS_SERVERS`: A comma-separated list of redis servers where Shlink locks are stored (locks are used to prevent some operations to be run more than once in parallel). This is important when running more than one Shlink instance ([Multi instance considerations](#multi-instance-considerations)). If not provided, Shlink stores locks on every instance separately. @@ -146,6 +147,7 @@ docker run \ -e WEB_WORKER_NUM=64 \ -e TASK_WORKER_NUM=32 \ -e "VISITS_WEBHOOKS=http://my-api.com/api/v2.3/notify,https://third-party.io/foo" \ + -e DEFAULT_SHORT_CODES_LENGTH=6 \ shlinkio/shlink:stable ``` @@ -170,6 +172,7 @@ The whole configuration should have this format, but it can be split into multip "base_path": "/my-campaign", "web_worker_num": 64, "task_worker_num": 32, + "default_short_codes_length": 6, "redis_servers": [ "tcp://172.20.0.1:6379", "tcp://172.20.0.2:6379" diff --git a/docker/config/shlink_in_docker.local.php b/docker/config/shlink_in_docker.local.php index 9e10d419..6cf86434 100644 --- a/docker/config/shlink_in_docker.local.php +++ b/docker/config/shlink_in_docker.local.php @@ -11,6 +11,9 @@ use function explode; use function Functional\contains; use function Shlinkio\Shlink\Common\env; +use const Shlinkio\Shlink\Core\DEFAULT_SHORT_CODES_LENGTH; +use const Shlinkio\Shlink\Core\MIN_SHORT_CODES_LENGTH; + $helper = new class { private const DB_DRIVERS_MAP = [ 'mysql' => 'pdo_mysql', @@ -70,6 +73,12 @@ $helper = new class { $redisServers = env('REDIS_SERVERS'); return $redisServers === null ? null : ['servers' => $redisServers]; } + + public function getDefaultShortCodesLength(): int + { + $value = (int) env('DEFAULT_SHORT_CODES_LENGTH', DEFAULT_SHORT_CODES_LENGTH); + return $value < MIN_SHORT_CODES_LENGTH ? MIN_SHORT_CODES_LENGTH : $value; + } }; return [ @@ -96,6 +105,7 @@ return [ ], 'validate_url' => (bool) env('VALIDATE_URLS', false), 'visits_webhooks' => $helper->getVisitsWebhooks(), + 'default_short_codes_length' => $helper->getDefaultShortCodesLength(), ], 'not_found_redirects' => $helper->getNotFoundRedirectsConfig(), diff --git a/module/Core/functions/functions.php b/module/Core/functions/functions.php index 61d0be1e..87399208 100644 --- a/module/Core/functions/functions.php +++ b/module/Core/functions/functions.php @@ -11,6 +11,7 @@ use PUGX\Shortid\Factory as ShortIdFactory; use function sprintf; const DEFAULT_SHORT_CODES_LENGTH = 5; +const MIN_SHORT_CODES_LENGTH = 4; function generateRandomShortCode(int $length): string { diff --git a/module/Core/src/Config/SimplifiedConfigParser.php b/module/Core/src/Config/SimplifiedConfigParser.php index fa7a4acb..a03ccc3e 100644 --- a/module/Core/src/Config/SimplifiedConfigParser.php +++ b/module/Core/src/Config/SimplifiedConfigParser.php @@ -32,6 +32,7 @@ class SimplifiedConfigParser 'web_worker_num' => ['mezzio-swoole', 'swoole-http-server', 'options', 'worker_num'], 'task_worker_num' => ['mezzio-swoole', 'swoole-http-server', 'options', 'task_worker_num'], 'visits_webhooks' => ['url_shortener', 'visits_webhooks'], + 'default_short_codes_length' => ['url_shortener', 'default_short_codes_length'], ]; private const SIMPLIFIED_CONFIG_SIDE_EFFECTS = [ 'delete_short_url_threshold' => [ diff --git a/module/Core/src/Validation/ShortUrlMetaInputFilter.php b/module/Core/src/Validation/ShortUrlMetaInputFilter.php index 9e8b1c7a..a71b4cc2 100644 --- a/module/Core/src/Validation/ShortUrlMetaInputFilter.php +++ b/module/Core/src/Validation/ShortUrlMetaInputFilter.php @@ -10,6 +10,8 @@ use Laminas\InputFilter\InputFilter; use Laminas\Validator; use Shlinkio\Shlink\Common\Validation; +use const Shlinkio\Shlink\Core\MIN_SHORT_CODES_LENGTH; + class ShortUrlMetaInputFilter extends InputFilter { use Validation\InputFactoryTrait; @@ -43,7 +45,7 @@ class ShortUrlMetaInputFilter extends InputFilter $this->add($customSlug); $this->add($this->createPositiveNumberInput(self::MAX_VISITS)); - $this->add($this->createPositiveNumberInput(self::SHORT_CODE_LENGTH, 4)); + $this->add($this->createPositiveNumberInput(self::SHORT_CODE_LENGTH, MIN_SHORT_CODES_LENGTH)); $this->add($this->createBooleanInput(self::FIND_IF_EXISTS, false)); diff --git a/module/Core/test/Config/SimplifiedConfigParserTest.php b/module/Core/test/Config/SimplifiedConfigParserTest.php index 1d4f3b8d..7a304ad5 100644 --- a/module/Core/test/Config/SimplifiedConfigParserTest.php +++ b/module/Core/test/Config/SimplifiedConfigParserTest.php @@ -57,6 +57,7 @@ class SimplifiedConfigParserTest extends TestCase 'http://my-api.com/api/v2.3/notify', 'https://third-party.io/foo', ], + 'default_short_codes_length' => 8, ]; $expected = [ 'app_options' => [ @@ -84,6 +85,7 @@ class SimplifiedConfigParserTest extends TestCase 'http://my-api.com/api/v2.3/notify', 'https://third-party.io/foo', ], + 'default_short_codes_length' => 8, ], 'delete_short_urls' => [