Repository: shlinkio/shlink (PHP)

Issue:
Allow customizing OpenSwoole configuration options
#### Summary

One of my use-cases for Shlink is for single-use URLs for uploading content / large files. This was recently supported since allowing for 307/308 redirect codes (via #1657) as the request method is now persisted. However, when attempting to perform a PUT request for a file that exceeds 2MB in size, I receive a 413 response and an error in the Shlink logs appears:
```
WARNING Port_onRead_http() (ERRNO 7102): Request Entity Too Large: header-length (368) + content-length (2719080) is greater than the package_max_length(2097152) from session#1466 on 0.0.0.0:8080
```

[OpenSwoole config](https://openswoole.com/docs/modules/swoole-server/configuration) allows setting the `package_max_length` option, it would be great if it was possible to override the default value when starting up a local Shlink server.


Discussion: I have some thoughts about this:

* This is too specific for openswoole. The way you have implemented it in #1661, would make it useless if you run Shlink with roadrunner or php-fpm, making it a bit confusing even if it's documented. At least it should work for roadrunner too.
* This is a very specific requirement for your very specific scenario. Shlink does not really need more than 2MB to be sent on any use-case. However, since you need to POST extra stuff to the redirected URL, you are sending it first to Shlink, which doesn't really need it (this also has the problem that you are forcing the file to be uploaded twice, first to Shlink, and then to the redirected URL, but that's another story).

So, instead of defining a new general-purpose env var, I'm thinking if maybe a better way to handle this is to define a way to provide any config for openswoole via special env vars.

That way you would be able to potentially define anything from https://openswoole.com/docs/modules/swoole-server/configuration for your Shlink instance if you wish to.

Maybe making Shlink propagate all the env vars prefixed with `OPENSWOOLE_`. For example, `OPENSWOOLE_PACKAGE_MAX_LENGTH` would be provided to Shlink's openswoole as `package_max_length` config, and so on.

The only open question would be how to define nested keys, but the general idea should work with the next benefits:

* It will be very explicit that it applies only to openswoole, allowing to later define something similar for roadrunner if needed.
* It will also be clear that's sort of a workaround, allowing to document that any changes in openswoole config will not be considered a breaking change for Shlink. If you go this way, you are on your own.
This is a rough implementation of the idea https://github.com/shlinkio/shlink-config/pull/24

Then `getOpenswooleConfigFromEnv` needs to be "merged" in the config that's later passed to openswoole via mezzio-swoole.

Some limitations:

* There's no easy way to provide nested values, so I'll probably leave that out of this for now.
* There won't be a way to provide these from shlink-installer, at least not for now. Might consider adding it later if needed, but I think most of the people using the installer does not serve Shlink with openswoole anyway.
* Some configs might break Shlink, so I will clearly document this as experimental and "do at your own risk", but at least users will have almost full control of their openswoole instance.
The feature is ready and I'm finishing the docs.

This will be added to https://shlink.io/documentation/environment-variables/

![image](https://user-images.githubusercontent.com/2719332/212158556-f3dd8a5e-4a34-44c5-bc03-fd9f9c1fbc3c.png)


Now you should be able to provide `OPENSWOOLE_PACKAGE_MAX_LENGTH=?` to Shlink with the value you need.



Fix (patch):
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a7389d9d4..a7a45727d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
 
   The status 308 is equivalent to 301, and 307 is equivalent to 302. The difference is that the spec requires the client to respect the original HTTP method when performing the redirect. With 301 and 302, some old clients might perform a `GET` request during the redirect, regardless the original request method.
 
+* [#1662](https://github.com/shlinkio/shlink/issues/1662) Added support to provide openswoole-specific config options via env vars prefixed with `OPENSWOOLE_`.
+
 ### Changed
 * *Nothing*
 
diff --git a/composer.json b/composer.json
index a3b90d762..856087429 100644
--- a/composer.json
+++ b/composer.json
@@ -46,7 +46,7 @@
         "pugx/shortid-php": "^1.1",
         "ramsey/uuid": "^4.5",
         "shlinkio/shlink-common": "^5.2",
-        "shlinkio/shlink-config": "^2.3",
+        "shlinkio/shlink-config": "dev-main#2a5b5c2 as 2.4",
         "shlinkio/shlink-event-dispatcher": "^2.6",
         "shlinkio/shlink-importer": "^5.0",
         "shlinkio/shlink-installer": "dev-develop#5fcee9b as 8.3",
diff --git a/config/autoload/swoole.global.php b/config/autoload/swoole.global.php
index 36cba24fd..494e3cf25 100644
--- a/config/autoload/swoole.global.php
+++ b/config/autoload/swoole.global.php
@@ -4,6 +4,8 @@
 
 use Shlinkio\Shlink\Core\Config\EnvVars;
 
+use function Shlinkio\Shlink\Config\getOpenswooleConfigFromEnv;
+
 use const Shlinkio\Shlink\MIN_TASK_WORKERS;
 
 return (static function (): array {
@@ -21,6 +23,7 @@
                 'process-name' => 'shlink',
 
                 'options' => [
+                    ...getOpenswooleConfigFromEnv(),
                     'worker_num' => (int) EnvVars::WEB_WORKER_NUM->loadFromEnv(16),
                     'task_worker_num' => max($taskWorkers, MIN_TASK_WORKERS),
                 ],