mirror of
https://github.com/php/frankenphp.git
synced 2026-04-29 03:53:13 +02:00
Calls 'update_request_info' from the C side.
This commit is contained in:
@@ -21,6 +21,16 @@ import (
|
||||
"github.com/dunglas/frankenphp/internal/phpheaders"
|
||||
)
|
||||
|
||||
// Map of supported protocols to Apache ssl_mod format
|
||||
// Note that these are slightly different from SupportedProtocols in caddytls/config.go
|
||||
var tlsProtocolStrings = map[uint16]string{
|
||||
tls.VersionTLS10: "TLSv1",
|
||||
tls.VersionTLS11: "TLSv1.1",
|
||||
tls.VersionTLS12: "TLSv1.2",
|
||||
tls.VersionTLS13: "TLSv1.3",
|
||||
}
|
||||
|
||||
// List of all keys in the $_SERVER array excluding headers and environment variables.
|
||||
var knownServerKeys = []string{
|
||||
"CONTENT_LENGTH",
|
||||
"DOCUMENT_ROOT",
|
||||
@@ -264,13 +274,47 @@ func splitPos(path string, splitPath []string) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// Map of supported protocols to Apache ssl_mod format
|
||||
// Note that these are slightly different from SupportedProtocols in caddytls/config.go
|
||||
var tlsProtocolStrings = map[uint16]string{
|
||||
tls.VersionTLS10: "TLSv1",
|
||||
tls.VersionTLS11: "TLSv1.1",
|
||||
tls.VersionTLS12: "TLSv1.2",
|
||||
tls.VersionTLS13: "TLSv1.3",
|
||||
// update the sapi_request_info struct
|
||||
// see: https://github.com/php/php-src/blob/345e04b619c3bc11ea17ee02cdecad6ae8ce5891/main/SAPI.h#L72
|
||||
//
|
||||
//export go_update_request_info
|
||||
func go_update_request_info(threadIndex C.uintptr_t, info *C.sapi_request_info) {
|
||||
thread := phpThreads[threadIndex]
|
||||
fc := thread.getRequestContext()
|
||||
request := fc.request
|
||||
|
||||
authUser, authPassword, ok := request.BasicAuth()
|
||||
if ok && authPassword != "" {
|
||||
info.auth_password = thread.pinCString(authPassword)
|
||||
}
|
||||
if ok && authUser != "" {
|
||||
info.auth_user = thread.pinCString(authUser)
|
||||
}
|
||||
|
||||
info.request_method = thread.pinCString(request.Method)
|
||||
info.query_string = thread.pinCString(request.URL.RawQuery)
|
||||
info.content_length = C.zend_long(request.ContentLength)
|
||||
|
||||
contentType := request.Header.Get("Content-Type")
|
||||
if contentType != "" {
|
||||
info.content_type = thread.pinCString(contentType)
|
||||
}
|
||||
|
||||
if fc.pathInfo != "" {
|
||||
info.path_translated = thread.pinCString(sanitizedPathJoin(fc.documentRoot, fc.pathInfo)) // Info: http://www.oreilly.com/openbook/cgi/ch02_04.html
|
||||
}
|
||||
|
||||
info.request_uri = thread.pinCString(request.URL.RequestURI())
|
||||
|
||||
info.proto_num = C.int(request.ProtoMajor*1000 + request.ProtoMinor)
|
||||
}
|
||||
|
||||
//export go_is_worker_request
|
||||
func go_is_worker_request(threadIndex C.uintptr_t) C.bool {
|
||||
thread := phpThreads[threadIndex]
|
||||
fc := thread.getRequestContext()
|
||||
|
||||
return C.bool(fc.worker != nil)
|
||||
}
|
||||
|
||||
// SanitizedPathJoin performs filepath.Join(root, reqPath) that
|
||||
|
||||
+15
-31
@@ -75,6 +75,16 @@ __thread uintptr_t thread_index;
|
||||
__thread bool is_worker_thread = false;
|
||||
__thread zval *os_environment = NULL;
|
||||
|
||||
static void frankenphp_update_request_context(){
|
||||
// update server context here ?
|
||||
SG(server_context) = (void *)1;
|
||||
// It is not reset by zend engine, set it to 200.
|
||||
SG(sapi_headers).http_response_code = 200;
|
||||
|
||||
go_update_request_info(thread_index, &SG(request_info));
|
||||
is_worker_thread = go_is_worker_request(thread_index);
|
||||
}
|
||||
|
||||
static void frankenphp_free_request_context() {
|
||||
if (SG(request_info).cookie_data != NULL) {
|
||||
free(SG(request_info).cookie_data);
|
||||
@@ -174,6 +184,8 @@ void frankenphp_add_assoc_str_ex(zval *track_vars_array, char *key,
|
||||
static int frankenphp_worker_request_startup() {
|
||||
int retval = SUCCESS;
|
||||
|
||||
frankenphp_update_request_context();
|
||||
|
||||
zend_try {
|
||||
frankenphp_destroy_super_globals();
|
||||
frankenphp_release_temporary_streams();
|
||||
@@ -507,36 +519,8 @@ static void frankenphp_request_shutdown() {
|
||||
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_ENV]);
|
||||
array_init(&PG(http_globals)[TRACK_VARS_ENV]);
|
||||
}
|
||||
php_request_shutdown((void *)0);
|
||||
frankenphp_free_request_context();
|
||||
}
|
||||
|
||||
int frankenphp_update_server_context(bool is_worker_request,
|
||||
|
||||
const char *request_method,
|
||||
char *query_string,
|
||||
zend_long content_length,
|
||||
char *path_translated, char *request_uri,
|
||||
const char *content_type, char *auth_user,
|
||||
char *auth_password, int proto_num) {
|
||||
|
||||
SG(server_context) = (void *)1;
|
||||
is_worker_thread = is_worker_request;
|
||||
|
||||
// It is not reset by zend engine, set it to 200.
|
||||
SG(sapi_headers).http_response_code = 200;
|
||||
|
||||
SG(request_info).auth_password = auth_password;
|
||||
SG(request_info).auth_user = auth_user;
|
||||
SG(request_info).request_method = request_method;
|
||||
SG(request_info).query_string = query_string;
|
||||
SG(request_info).content_type = content_type;
|
||||
SG(request_info).content_length = content_length;
|
||||
SG(request_info).path_translated = path_translated;
|
||||
SG(request_info).request_uri = request_uri;
|
||||
SG(request_info).proto_num = proto_num;
|
||||
|
||||
return SUCCESS;
|
||||
php_request_shutdown((void *)0);
|
||||
}
|
||||
|
||||
static int frankenphp_startup(sapi_module_struct *sapi_module) {
|
||||
@@ -974,7 +958,8 @@ bool frankenphp_new_php_thread(uintptr_t thread_index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int frankenphp_request_startup() {
|
||||
static int frankenphp_request_startup() {
|
||||
frankenphp_update_request_context();
|
||||
if (php_request_startup() == SUCCESS) {
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -1014,7 +999,6 @@ int frankenphp_execute_script(char *file_name) {
|
||||
|
||||
zend_destroy_file_handle(&file_handle);
|
||||
|
||||
frankenphp_free_request_context();
|
||||
frankenphp_request_shutdown();
|
||||
|
||||
return status;
|
||||
|
||||
@@ -12,8 +12,6 @@ package frankenphp
|
||||
//
|
||||
// We also set these flags for hardening: https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59
|
||||
|
||||
// #cgo nocallback frankenphp_update_server_context
|
||||
// #cgo noescape frankenphp_update_server_context
|
||||
// #include <stdlib.h>
|
||||
// #include <stdint.h>
|
||||
// #include <php_variables.h>
|
||||
@@ -32,7 +30,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -317,66 +314,6 @@ func Shutdown() {
|
||||
logger.Debug("FrankenPHP shut down")
|
||||
}
|
||||
|
||||
func updateServerContext(thread *phpThread, fc *frankenPHPContext, isWorkerRequest bool) error {
|
||||
request := fc.request
|
||||
authUser, authPassword, ok := request.BasicAuth()
|
||||
var cAuthUser, cAuthPassword *C.char
|
||||
if ok && authPassword != "" {
|
||||
cAuthPassword = thread.pinCString(authPassword)
|
||||
}
|
||||
if ok && authUser != "" {
|
||||
cAuthUser = thread.pinCString(authUser)
|
||||
}
|
||||
|
||||
cMethod := thread.pinCString(request.Method)
|
||||
cQueryString := thread.pinCString(request.URL.RawQuery)
|
||||
contentLengthStr := request.Header.Get("Content-Length")
|
||||
contentLength := 0
|
||||
if contentLengthStr != "" {
|
||||
var err error
|
||||
contentLength, err = strconv.Atoi(contentLengthStr)
|
||||
if err != nil || contentLength < 0 {
|
||||
return fmt.Errorf("invalid Content-Length header: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
contentType := request.Header.Get("Content-Type")
|
||||
var cContentType *C.char
|
||||
if contentType != "" {
|
||||
cContentType = thread.pinCString(contentType)
|
||||
}
|
||||
|
||||
// compliance with the CGI specification requires that
|
||||
// PATH_TRANSLATED should only exist if PATH_INFO is defined.
|
||||
// Info: https://www.ietf.org/rfc/rfc3875 Page 14
|
||||
var cPathTranslated *C.char
|
||||
if fc.pathInfo != "" {
|
||||
cPathTranslated = thread.pinCString(sanitizedPathJoin(fc.documentRoot, fc.pathInfo)) // Info: http://www.oreilly.com/openbook/cgi/ch02_04.html
|
||||
}
|
||||
|
||||
cRequestUri := thread.pinCString(request.URL.RequestURI())
|
||||
|
||||
ret := C.frankenphp_update_server_context(
|
||||
C.bool(isWorkerRequest || fc.responseWriter == nil),
|
||||
|
||||
cMethod,
|
||||
cQueryString,
|
||||
C.zend_long(contentLength),
|
||||
cPathTranslated,
|
||||
cRequestUri,
|
||||
cContentType,
|
||||
cAuthUser,
|
||||
cAuthPassword,
|
||||
C.int(request.ProtoMajor*1000+request.ProtoMinor),
|
||||
)
|
||||
|
||||
if ret > 0 {
|
||||
return ErrRequestContextCreation
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeHTTP executes a PHP script according to the given context and options.
|
||||
func ServeHTTP(responseWriter http.ResponseWriter, request *http.Request, opts ...RequestOption) error {
|
||||
if !isRunning {
|
||||
|
||||
Reference in New Issue
Block a user