frankenphp

package module
v1.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2024 License: MIT Imports: 25 Imported by: 1

README

FrankenPHP: Modern App Server for PHP

FrankenPHP

FrankenPHP is a modern application server for PHP built on top of the Caddy web server.

FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: Early Hints, worker mode, real-time capabilities, automatic HTTPS, HTTP/2, and HTTP/3 support...

FrankenPHP works with any PHP app and makes your Laravel and Symfony projects faster than ever thanks to their official integrations with the worker mode.

FrankenPHP can also be used as a standalone Go library to embed PHP in any app using net/http.

Learn more on frankenphp.dev and in this slide deck:

Slides

Getting Started

Docker
docker run -v $PWD:/app/public \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

Go to https://localhost, and enjoy!

[!TIP]

Do not attempt to use https://127.0.0.1. Use https://localhost and accept the self-signed certificate. Use the SERVER_NAME environment variable to change the domain to use.

Standalone Binary

If you prefer not to use Docker, we provide standalone FrankenPHP binaries for Linux and macOS containing PHP 8.3 and most popular PHP extensions: Download FrankenPHP

To serve the content of the current directory, run:

./frankenphp php-server

You can also run command-line scripts with:

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

Docs

Examples and Skeletons

Documentation

Overview

Package frankenphp embeds PHP in Go projects and provides a SAPI for net/http.

This is the core of the FrankenPHP app server, and can be used in any Go program.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	InvalidRequestError         = errors.New("not a FrankenPHP request")
	AlreaydStartedError         = errors.New("FrankenPHP is already started")
	InvalidPHPVersionError      = errors.New("FrankenPHP is only compatible with PHP 8.2+")
	ZendSignalsError            = errors.New("Zend Signals are enabled, recompile PHP with --disable-zend-signals")
	NotEnoughThreads            = errors.New("the number of threads must be superior to the number of workers")
	MainThreadCreationError     = errors.New("error creating the main thread")
	RequestContextCreationError = errors.New("error during request context creation")
	RequestStartupError         = errors.New("error during PHP request startup")
	ScriptExecutionError        = errors.New("error during PHP script execution")
)
View Source
var EmbeddedAppPath string

The path of the embedded PHP application (empty if none)

Functions

func ExecuteScriptCLI

func ExecuteScriptCLI(script string, args []string) int

ExecuteScriptCLI executes the PHP script passed as parameter. It returns the exit status code of the script.

Example
package main

import (
	"log"
	"os"

	"github.com/dunglas/frankenphp"
)

func main() {
	if len(os.Args) <= 1 {
		log.Println("Usage: my-program script.php")
		os.Exit(1)
	}

	os.Exit(frankenphp.ExecuteScriptCLI(os.Args[1], os.Args))
}
Output:

func Handles added in v1.0.3

func Handles() *handleList

Handles Get a new list of handles

func Init

func Init(options ...Option) error

Init starts the PHP runtime and the configured workers.

func NewRequestWithContext

func NewRequestWithContext(r *http.Request, opts ...RequestOption) (*http.Request, error)

NewRequestWithContext creates a new FrankenPHP request context.

func Pointers added in v1.0.3

func Pointers() *pointerList

Pointers Get a new list of pointers

func ServeHTTP

func ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) error

ServeHTTP executes a PHP script according to the given context.

Example
package main

import (
	"log"
	"net/http"

	"github.com/dunglas/frankenphp"
)

func main() {
	if err := frankenphp.Init(); err != nil {
		panic(err)
	}
	defer frankenphp.Shutdown()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot("/path/to/document/root", false))
		if err != nil {
			panic(err)
		}

		if err := frankenphp.ServeHTTP(w, req); err != nil {
			panic(err)
		}
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}
Output:

Example (Workers)
package main

import (
	"log"
	"net/http"

	"github.com/dunglas/frankenphp"
)

func main() {
	if err := frankenphp.Init(
		frankenphp.WithWorkers("worker1.php", 4, map[string]string{"ENV1": "foo"}),
		frankenphp.WithWorkers("worker2.php", 2, map[string]string{"ENV2": "bar"}),
	); err != nil {
		panic(err)
	}
	defer frankenphp.Shutdown()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot("/path/to/document/root", false))
		if err != nil {
			panic(err)
		}

		if err := frankenphp.ServeHTTP(w, req); err != nil {
			panic(err)
		}
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}
Output:

func Shutdown

func Shutdown()

Shutdown stops the workers and the PHP runtime.

Types

type FrankenPHPContext

type FrankenPHPContext struct {
	// contains filtered or unexported fields
}

FrankenPHPContext provides contextual information about the Request to handle.

func FromContext

func FromContext(ctx context.Context) (fctx *FrankenPHPContext, ok bool)

FromContext extracts the FrankenPHPContext from a context.

type Option

type Option func(h *opt) error

Option instances allow to configure FrankenPHP.

func WithLogger

func WithLogger(l *zap.Logger) Option

WithLogger configures the global logger to use.

func WithNumThreads

func WithNumThreads(numThreads int) Option

WithNumThreads configures the number of PHP threads to start.

func WithWorkers

func WithWorkers(fileName string, num int, env map[string]string) Option

WithWorkers configures the PHP workers to start.

type PHPConfig

type PHPConfig struct {
	Version                PHPVersion
	ZTS                    bool
	ZendSignals            bool
	ZendMaxExecutionTimers bool
}

func Config

func Config() PHPConfig

type PHPVersion

type PHPVersion struct {
	MajorVersion   int
	MinorVersion   int
	ReleaseVersion int
	ExtraVersion   string
	Version        string
	VersionID      int
}

func Version

func Version() PHPVersion

Version returns infos about the PHP version.

type PreparedEnv added in v1.1.1

type PreparedEnv = map[string]string

func PrepareEnv added in v1.1.1

func PrepareEnv(env map[string]string) PreparedEnv

type RequestOption

type RequestOption func(h *FrankenPHPContext) error

RequestOption instances allow to configure a FrankenPHP Request.

func WithRequestDocumentRoot

func WithRequestDocumentRoot(documentRoot string, resolveSymlink bool) RequestOption

WithRequestDocumentRoot sets the root directory of the PHP application. if resolveSymlink is true, oath declared as root directory will be resolved to its absolute value after the evaluation of any symbolic links. Due to the nature of PHP opcache, root directory path is cached: when using a symlinked directory as root this could generate errors when symlink is changed without PHP being restarted; enabling this directive will set $_SERVER['DOCUMENT_ROOT'] to the real directory path.

func WithRequestEnv

func WithRequestEnv(env map[string]string) RequestOption

WithRequestEnv set CGI-like environment variables that will be available in $_SERVER. Values set with WithEnv always have priority over automatically populated values.

func WithRequestLogger

func WithRequestLogger(logger *zap.Logger) RequestOption

WithRequestLogger sets the logger associated with the current request

func WithRequestPreparedEnv added in v1.1.1

func WithRequestPreparedEnv(env PreparedEnv) RequestOption

func WithRequestSplitPath

func WithRequestSplitPath(splitPath []string) RequestOption

The path in the URL will be split into two, with the first piece ending with the value of SplitPath. The first piece will be assumed as the actual resource (CGI script) name, and the second piece will be set to PATH_INFO for the CGI script to use.

Future enhancements should be careful to avoid CVE-2019-11043, which can be mitigated with use of a try_files-like behavior that 404s if the fastcgi path info is not found.

Directories

Path Synopsis
caddy module
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL