Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide PHP with the raw POST body #105

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 1 addition & 120 deletions src/php-wasm/__tests__/php-server.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,11 @@
import * as phpLoaderModule from '../../../build/php.node.js';
import * as phpLoaderModule from '../../../build/php-5.6.node.js';
import { startPHP } from '../php';
import { PHPServer } from '../php-server';

const { TextEncoder, TextDecoder } = require('util');
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

describe('PHP Server – boot', () => {
beforeAll(() => {
// Shim the user agent for the server
(global as any).navigator = { userAgent: '' };
});

it('should boot', async () => {
const php = await startPHP(phpLoaderModule, 'NODE');
php.mkdirTree('/tests');
const server = new PHPServer(php, {
documentRoot: '/tests',
absoluteUrl: 'http://localhost/',
isStaticFilePath: (path) => path.startsWith('/uploads'),
});

server.php.writeFile(
'/tests/upload.php',
`<?php echo json_encode([
'files' => $_FILES,
'is_uploaded' => is_uploaded_file($_FILES['file_txt']['tmp_name'])
]);`
);
const response = await server.request({
path: `/upload.php`,
method: 'POST',
_POST: {},
files: {
file_txt: new File(['Hello world'], 'file.txt'),
},
});
const bodyText = new TextDecoder().decode(response.body);
expect(JSON.parse(bodyText)).toEqual({
files: {
file_txt: {
name: 'file.txt',
type: 'text/plain',
tmp_name: expect.any(String),
error: '0',
size: '1',
},
},
is_uploaded: true,
});
});
});

describe('PHP Server – requests', () => {
beforeAll(() => {
// Shim the user agent for the server
Expand Down Expand Up @@ -96,77 +50,4 @@ describe('PHP Server – requests', () => {
},
});
});

it('should parse FILES arrays in a PHP way', async () => {
server.php.writeFile(
'/tests/upload.php',
`<?php echo json_encode([
'files' => $_FILES,
'is_uploaded' => is_uploaded_file($_FILES['file_txt']['first']['tmp_name'])
]);`
);
const response = await server.request({
path: `/upload.php`,
method: 'POST',
_POST: {},
files: {
'file_txt[first]': new File(['Hello world'], 'file.txt'),
},
});
const bodyText = new TextDecoder().decode(response.body);
expect(JSON.parse(bodyText)).toEqual({
files: {
file_txt: {
first: {
name: 'file.txt',
type: 'text/plain',
tmp_name: expect.any(String),
error: '0',
size: '1',
},
},
},
is_uploaded: true,
});
});
});

// Shim the browser's file class
class File {
data;
name;

constructor(data, name) {
this.data = data;
this.name = name;
}

get size() {
return this.data.length;
}

get type() {
return 'text/plain';
}

arrayBuffer() {
return dataToArrayBuffer(this.data);
}
}

function dataToArrayBuffer(data) {
if (typeof data === 'string') {
return new TextEncoder().encode(data).buffer;
} else if (data instanceof ArrayBuffer) {
data = new Uint8Array(data);
} else if (Array.isArray(data)) {
if (data[0] instanceof Number) {
return new Uint8Array(data);
}
return dataToArrayBuffer(data[0]);
} else if (data instanceof Uint8Array) {
return data.buffer;
} else {
throw new Error('Unsupported data type');
}
}
100 changes: 99 additions & 1 deletion src/php-wasm/__tests__/php.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as phpLoaderModule from '../../../build/php.node.js';
import * as phpLoaderModule from '../../../build/php-5.6.node.js';
import { startPHP } from '../php';

const { TextEncoder, TextDecoder } = require('util');
Expand Down Expand Up @@ -151,3 +151,101 @@ describe('PHP – stdio', () => {
});
});
});

describe('PHP Server – requests', () => {
beforeAll(() => {
// Shim the user agent for the server
(global as any).navigator = { userAgent: '' };
});

let php, server;
beforeEach(async () => {
php = await startPHP(phpLoaderModule, 'NODE');
php.mkdirTree('/tests');
});

it('should parse FILES arrays in a PHP way', async () => {
const response = php.run(
`<?php echo json_encode([
'files' => $_FILES,
'is_uploaded' => is_uploaded_file($_FILES['file_txt']['first']['tmp_name'])
]);`,
{
method: 'POST',
uploadedFiles: await php.uploadFiles({
'file_txt[first]': new File(['Hello world'], 'file.txt'),
}),
}
);
const bodyText = new TextDecoder().decode(response.stdout);
expect(JSON.parse(bodyText)).toEqual({
files: {
file_txt: {
first: {
name: 'file.txt',
type: 'text/plain',
tmp_name: expect.any(String),
error: '0',
size: '1',
},
},
},
is_uploaded: true,
});
});

it('Should have access to raw POST data', async () => {
const response = await php.run(
`<?php
$fp = fopen('php://input', 'r');
echo fread($fp, 100);
fclose($fp);
`,
{
requestBody: '{"foo": "bar"}',
}
);
const bodyText = new TextDecoder().decode(response.stdout);
expect(bodyText).toEqual('{"foo": "bar"}');
});
});

// Shim the browser's file class
class File {
data;
name;

constructor(data, name) {
this.data = data;
this.name = name;
}

get size() {
return this.data.length;
}

get type() {
return 'text/plain';
}

arrayBuffer() {
return new ArrayBuffer(toUint8Array(this.data));
}
}

function toUint8Array(data) {
if (typeof data === 'string') {
return new TextEncoder().encode(data).buffer;
} else if (data instanceof ArrayBuffer) {
data = new Uint8Array(data);
} else if (Array.isArray(data)) {
if (data[0] instanceof Number) {
return new Uint8Array(data);
}
return toUint8Array(data[0]);
} else if (data instanceof Uint8Array) {
return data.buffer;
} else {
throw new Error('Unsupported data type');
}
}
Loading