Skip to content

Commit

Permalink
PHP: Remove addServerGlobalEntry() method, accept $_SERVER as php.run…
Browse files Browse the repository at this point in the history
…() property (#1286)

Removes the public `php.addServerGlobalEntry()` method in favor of a new
`$_SERVER` property for `PHPRequest`. The provided `$_SERVER` entries
only affected the next `run()` call so making them a part of the `run()`
argument is more natural.

## What problem does this solve?

This PR reduces the amount of state stored in the `BasePHP` class,
simplifying [the PHPProcessManager
explorations](#1287).

## Testing instructions

Confirm the unit and e2e tests pass.
  • Loading branch information
adamziel authored Apr 21, 2024
1 parent 289ec39 commit 23c0fc6
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 50 deletions.
112 changes: 69 additions & 43 deletions packages/php-wasm/universal/src/lib/base-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
#sapiName?: string;
#webSapiInitialized = false;
#wasmErrorsTarget: UnhandledRejectionsTarget | null = null;
#serverEntries: Record<string, string> = {};
#eventListeners: Map<string, Set<PHPEventListener>> = new Map();
#messageListeners: MessageListener[] = [];
requestHandler?: PHPBrowser;
Expand Down Expand Up @@ -271,15 +270,28 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
const headers = normalizeHeaders(request.headers || {});
const host = headers['host'] || 'example.com:443';

this.#setRequestHostAndProtocol(host, request.protocol || 'http');
const port = this.#inferPortFromHostAndProtocol(
host,
request.protocol || 'http'
);
this.#setRequestHost(host);
this.#setRequestPort(port);
this.#setRequestHeaders(headers);
if (request.body) {
heapBodyPointer = this.#setRequestBody(request.body);
}
if (typeof request.code === 'string') {
this.#setPHPCode(' ?>' + request.code);
}
this.#addServerGlobalEntriesInWasm();

const $_SERVER = this.#prepareServerEntries(
request.$_SERVER,
headers,
port
);
for (const key in $_SERVER) {
this.#setServerGlobalEntry(key, $_SERVER![key]);
}

const env = request.env || {};
for (const key in env) {
Expand Down Expand Up @@ -321,6 +333,40 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
}
}

/**
* Prepares the $_SERVER entries for the PHP runtime.
*
* @param defaults Default entries to include in $_SERVER.
* @param headers HTTP headers to include in $_SERVER (as HTTP_ prefixed entries).
* @param port HTTP port, used to determine infer $_SERVER['HTTPS'] value if none
* was provided.
* @returns Computed $_SERVER entries.
*/
#prepareServerEntries(
defaults: Record<string, string> | undefined,
headers: PHPRequestHeaders,
port: number
): Record<string, string> {
const $_SERVER = {
...(defaults || {}),
};
$_SERVER['HTTPS'] = $_SERVER['HTTPS'] || port === 443 ? 'on' : 'off';
for (const name in headers) {
let HTTP_prefix = 'HTTP_';
/**
* Some headers are special and don't have the HTTP_ prefix.
*/
if (
['content-type', 'content-length'].includes(name.toLowerCase())
) {
HTTP_prefix = '';
}
$_SERVER[`${HTTP_prefix}${name.toUpperCase().replace(/-/g, '_')}`] =
headers[name];
}
return $_SERVER;
}

#initWebRuntime() {
/**
* This creates a consts.php file in an in-memory
Expand Down Expand Up @@ -412,14 +458,25 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
}
}

#setRequestHostAndProtocol(host: string, protocol: string) {
#setRequestHost(host: string) {
this[__private__dont__use].ccall(
'wasm_set_request_host',
null,
[STRING],
[host]
);
}

#setRequestPort(port: number) {
this[__private__dont__use].ccall(
'wasm_set_request_port',
null,
[NUMBER],
[port]
);
}

#inferPortFromHostAndProtocol(host: string, protocol: string) {
let port;
try {
port = parseInt(new URL(host).port, 10);
Expand All @@ -430,16 +487,7 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
if (!port || isNaN(port) || port === 80) {
port = protocol === 'https' ? 443 : 80;
}
this[__private__dont__use].ccall(
'wasm_set_request_port',
null,
[NUMBER],
[port]
);

if (protocol === 'https' || (!protocol && port === 443)) {
this.addServerGlobalEntry('HTTPS', 'on');
}
return port;
}

#setRequestMethod(method: string) {
Expand Down Expand Up @@ -476,21 +524,6 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
[parseInt(headers['content-length'], 10)]
);
}
for (const name in headers) {
let HTTP_prefix = 'HTTP_';
/**
* Some headers are special and don't have the HTTP_ prefix.
*/
if (
['content-type', 'content-length'].includes(name.toLowerCase())
) {
HTTP_prefix = '';
}
this.addServerGlobalEntry(
`${HTTP_prefix}${name.toUpperCase().replace(/-/g, '_')}`,
headers[name]
);
}
}

#setRequestBody(body: string | Uint8Array) {
Expand Down Expand Up @@ -547,19 +580,13 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
);
}

addServerGlobalEntry(key: string, value: string) {
this.#serverEntries[key] = value;
}

#addServerGlobalEntriesInWasm() {
for (const key in this.#serverEntries) {
this[__private__dont__use].ccall(
'wasm_add_SERVER_entry',
null,
[STRING, STRING],
[key, this.#serverEntries[key]]
);
}
#setServerGlobalEntry(key: string, value: string) {
this[__private__dont__use].ccall(
'wasm_add_SERVER_entry',
null,
[STRING, STRING],
[key, value]
);
}

#setEnv(name: string, value: string) {
Expand Down Expand Up @@ -665,7 +692,6 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
throw rethrown;
} finally {
this.#wasmErrorsTarget?.removeEventListener('error', errorListener);
this.#serverEntries = {};
}

const { headers, httpStatusCode } = this.#getResponseHeaders();
Expand Down
14 changes: 7 additions & 7 deletions packages/php-wasm/universal/src/lib/php-request-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,6 @@ export class PHPRequestHandler implements RequestHandler {
*/
const release = await this.#semaphore.acquire();
try {
this.php.addServerGlobalEntry('REMOTE_ADDR', '127.0.0.1');
this.php.addServerGlobalEntry('DOCUMENT_ROOT', this.#DOCROOT);
this.php.addServerGlobalEntry(
'HTTPS',
this.#ABSOLUTE_URL.startsWith('https://') ? 'on' : ''
);

let preferredMethod: PHPRunOptions['method'] = 'GET';

const headers: Record<string, string> = {
Expand Down Expand Up @@ -254,6 +247,13 @@ export class PHPRequestHandler implements RequestHandler {
),
protocol: this.#PROTOCOL,
method: request.method || preferredMethod,
$_SERVER: {
REMOTE_ADDR: '127.0.0.1',
DOCUMENT_ROOT: this.#DOCROOT,
HTTPS: this.#ABSOLUTE_URL.startsWith('https://')
? 'on'
: '',
},
body,
scriptPath,
headers,
Expand Down
5 changes: 5 additions & 0 deletions packages/php-wasm/universal/src/lib/universal-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,11 @@ export interface PHPRunOptions {
*/
env?: Record<string, string>;

/**
* $_SERVER entries to set for this run.
*/
$_SERVER?: Record<string, string>;

/**
* The code snippet to eval instead of a php file.
*/
Expand Down

0 comments on commit 23c0fc6

Please sign in to comment.