Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(caddy): allow to start workers using the php-server built-in command #339

Merged
merged 3 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ FrankenPHP can also be used as a standalone Go library to embed PHP in any app u

## Getting Started

### Docker

```console
docker run -v $PWD:/app/public \
-p 80:80 -p 443:443 \
Expand All @@ -24,10 +26,26 @@ docker run -v $PWD:/app/public \

Go to `https://localhost`, and enjoy!

> [!TIP]
>
> Do not attempt to use `https://127.0.0.1`. Use `localhost` and accept the self-signed certificate. Caddy has an automatic TLS handling that auto-trusts some local-based hostnames like `localhost`, but it does not apply to IP addresses. More details [on Caddy's "automatic https" docs](https://caddyserver.com/docs/automatic-https#hostname-requirements).

### Standalone Binary

If you prefer not to use Docker, we provide standalone FrankenPHP binaries for Linux and macOS
containing [PHP 8.3](https://www.php.net/releases/8.3/en.php) and most popular PHP extensions: [Download FrankenPHP](https://github.com/dunglas/frankenphp/releases)

> Note: do not attempt to use `https://127.0.0.1`. Use `localhost` and accept the self-signed certificate. Caddy has an automatic TLS handling that auto-trusts some local-based hostnames like `localhost`, but it does not apply to IP addresses. More details [on Caddy's "automatic https" docs](https://caddyserver.com/docs/automatic-https#hostname-requirements).
To serve the content of the current directory, run:

```console
./frankenphp php-server
```

You can also run command-line scripts with:

```console
./frankenphp php-cli /path/to/your/script.php
```

## Docs

Expand Down
31 changes: 28 additions & 3 deletions caddy/php-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/caddyserver/caddy/v2"
Expand All @@ -25,7 +26,7 @@ import (
func init() {
caddycmd.RegisterCommand(caddycmd.Command{
Name: "php-server",
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--access-log] [--debug] [--no-compress]",
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--worker /path/to/worker.php<,nb-workers>] [--access-log] [--debug] [--no-compress]",
Short: "Spins up a production-ready PHP server",
Long: `
A simple but production-ready PHP server. Useful for quick deployments,
Expand All @@ -43,6 +44,7 @@ For more advanced use cases, see https://github.com/dunglas/frankenphp/blob/main
cmd.Flags().StringP("domain", "d", "", "Domain name at which to serve the files")
cmd.Flags().StringP("root", "r", "", "The path to the root of the site")
cmd.Flags().StringP("listen", "l", "", "The address to which to bind the listener")
cmd.Flags().StringArrayP("worker", "w", []string{}, "Worker script")
cmd.Flags().BoolP("access-log", "a", false, "Enable the access log")
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
cmd.Flags().BoolP("no-compress", "", false, "Disable Zstandard and Gzip compression")
Expand All @@ -62,6 +64,29 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
debug := fs.Bool("debug")
compress := !fs.Bool("no-compress")

workers, err := fs.GetStringArray("worker")
if err != nil {
panic(err)
}

var workersOption []workerConfig
if len(workers) != 0 {
workersOption = make([]workerConfig, 0, len(workers))
for _, worker := range workers {
parts := strings.SplitN(worker, ",", 2)
if frankenphp.EmbeddedAppPath != "" && filepath.IsLocal(parts[0]) {
parts[0] = filepath.Join(frankenphp.EmbeddedAppPath, parts[0])
}

var num int
if len(parts) > 1 {
num, _ = strconv.Atoi(parts[1])
}

workersOption = append(workersOption, workerConfig{FileName: parts[0], Num: num})
}
}

if frankenphp.EmbeddedAppPath != "" {
if root == "" {
root = filepath.Join(frankenphp.EmbeddedAppPath, defaultDocumentRoot)
Expand Down Expand Up @@ -213,7 +238,7 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
},
AppsRaw: caddy.ModuleMap{
"http": caddyconfig.JSON(httpApp, nil),
"frankenphp": caddyconfig.JSON(FrankenPHPApp{}, nil),
"frankenphp": caddyconfig.JSON(FrankenPHPApp{Workers: workersOption}, nil),
},
}

Expand All @@ -227,7 +252,7 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
}
}

err := caddy.Run(cfg)
err = caddy.Run(cfg)
if err != nil {
return caddy.ExitCodeFailedStartup, err
}
Expand Down
24 changes: 23 additions & 1 deletion docs/worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
Boot your application once and keep it in memory.
FrankenPHP will handle incoming requests in a few milliseconds.

## Starting Worker Scripts

### Docker

Set the value of the `FRANKENPHP_CONFIG` environment variable to `worker /path/to/your/worker/script.php`:

```console
docker run \
-e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
-v $PWD:/app \
-p 80:80 -p 443:443 \
dunglas/frankenphp
```

### Standalone Binary

Use the `--worker` option of the `php-server` command to serve the content of the current directory using a worker:

```console
./frankenphp php-server --worker /path/to/your/worker/script.php
```

## Symfony Runtime

The worker mode of FrankenPHP is supported by the [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html).
Expand All @@ -12,7 +34,7 @@ To start any Symfony application in a worker, install the FrankenPHP package of
composer require runtime/frankenphp-symfony
```

Start your app server by defining the `APP_RUNTIME` environment variable to use the FrankenPHP Symfony Runtime
Start your app server by defining the `APP_RUNTIME` environment variable to use the FrankenPHP Symfony Runtime:

```console
docker run \
Expand Down