After four years, the demos in my article “Headless Form Submission with the WordPress REST API” stopped working. The article includes CodePen embeds showing how to use REST API endpoints of popular WordPress form plugins for validation errors and feedback in a custom front-end. These relied on a WordPress site I had running, but it failed during an infrastructure migration, and I lost account access.
I could have contacted support or restored a backup, but it made me wonder: what if it wasn’t WordPress? What if it were a third-party service I couldn’t fix? Is there a way to build demos that don’t break when services fail? Can we ensure educational demos remain available?
Or is it inevitable? Are demos doomed to break eventually?
Parallels with software testing arise. The issue is dependencies, especially third-party ones, which are outside control. The most reliable way to avoid issues is to remove the external service, decoupling from it. How this is done depends on context. Techniques for handling dependencies can make demos more resilient.
Using CodePen demos as an example, the same approach works in many contexts. Two common strategies to break reliance on a REST API are:
1. Mocking HTTP calls in code, returning stubbed responses instead of real requests.
2. Using a mock API server as a stand-in for the real service, serving predefined responses.
Both have trade-offs, but let’s look at those later.
Modern testing frameworks like Jest or Playwright offer built-in mocking capabilities. However, we can’t use them in pens. Instead, we can monkey patch the Fetch API to intercept requests and return mock responses, adding new behavior by overwriting existing functions.
Implementing it looks like this:
“`javascript
const fetchWPFormsRestApiInterceptor = (fetch) => async (resource, options = {}) => {
if (typeof resource !== “string” || !(options.body instanceof FormData)) {
return fetch(resource, options);
}
if (resource.match(/wp-json/contact-form-7/)) {
return contactForm7Response(options.body);
}
if (resource.match(/wp-json/gf/)) {
return gravityFormsResponse(options.body);
}
return fetch(resource, options);
};
window.fetch = fetchWPFormsRestApiInterceptor(window.fetch);
“`
The replacement function, `fetchWPFormsRestApiInterceptor`, acts as an interceptor, modifying requests or responses based on conditions. Returning a fake response is as simple as calling the static JSON method of the `Response` object:
“`javascript
const contactForm7Response = (formData) => {
const body = {}
return Response.json(body);
};
“`
For the CodePen demo, the response might be built like this:
“`javascript
const contactForm7Response = (formData) => {
const submissionSuccess = {
into: “#”,
status: “mail_sent”,
message: “Thank you for your message. It has been sent.!”,
posted_data_hash: “d52f9f9de995287195409fe6dcde0c50”
};
const submissionValidationFailed = {
into: “#”,
status: “validation_failed”,
message: “One or more fields have an error. Please check and try again.”,
posted_data_hash: “”,
invalid_fields: []
};
if (!formData.get(“somebodys-name”)) {
submissionValidationFailed.invalid_fields.push({
into: “span.wpcf7-form-control-wrap.somebodys-name”,
message: “This field is required.”,
idref: null,
error_id: “-ve-somebodys-name”
});
}
if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(formData.get(“any-email”))) {
submissionValidationFailed.invalid_fields.push({
into: “span.wpcf7-form-control-wrap.any-email”,
message: “The email address entered is invalid.”,
idref: null,
error_id: “-ve-any-email”
});
}
const body = !submissionValidationFailed.invalid_fields.length ? submissionSuccess : submissionValidationFailed;
return Response.json(body);
};
“`
Now, any `fetch` call to a URL matching `wp-json/contact-form-7` returns the faked success or validation errors, depending on the form input.
Running a traditionally hosted mock API server reintroduces concerns around availability, maintenance, and cost. Using serverless functions can sidestep these issues. DigitalOcean Functions offers a generous free tier, making mocked APIs practically free and requiring no more effort than manual mocking.
For simple use cases, everything can be done through the Functions control panel. For more complex needs, functions can be developed locally and deployed using `doctl` (DigitalOcean’s CLI). Creating a separate Function for each endpoint avoids unnecessary conditions. We can stick with
Discover more from WIREDGORILLA
Subscribe to get the latest posts sent to your email.