mirror of
https://github.com/dunglas/frankenphp.git
synced 2025-12-24 13:38:11 +08:00
initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.vscode/
|
||||
5
CONTRIBUTING.md
Normal file
5
CONTRIBUTING.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
## Compiling PHP
|
||||
|
||||
Pass the `--enable-debug` flag to compile PHP with debugging symbols.
|
||||
38
Dockerfile
Normal file
38
Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
||||
FROM golang
|
||||
|
||||
ARG PHP_VERSION=8.0.11
|
||||
|
||||
# Sury doesn't provide ZTS builds for now
|
||||
#RUN apt-get update && \
|
||||
# apt-get -y --no-install-recommends install apt-transport-https lsb-release&& \
|
||||
# wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \
|
||||
# sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' && \
|
||||
# apt-get update && \
|
||||
# apt-get -y --no-install-recommends install php8.0-dev && \
|
||||
# apt-get -y remove apt-transport-https lsb-release && \
|
||||
# apt-get clean all
|
||||
#ENV CGO_CFLAGS="-I /usr/include/php/20200930 -I /usr/include/php/20200930/Zend -I /usr/include/php/20200930/TSRM -I /usr/include/php/20200930/main -I /usr/include/php/20200930/sapi/embed"
|
||||
|
||||
# TODO: check the downloaded package using the provided GPG signatures
|
||||
RUN apt-get update && \
|
||||
apt-get -y --no-install-recommends install libxml2 libxml2-dev sqlite3 libsqlite3-dev && \
|
||||
apt-get clean && \
|
||||
curl -s -o php-${PHP_VERSION}.tar.gz https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz && \
|
||||
tar -xf php-${PHP_VERSION}.tar.gz && \
|
||||
cd php-${PHP_VERSION}/ && \
|
||||
# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
|
||||
./configure --enable-zts --enable-embed --enable-debug && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -Rf php-${PHP_VERSION}/ php-${PHP_VERSION}.tar.gz
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib/
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN go get -d -v ./...
|
||||
#RUN go build -v
|
||||
#RUN cd cmd/frankenphp && go install -v ./...
|
||||
|
||||
#CMD ["frankenphp"]
|
||||
79
README.md
Normal file
79
README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Caddy PHP
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
### Docker
|
||||
|
||||
The easiest way to get started is to use our Docker image:
|
||||
|
||||
```
|
||||
docker build -t frankenphp .
|
||||
```
|
||||
|
||||
### Compile fron Sources
|
||||
|
||||
#### Install PHP
|
||||
|
||||
Most distributions doesn't provide packages containing ZTS builds of PHP.
|
||||
Because the Go HTTP server uses goroutines, a ZTS build is needed.
|
||||
|
||||
Start by [downloading the latest version of PHP](https://www.php.net/downloads.php),
|
||||
then follow the instructions according to your operating system.
|
||||
|
||||
##### Linux
|
||||
|
||||
```
|
||||
./configure --enable-embed --enable-zts
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
##### Mac
|
||||
|
||||
```
|
||||
brew install libiconv
|
||||
./configure \
|
||||
--enable-zts \
|
||||
--enable-embed=dylib \
|
||||
--with-iconv=/opt/homebrew/opt/libiconv/ \
|
||||
--without-pcre-jit
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
Then, you also need to build a Mac-compatible PHP shared library.
|
||||
As the standard PHP distribution doesn't provide one, you need to do a few extra steps:
|
||||
|
||||
Start by adding those lines at the end of the `Makefile`:
|
||||
|
||||
```
|
||||
libs/libphp.dylib: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(LIBTOOL) --mode=link $(CC) -dynamiclib $(LIBPHP_CFLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@
|
||||
-@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```
|
||||
make libs/libphp.dylib
|
||||
sudo cp libs/libphp.dylib /usr/local/lib/
|
||||
```
|
||||
|
||||
#### Compile the Go App
|
||||
|
||||
```
|
||||
go get -d -v ./...
|
||||
go build -v
|
||||
```
|
||||
|
||||
## Misc Dev Resources
|
||||
|
||||
* [PHP embedding in uWSGI](https://github.com/unbit/uwsgi/blob/master/plugins/php/php_plugin.c)
|
||||
* [PHP embedding in NGINX Unit](https://github.com/nginx/unit/blob/master/src/nxt_php_sapi.c)
|
||||
* [PHP embedding in Go (go-php)](https://github.com/deuill/go-php)
|
||||
* [PHP embedding in Go (GoEmPHP)](https://github.com/mikespook/goemphp)
|
||||
* [PHP embedding in C++](https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7)
|
||||
* [Extending and Embedding PHP by Sara Golemon](https://books.google.fr/books?id=zMbGvK17_tYC&pg=PA254&lpg=PA254#v=onepage&q&f=false)
|
||||
* [What the heck is TSRMLS_CC, anyway?](http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html)
|
||||
* [PHP embedding on Mac](https://gist.github.com/jonnywang/61427ffc0e8dde74fff40f479d147db4)
|
||||
71
caddy.go
Normal file
71
caddy.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Package frankenphp provide a PHP module for Caddy.
|
||||
// FrankenPHP embeds the PHP interpreter directly in Caddy, giving it the ability to run your PHP scripts directly.
|
||||
// No PHP FPM required!
|
||||
package frankenphp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterModule(FrankenPHP{})
|
||||
httpcaddyfile.RegisterHandlerDirective("php", parseCaddyfile)
|
||||
}
|
||||
|
||||
type FrankenPHP struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// CaddyModule returns the Caddy module information.
|
||||
func (FrankenPHP) CaddyModule() caddy.ModuleInfo {
|
||||
return caddy.ModuleInfo{
|
||||
ID: "http.handlers.php",
|
||||
New: func() caddy.Module { return new(FrankenPHP) },
|
||||
}
|
||||
}
|
||||
|
||||
// Provision sets up the module.
|
||||
func (f *FrankenPHP) Provision(ctx caddy.Context) error {
|
||||
f.logger = ctx.Logger(f)
|
||||
Startup()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FrankenPHP) Cleanup() error {
|
||||
Shutdown()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeHTTP implements caddyhttp.MiddlewareHandler.
|
||||
func (f FrankenPHP) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
|
||||
w.Write([]byte("Hello World"))
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
|
||||
func (m *FrankenPHP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseCaddyfile unmarshals tokens from h into a new Middleware.
|
||||
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
|
||||
var m FrankenPHP
|
||||
err := m.UnmarshalCaddyfile(h.Dispenser)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// Interface guards
|
||||
var (
|
||||
_ caddy.Provisioner = (*FrankenPHP)(nil)
|
||||
_ caddy.CleanerUpper = (*FrankenPHP)(nil)
|
||||
_ caddyhttp.MiddlewareHandler = (*FrankenPHP)(nil)
|
||||
_ caddyfile.Unmarshaler = (*FrankenPHP)(nil)
|
||||
)
|
||||
27
caddy_test.go
Normal file
27
caddy_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package frankenphp_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/caddyserver/caddy/v2/caddytest"
|
||||
)
|
||||
|
||||
func TestPHP(t *testing.T) {
|
||||
tester := caddytest.NewTester(t)
|
||||
tester.InitServer(`
|
||||
{
|
||||
http_port 9080
|
||||
https_port 9443
|
||||
}
|
||||
localhost:9080 {
|
||||
route {
|
||||
php
|
||||
|
||||
respond 404
|
||||
}
|
||||
}
|
||||
`, "caddyfile")
|
||||
|
||||
tester.AssertGetResponse("http://localhost:9080", http.StatusOK, "Hello World")
|
||||
}
|
||||
4
cmd/frankenphp/main.go
Normal file
4
cmd/frankenphp/main.go
Normal file
@@ -0,0 +1,4 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
}
|
||||
146
frankenphp.c
Normal file
146
frankenphp.c
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <errno.h>
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_variables.h"
|
||||
|
||||
static int frankenphp_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
return php_module_startup(sapi_module, NULL, 0);
|
||||
}
|
||||
|
||||
static int frankenphp_deactivate(void)
|
||||
{
|
||||
// TODO: flush everything
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static size_t frankenphp_ub_write(const char *str, size_t str_length)
|
||||
{
|
||||
// TODO: call the Go writer
|
||||
|
||||
return str_length;
|
||||
}
|
||||
|
||||
static void frankenphp_flush(void *server_context)
|
||||
{
|
||||
// TODO: call the Go flusher
|
||||
}
|
||||
|
||||
static void frankenphp_send_header(sapi_header_struct *sapi_header, void *server_context)
|
||||
{
|
||||
// TODO: call the Go set header
|
||||
}
|
||||
|
||||
static char* frankenphp_read_cookies(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void frankenphp_register_variables(zval *track_vars_array)
|
||||
{
|
||||
php_import_environment_variables(track_vars_array);
|
||||
}
|
||||
|
||||
static void frankenphp_log_message(const char *message, int syslog_type_int)
|
||||
{
|
||||
// TODO: call Go logger
|
||||
}
|
||||
|
||||
sapi_module_struct frankenphp_module = {
|
||||
"frankenphp", /* name */
|
||||
"FrankenPHP SAPI for Go and Caddy", /* pretty name */
|
||||
|
||||
frankenphp_startup, /* startup */
|
||||
php_module_shutdown_wrapper, /* shutdown */
|
||||
|
||||
NULL, /* activate */
|
||||
frankenphp_deactivate, /* deactivate */
|
||||
|
||||
frankenphp_ub_write, /* unbuffered write */
|
||||
frankenphp_flush, /* flush */
|
||||
NULL, /* get uid */
|
||||
NULL, /* getenv */
|
||||
|
||||
php_error, /* error handler */
|
||||
|
||||
NULL, /* header handler */
|
||||
NULL, /* send headers handler */
|
||||
frankenphp_send_header, /* send header handler */
|
||||
|
||||
NULL, /* read POST data */
|
||||
frankenphp_read_cookies, /* read Cookies */
|
||||
|
||||
frankenphp_register_variables, /* register server variables */
|
||||
frankenphp_log_message, /* Log message */
|
||||
NULL, /* Get request time */
|
||||
NULL, /* Child terminate */
|
||||
|
||||
STANDARD_SAPI_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
int frankenphp_init() {
|
||||
#ifndef ZTS
|
||||
return FAILURE;
|
||||
#endif
|
||||
|
||||
// TODO: copied from php_embed.c, check if this is really necessary in our case
|
||||
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
|
||||
that sockets created via fsockopen()
|
||||
don't kill PHP if the remote site
|
||||
closes it. in apache|apxs mode apache
|
||||
does that for us! thies@thieso.net
|
||||
20000419 */
|
||||
|
||||
php_tsrm_startup();
|
||||
# ifdef PHP_WIN32
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
# endif
|
||||
|
||||
zend_signal_startup();
|
||||
sapi_startup(&frankenphp_module);
|
||||
|
||||
if (frankenphp_module.startup(&frankenphp_module) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void frankenphp_shutdown()
|
||||
{
|
||||
php_module_shutdown();
|
||||
sapi_shutdown();
|
||||
tsrm_shutdown();
|
||||
}
|
||||
|
||||
int frankenphp_request_startup() {
|
||||
if (php_request_startup() == FAILURE) {
|
||||
php_request_shutdown(NULL);
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int frankenphp_execute_script(const char* file_name)
|
||||
{
|
||||
int status = FAILURE;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
zend_stream_init_filename(&file_handle, file_name);
|
||||
|
||||
zend_first_try {
|
||||
status = php_execute_script(&file_handle);
|
||||
} zend_catch {
|
||||
/* int exit_status = EG(exit_status); */ \
|
||||
} zend_end_try();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void frankenphp_request_shutdown()
|
||||
{
|
||||
php_request_shutdown(NULL);
|
||||
}
|
||||
38
frankenphp.go
Normal file
38
frankenphp.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package frankenphp
|
||||
|
||||
// #cgo CFLAGS: -Wall -Wno-unused-variable -g
|
||||
// #cgo CFLAGS: -I/usr/local/include/php -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/main
|
||||
// #cgo LDFLAGS: -L/usr/local/lib -lphp
|
||||
// #include <stdlib.h>
|
||||
// #include "frankenphp.h"
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func Startup() error {
|
||||
if C.frankenphp_init() < 0 {
|
||||
return fmt.Errorf(`ZTS is not enabled, recompile PHP using the "--enable-zts" configuration option`)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Shutdown() {
|
||||
C.frankenphp_shutdown()
|
||||
}
|
||||
|
||||
func ExecuteScript(fileName string) error {
|
||||
if C.frankenphp_request_startup() < 0 {
|
||||
return fmt.Errorf("error during PHP request startup")
|
||||
}
|
||||
|
||||
cFileName := C.CString(fileName)
|
||||
defer C.free(unsafe.Pointer(cFileName))
|
||||
C.frankenphp_execute_script(cFileName)
|
||||
|
||||
C.frankenphp_request_shutdown()
|
||||
|
||||
return nil
|
||||
}
|
||||
13
frankenphp.h
Normal file
13
frankenphp.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _FRANKENPPHP_H
|
||||
#define _FRANKENPPHP_H
|
||||
|
||||
int frankenphp_init();
|
||||
void frankenphp_shutdown();
|
||||
|
||||
int frankenphp_request_startup();
|
||||
int frankenphp_request_shutdown();
|
||||
|
||||
int frankenphp_execute_script(const char* file_name);
|
||||
int frankenphp_request_shutdown();
|
||||
|
||||
#endif
|
||||
21
frankenphp_test.go
Normal file
21
frankenphp_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package frankenphp_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStartup(t *testing.T) {
|
||||
defer frankenphp.Shutdown()
|
||||
assert.Nil(t, frankenphp.Startup())
|
||||
}
|
||||
|
||||
func TestExecuteString(t *testing.T) {
|
||||
defer frankenphp.Shutdown()
|
||||
require.Nil(t, frankenphp.Startup())
|
||||
|
||||
assert.Nil(t, frankenphp.ExecuteScript("testdata/index.php"))
|
||||
}
|
||||
113
go.mod
Normal file
113
go.mod
Normal file
@@ -0,0 +1,113 @@
|
||||
module github.com/dunglas/frankenphp
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/caddyserver/caddy/v2 v2.4.5
|
||||
go.uber.org/zap v1.19.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
||||
github.com/alecthomas/chroma v0.9.2 // indirect
|
||||
github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f // indirect
|
||||
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/caddyserver/certmagic v0.14.5 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgraph-io/badger v1.6.2 // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||
github.com/go-kit/kit v0.10.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/cel-go v0.7.3 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.1 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
|
||||
github.com/klauspost/compress v1.13.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/lucas-clemente/quic-go v0.23.0 // indirect
|
||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||
github.com/manifoldco/promptui v0.8.0 // indirect
|
||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mholt/acmez v1.0.0 // indirect
|
||||
github.com/micromdm/scep/v2 v2.0.0 // indirect
|
||||
github.com/miekg/dns v1.1.42 // indirect
|
||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.1 // indirect
|
||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||
github.com/naoina/toml v0.1.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/rs/xid v1.2.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||
github.com/smallstep/certificates v0.16.4 // indirect
|
||||
github.com/smallstep/cli v0.16.1 // indirect
|
||||
github.com/smallstep/nosql v0.3.8 // indirect
|
||||
github.com/smallstep/truststore v0.9.6 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/stoewer/go-strcase v1.2.0 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/urfave/cli v1.22.5 // indirect
|
||||
github.com/yuin/goldmark v1.4.0 // indirect
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
||||
go.step.sm/cli-utils v0.4.1 // indirect
|
||||
go.step.sm/crypto v0.9.0 // indirect
|
||||
go.step.sm/linkedca v0.0.0-20210611183751-27424aae8d25 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/tools v0.1.5 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08 // indirect
|
||||
google.golang.org/grpc v1.38.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
|
||||
)
|
||||
3
testdata/index.php
vendored
Normal file
3
testdata/index.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'I am by birth a Genevese';
|
||||
Reference in New Issue
Block a user