Skip to content
Open
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
26 changes: 24 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,31 @@ jobs:

- name: Checkout
uses: actions/checkout@v3


# Runs before the Docker suites for fast feedback. Needs the root
# dependencies, not the ones in test/.
- name: Install root dependencies
run: npm install

- name: sqlite unit tests
# Serial: the test files share the plugin's hardcoded /tmp cache and
# etag paths, and node --test runs files in parallel processes.
run: node --test --test-concurrency=1 sqliteS3.concurrency.test.js sqliteVercelBlob.etag.test.js sqliteVercelBlob.concurrency.test.js
working-directory: ./test

- run: ./run-db-test.sh
working-directory: ./test

- run: ./run-s3-test.sh
working-directory: ./test
working-directory: ./test

- run: ./run-blob-test.sh
working-directory: ./test

# A warm container gets its ETag from its own upload and then only ever
# revalidates, so it never writes using a download's ETag. Cold instances
# do that on every first request, which is where conditional writes broke
# in production. BLOB_NO_CONDITIONAL_READS makes every read a full one.
- name: blob tests with cold-instance reads
run: BLOB_NO_CONDITIONAL_READS=1 ./run-blob-test.sh
working-directory: ./test
102 changes: 27 additions & 75 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,46 @@ const serverlesswp = require('serverlesswp');

const { validate } = require('../util/install.js');
const { setup } = require('../util/directory.js');
const sqliteS3 = require('../util/sqliteS3.js');
const storage = require('../util/storage.js');
const sandbox = require('../util/sandbox.js');
const readOnly = require('../util/readOnly.js');

const pathToWP = '/tmp/wp';
let initSqliteS3 = false;
const wpContentPath = pathToWP + '/wp-content';
const sqlitePluginPath = wpContentPath + '/plugins/sqlite-database-integration';

// Which database this deployment uses. See util/storage.js.
const database = storage.resolve();

const readOnlyActive = !!process.env['SERVERLESSWP_READ_ONLY_MODE']
&& !['false', '0', 'no'].includes(process.env['SERVERLESSWP_READ_ONLY_MODE'].toLowerCase());

let initDone = false;

// Move the /wp directory to /tmp/wp so that it is writeable.
setup();

