Skip to content

Commit

Permalink
feat(caddy): allow to start workers using the php-server built-in com…
Browse files Browse the repository at this point in the history
…mand (#339)
  • Loading branch information
dunglas authored Dec 6, 2023
1 parent dee84ed commit e3361c2
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
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

0 comments on commit e3361c2

Please sign in to comment.