Skip to content

Commit 98573ed

Browse files
refactor: extract the state module and make the backoff error instead of panic
This PR: - moves state.go to its own module - moves the phpheaders test the phpheaders module - simplifies backoff.go - makes the backoff error instead of panic (so it can be tested) - removes some unused C structs
1 parent 16e2bbb commit 98573ed

23 files changed

Lines changed: 271 additions & 338 deletions

backoff.go

Lines changed: 0 additions & 51 deletions
This file was deleted.

backoff_test.go

Lines changed: 0 additions & 41 deletions
This file was deleted.

cgi.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,13 @@ func splitPos(path string, splitPath []string) int {
277277
// See: https://github.com/php/php-src/blob/345e04b619c3bc11ea17ee02cdecad6ae8ce5891/main/SAPI.h#L72
278278
//
279279
//export go_update_request_info
280-
func go_update_request_info(threadIndex C.uintptr_t, info *C.sapi_request_info) C.bool {
280+
func go_update_request_info(threadIndex C.uintptr_t, info *C.sapi_request_info) {
281281
thread := phpThreads[threadIndex]
282282
fc := thread.frankenPHPContext()
283283
request := fc.request
284284

285285
if request == nil {
286-
return C.bool(fc.worker != nil)
286+
return
287287
}
288288

289289
authUser, authPassword, ok := request.BasicAuth()
@@ -311,8 +311,6 @@ func go_update_request_info(threadIndex C.uintptr_t, info *C.sapi_request_info)
311311
info.request_uri = thread.pinCString(request.URL.RequestURI())
312312

313313
info.proto_num = C.int(request.ProtoMajor*1000 + request.ProtoMinor)
314-
315-
return C.bool(fc.worker != nil)
316314
}
317315

318316
// SanitizedPathJoin performs filepath.Join(root, reqPath) that

debugstate.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package frankenphp
22

3+
import (
4+
"github.com/dunglas/frankenphp/internal/state"
5+
)
6+
37
// EXPERIMENTAL: ThreadDebugState prints the state of a single PHP thread - debugging purposes only
48
type ThreadDebugState struct {
59
Index int
@@ -23,7 +27,7 @@ func DebugState() FrankenPHPDebugState {
2327
ReservedThreadCount: 0,
2428
}
2529
for _, thread := range phpThreads {
26-
if thread.state.is(stateReserved) {
30+
if thread.state.Is(state.Reserved) {
2731
fullState.ReservedThreadCount++
2832
continue
2933
}
@@ -38,9 +42,9 @@ func threadDebugState(thread *phpThread) ThreadDebugState {
3842
return ThreadDebugState{
3943
Index: thread.threadIndex,
4044
Name: thread.name(),
41-
State: thread.state.name(),
42-
IsWaiting: thread.state.isInWaitingState(),
43-
IsBusy: !thread.state.isInWaitingState(),
44-
WaitingSinceMilliseconds: thread.state.waitTime(),
45+
State: thread.state.Name(),
46+
IsWaiting: thread.state.IsInWaitingState(),
47+
IsBusy: !thread.state.IsInWaitingState(),
48+
WaitingSinceMilliseconds: thread.state.WaitTime(),
4549
}
4650
}

env.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package frankenphp
22

33
// #cgo nocallback frankenphp_init_persistent_string
4-
// #cgo nocallback frankenphp_add_assoc_str_ex
54
// #cgo noescape frankenphp_init_persistent_string
6-
// #cgo noescape frankenphp_add_assoc_str_ex
75
// #include "frankenphp.h"
6+
// #include <Zend/zend_API.h>
87
import "C"
98
import (
109
"os"
@@ -98,7 +97,7 @@ func go_getfullenv(threadIndex C.uintptr_t, trackVarsArray *C.zval) {
9897
env := getSandboxedEnv(thread)
9998

10099
for key, val := range env {
101-
C.frankenphp_add_assoc_str_ex(trackVarsArray, toUnsafeChar(key), C.size_t(len(key)), val)
100+
C.add_assoc_str_ex(trackVarsArray, toUnsafeChar(key), C.size_t(len(key)), val)
102101
}
103102
}
104103

frankenphp.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ frankenphp_version frankenphp_get_version() {
5151

5252
frankenphp_config frankenphp_get_config() {
5353
return (frankenphp_config){
54-
frankenphp_get_version(),
5554
#ifdef ZTS
5655
true,
5756
#else
@@ -75,14 +74,18 @@ __thread uintptr_t thread_index;
7574
__thread bool is_worker_thread = false;
7675
__thread zval *os_environment = NULL;
7776

77+
void frankenphp_update_local_thread_context(bool is_worker) {
78+
is_worker_thread = is_worker;
79+
}
80+
7881
static void frankenphp_update_request_context() {
7982
/* the server context is stored on the go side, still SG(server_context) needs
8083
* to not be NULL */
8184
SG(server_context) = (void *)1;
8285
/* status It is not reset by zend engine, set it to 200. */
8386
SG(sapi_headers).http_response_code = 200;
8487

85-
is_worker_thread = go_update_request_info(thread_index, &SG(request_info));
88+
go_update_request_info(thread_index, &SG(request_info));
8689
}
8790

8891
static void frankenphp_free_request_context() {
@@ -206,11 +209,6 @@ PHPAPI void get_full_env(zval *track_vars_array) {
206209
go_getfullenv(thread_index, track_vars_array);
207210
}
208211

209-
void frankenphp_add_assoc_str_ex(zval *track_vars_array, char *key,
210-
size_t keylen, zend_string *val) {
211-
add_assoc_str_ex(track_vars_array, key, keylen, val);
212-
}
213-
214212
/* Adapted from php_request_startup() */
215213
static int frankenphp_worker_request_startup() {
216214
int retval = SUCCESS;
@@ -652,8 +650,9 @@ static char *frankenphp_read_cookies(void) {
652650
}
653651

654652
/* all variables with well defined keys can safely be registered like this */
655-
void frankenphp_register_trusted_var(zend_string *z_key, char *value,
656-
size_t val_len, HashTable *ht) {
653+
static inline void frankenphp_register_trusted_var(zend_string *z_key,
654+
char *value, size_t val_len,
655+
HashTable *ht) {
657656
if (value == NULL) {
658657
zval empty;
659658
ZVAL_EMPTY_STRING(&empty);

frankenphp.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ typedef struct ht_key_value_pair {
2323
size_t val_len;
2424
} ht_key_value_pair;
2525

26-
typedef struct php_variable {
27-
const char *var;
28-
size_t data_len;
29-
char *data;
30-
} php_variable;
31-
3226
typedef struct frankenphp_version {
3327
unsigned char major_version;
3428
unsigned char minor_version;
@@ -40,7 +34,6 @@ typedef struct frankenphp_version {
4034
frankenphp_version frankenphp_get_version();
4135

4236
typedef struct frankenphp_config {
43-
frankenphp_version version;
4437
bool zts;
4538
bool zend_signals;
4639
bool zend_max_execution_timers;
@@ -52,6 +45,7 @@ bool frankenphp_new_php_thread(uintptr_t thread_index);
5245

5346
bool frankenphp_shutdown_dummy_request(void);
5447
int frankenphp_execute_script(char *file_name);
48+
void frankenphp_update_local_thread_context(bool is_worker);
5549

5650
int frankenphp_execute_script_cli(char *script, int argc, char **argv,
5751
bool eval);
@@ -65,8 +59,6 @@ void frankenphp_register_variable_safe(char *key, char *var, size_t val_len,
6559
zend_string *frankenphp_init_persistent_string(const char *string, size_t len);
6660
int frankenphp_reset_opcache(void);
6761
int frankenphp_get_current_memory_limit();
68-
void frankenphp_add_assoc_str_ex(zval *track_vars_array, char *key,
69-
size_t keylen, zend_string *val);
7062

7163
void frankenphp_register_single(zend_string *z_key, char *value, size_t val_len,
7264
zval *track_vars_array);

frankenphp_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,12 @@ func testRequestHeaders(t *testing.T, opts *testOptions) {
618618
}
619619

620620
func TestFailingWorker(t *testing.T) {
621-
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
622-
body, _ := testGet("http://example.com/failing-worker.php", handler, t)
623-
assert.Contains(t, body, "ok")
624-
}, &testOptions{workerScript: "failing-worker.php"})
621+
err := frankenphp.Init(
622+
frankenphp.WithLogger(slog.New(slog.NewTextHandler(io.Discard, nil))),
623+
frankenphp.WithWorkers("failing worker", "testdata/failing-worker.php", 4, frankenphp.WithWorkerMaxFailures(1)),
624+
frankenphp.WithNumThreads(5),
625+
)
626+
assert.Error(t, err, "should return an immediate error if workers fail on startup")
625627
}
626628

627629
func TestEnv(t *testing.T) {

internal/phpheaders/phpheaders.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package phpheaders
22

3+
import "C"
34
import (
45
"context"
56
"strings"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package phpheaders
2+
3+
import (
4+
"net/http/httptest"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestAllCommonHeadersAreCorrect(t *testing.T) {
11+
fakeRequest := httptest.NewRequest("GET", "http://localhost", nil)
12+
13+
for header, phpHeader := range CommonRequestHeaders {
14+
// verify that common and uncommon headers return the same result
15+
expectedPHPHeader := GetUnCommonHeader(t.Context(), header)
16+
assert.Equal(t, phpHeader+"\x00", expectedPHPHeader, "header is not well formed: "+phpHeader)
17+
18+
// net/http will capitalize lowercase headers, verify that headers are capitalized
19+
fakeRequest.Header.Add(header, "foo")
20+
assert.Contains(t, fakeRequest.Header, header, "header is not correctly capitalized: "+header)
21+
}
22+
}

0 commit comments

Comments
 (0)