// This is where all requests to WordPress are routed through.
// See vercel.json or netlify.toml for the redirection rules.
// See vercel.json, netlify.toml, or serverless.yml for the redirection rules.
exports.handler = async function (event, context, callback) {
if ((process.env['SQLITE_S3_BUCKET'] || process.env['SERVERLESSWP_DATA_SECRET']) && !initSqliteS3) {
let wpContentPath = pathToWP + '/wp-content';
let sqlitePluginPath = wpContentPath + '/plugins/sqlite-database-integration';
await sqliteS3.prepPlugin(wpContentPath, sqlitePluginPath);

let branchSlug = '';
let bucketFallback = '';

// Vercel
if (process.env['VERCEL']) {
const branch = sqliteS3.branchNameToS3file(process.env['VERCEL_GIT_COMMIT_REF']);
branchSlug = branch ? '-' + branch : '';
bucketFallback = process.env['VERCEL_PROJECT_ID'];
if (!initDone) {
// Register readOnly first so blocked mutations short-circuit before the
// sqlite plugin tries to hit storage.
if (readOnlyActive) {
serverlesswp.registerPlugin(readOnly);
}

// Configure the sqliteS3 plugin.
let sqliteS3Config = {
bucket: process.env['SQLITE_S3_BUCKET'] || bucketFallback,
file:`wp-sqlite-s3${branchSlug}.sqlite`,
S3Client: {
credentials: {
"accessKeyId": process.env['SQLITE_S3_API_KEY'] || process.env['VERCEL_PROJECT_ID'],
"secretAccessKey": process.env['SQLITE_S3_API_SECRET'] || process.env['SERVERLESSWP_DATA_SECRET']
},
region: process.env['SQLITE_S3_REGION'],
}
};

if (process.env['SQLITE_S3_ENDPOINT']) {
sqliteS3Config.S3Client.endpoint = process.env['SQLITE_S3_ENDPOINT'];
}

if (process.env['SQLITE_S3_FORCE_PATH_STYLE'] || process.env['SERVERLESSWP_DATA_SECRET']) {
sqliteS3Config.S3Client.forcePathStyle = true;
if (database.plugin) {
await database.plugin.prepPlugin(wpContentPath, sqlitePluginPath);
database.plugin.config(database.config);
serverlesswp.registerPlugin(database.plugin);
}

if (process.env['SERVERLESSWP_DATA_SECRET']) {
sqliteS3Config.S3Client.endpoint = 'https://data.serverlesswp.com';
sqliteS3Config.onAuthError = () => sandbox.register(
sqliteS3Config.bucket,
process.env['SERVERLESSWP_DATA_SECRET']
);
serverlesswp.registerPlugin(sandbox);
}

sqliteS3.config(sqliteS3Config);
initSqliteS3 = true;
}

// Send the request (event object) to the serverlesswp library.
// It includes the PHP server that allows WordPress to handle the request.
let response = await serverlesswp({docRoot: pathToWP, event: event});

// Check to see if the database environment variables are in place.
let checkInstall = validate(response);

if (checkInstall) {
return checkInstall;
initDone = true;
}
else {
// Return the response for serving.
return response;
}
}

if (process.env['SERVERLESSWP_READ_ONLY_MODE'] && !['false', '0', 'no'].includes(process.env['SERVERLESSWP_READ_ONLY_MODE'].toLowerCase())) {
// Register before sqliteS3 so blocked requests force a response before the S3 fetch.
serverlesswp.registerPlugin(readOnly);
}

if (process.env['SQLITE_S3_BUCKET'] || process.env['SERVERLESSWP_DATA_SECRET']) {
// Register the sqlite serverlesswp plugin.
serverlesswp.registerPlugin(sqliteS3);
}

if (process.env['SERVERLESSWP_DATA_SECRET']) {
// Register the sandbox widget plugin.
serverlesswp.registerPlugin(sandbox);
}
const response = await serverlesswp({ docRoot: pathToWP, event: event });
const checkInstall = validate(response);
return checkInstall || response;
};
101 changes: 5 additions & 96 deletions api/vercel.js
Original file line number Diff line number Diff line change
@@ -1,98 +1,7 @@
const serverlesswp = require('serverlesswp');
// Vercel entry point, referenced by vercel.json. No Vercel-specific setup left
// here - util/storage.js reads the VERCEL_* variables itself.

const { validate } = require('../util/install.js');
const { setup } = require('../util/directory.js');
const sqliteS3 = require('../util/sqliteS3.js');
const sandbox = require('../util/sandbox.js');
const readOnly = require('../util/readOnly.js');
const core = require('./index.js');

const pathToWP = '/tmp/wp';
let initSqliteS3 = false;

// Move the /wp directory to /tmp/wp so that it is writeable.
setup();

// This is where all requests to WordPress are routed through.
// See vercel.json or netlify.toml for the redirection rules.
async function handler(event, context, callback) {
if ((process.env['SQLITE_S3_BUCKET'] || process.env['SERVERLESSWP_DATA_SECRET']) && !initSqliteS3) {
let wpContentPath = pathToWP + '/wp-content';
let sqlitePluginPath = wpContentPath + '/plugins/sqlite-database-integration';
await sqliteS3.prepPlugin(wpContentPath, sqlitePluginPath);

let branchSlug = '';
let bucketFallback = '';

// Vercel
if (process.env['VERCEL']) {
const branch = sqliteS3.branchNameToS3file(process.env['VERCEL_GIT_COMMIT_REF']);
branchSlug = branch ? '-' + branch : '';
bucketFallback = process.env['VERCEL_PROJECT_ID'];
}

// Configure the sqliteS3 plugin.
let sqliteS3Config = {
bucket: process.env['SQLITE_S3_BUCKET'] || bucketFallback,
file:`wp-sqlite-s3${branchSlug}.sqlite`,
S3Client: {
credentials: {
"accessKeyId": process.env['SQLITE_S3_API_KEY'] || process.env['VERCEL_PROJECT_ID'],
"secretAccessKey": process.env['SQLITE_S3_API_SECRET'] || process.env['SERVERLESSWP_DATA_SECRET']
},
region: process.env['SQLITE_S3_REGION'],
}
};

if (process.env['SQLITE_S3_ENDPOINT']) {
sqliteS3Config.S3Client.endpoint = process.env['SQLITE_S3_ENDPOINT'];
}

if (process.env['SQLITE_S3_FORCE_PATH_STYLE'] || process.env['SERVERLESSWP_DATA_SECRET']) {
sqliteS3Config.S3Client.forcePathStyle = true;
}

if (process.env['SERVERLESSWP_DATA_SECRET']) {
sqliteS3Config.S3Client.endpoint = 'https://data.serverlesswp.com';
sqliteS3Config.onAuthError = () => sandbox.register(
sqliteS3Config.bucket,
process.env['SERVERLESSWP_DATA_SECRET']
);
}

sqliteS3.config(sqliteS3Config);
initSqliteS3 = true;
}

// Send the request (event object) to the serverlesswp library.
// It includes the PHP server that allows WordPress to handle the request.
let response = await serverlesswp({docRoot: pathToWP, event: event});

// Check to see if the database environment variables are in place.
let checkInstall = validate(response);

if (checkInstall) {
return checkInstall;
}
else {
// Return the response for serving.
return response;
}
}

if (process.env['SERVERLESSWP_READ_ONLY_MODE'] && !['false', '0', 'no'].includes(process.env['SERVERLESSWP_READ_ONLY_MODE'].toLowerCase())) {
// Register before sqliteS3 so blocked requests force a response before the S3 fetch.
serverlesswp.registerPlugin(readOnly);
}

if (process.env['SQLITE_S3_BUCKET'] || process.env['SERVERLESSWP_DATA_SECRET']) {
// Register the sqlite serverlesswp plugin.
serverlesswp.registerPlugin(sqliteS3);
}

if (process.env['SERVERLESSWP_DATA_SECRET']) {
// Register the sandbox widget plugin.
serverlesswp.registerPlugin(sandbox);
}

module.exports = handler;
module.exports.handler = handler;
module.exports = core.handler;
module.exports.handler = core.handler;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"license": "MIT",
"dependencies": {
"@aws-sdk/client-s3": "^3.772.0",
"serverlesswp": "^0.5.4",
"@vercel/blob": "^2.3.3",
"serverlesswp": "^0.5.5",
"sqlite3": "^5.1.7"
},
"engines": {
Expand Down
Loading
Loading