Reputation: 699
I am posting data from a simple html form to an Express.js endpoint. When I post the data, I received the following error:
"Access to fetch at 'https://samplesite.net/sample' from origin 'https://samplesite.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."
Here's the form code:
<form id="form-email-list" >
<div class="contact__fields">
<div class="field field--with-error">
<input class="field__input"
autocomplete="given-name"
type="text"
id="form-email-firstname"
name="form_email_firstname"
value=""
placeholder="{{ 'templates.email_newsletter.form.first_name' | t }}"
autocapitalize="words"
autofocus
data-parsley-validation-threshold="2"
data-parsley-error-message="Enter your first name"
data-parsley-required
/>
<label class="field__label" for="form-email-firstname">{{ 'templates.email_newsletter.form.first_name' | t }} <span class="req" aria-hidden="true">*</span></label>
</div>
<div class="field">
<input
class="field__input"
autocomplete="family-name"
type="text"
id="form-email-lastname"
name="form_email_lastname"
value=""
placeholder="{{ 'templates.email_newsletter.form.last_name' | t }}"
autocapitalize="words"
data-parsley-validation-threshold="2"
data-parsley-error-message="Enter your last name"
data-parsley-required
/>
<label class="field__label" for="form-email-lastname">{{ 'templates.email_newsletter.form.last_name' | t }} <span class="req" aria-hidden="true">*</span></label>
</div>
<div class="field">
<input
class="field__input"
type="email"
id="form-email-email"
name="form_email_email"
value=""
placeholder="{{ 'templates.email_newsletter.form.email' | t }}"
autocorrect="off"
autocapitalize="off"
autocomplete="email"
data-parsley-validation-threshold="3"
data-parsley-type="email"
data-parsley-error-message="Enter a valid email address"
data-parsley-required
/>
<label class="field__label" for="form-email-email">{{ 'templates.email_newsletter.form.email' | t }} <span class="req" aria-hidden="true">*</span></label>
</div>
<div class="field">
<input
class="field__input"
autocomplete="postal-code"
type="text"
id="form-email-zip"
name="form_email_zip"
value=""
placeholder="{{ 'templates.email_newsletter.form.zip' | t }}"
autocomplete="postal-code"
data-parsley-pattern="^[0-9]{5}(?:-[0-9]{4})?$"
data-parsley-maxlength="10"
data-parsley-validation-threshold="5"
data-parsley-error-message="Enter a 5 (XXXXX) or 9 (XXXXX-XXXX) digit zip code"
data-parsley-required
/>
<label class="field__label" for="form-email-zip">{{ 'templates.email_newsletter.form.zip' | t }} <span class="req" aria-hidden="true">*</span></label>
</div>
</div>
<div class="field">
<input
class="field__input js-validate-dob"
autocomplete="bday"
type="date"
id="form-email-dob"
name="form_email_dob"
value=""
placeholder="MM/DD/YYYY"
data-date-format="MM/DD/YYYY"
data-date-maxDate=""
data-parsley-maxdate=""
data-parsley-required
/>
<label class="field__label" for="form-email-dob">{{ 'templates.email_newsletter.form.dob' | t }} <span class="req" aria-hidden="true">*</span></label>
</div>
<div class="field checkbox">
<input
autocomplete="off"
type="checkbox"
id="form-email-optin"
name="form_email_optin"
value=""
/>
<label for="form-email-optin">
Yes, I consent...yadda yadda
</label>
</div>
<div class="contact__button">
<button type="submit" id="btn-submit" class="button">
{{ 'templates.email_newsletter.form.send' | t }}
</button>
</div>
</form>
Fetch Code
const formEmailList = document.getElementById('form-email-list');
formEmailList.addEventListener('submit', function(event) {
event.preventDefault();
let formEmailListURL = "https://samplesite.net/sample";
let fieldFirstName = document.getElementById('form-email-firstname').value;
let fieldLastName = document.getElementById('form-email-lastname').value;
let fieldEmail = document.getElementById('form-email-email').value;
let fieldZip = document.getElementById('form-email-zip').value;
let fieldDOB = document.getElementById('form-email-dob').value;
let fieldOptIn = document.getElementById('form-email-optin').value;
let emailListData = {
abi_first_name: fieldFirstName,
abi_last_name: fieldLastName,
abi_email: fieldEmail,
abi_zipcode: fieldZip,
abi_dateofbirth: fieldDOB,
abi_emailoptin: fieldOptIn
}
console.log('Posting Form...');
fetch(formEmailListURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(emailListData),
})
.then(response => {
if (!response.ok) {
throw new Error('Server returned ' + response.status);
}
return response.json();
})
.then(function(data) {
console.log('Added to List:', data);
})
.catch(error => {
console.error('There was a problem:', error);
});
});
Here's the Express App Code
const express = require("express");
const helmet = require("helmet");
const cors = require("cors");
const app = express();
const port = process.env.PORT || 1337;
const corsOptions = {
origin: 'https://samplesite.com',
optionsSuccessStatus: 200
}
// Secure Headers
app.use(helmet());
// parse json request body
app.use(express.json());
// parse urlencoded request body
app.use(express.urlencoded({
extended: true
}));
// Create Asset Dir
app.use(express.static(__dirname + "/public"));
// Sample Route
app.options("/sample", cors(corsOptions));
app.post("/sample", cors(corsOptions), (req, res, next) => {
const postToEmailList = async () => {
try {
const fetch = require('node-fetch');
const FormData = require('form-data');
const form = new FormData();
form.append("targetType", "dataExtension");
form.append("attributes", `{"campaign":"test","email":"${req.body.email}","test_id":"${req.body.email}","dateofbirth":"${req.body.dateofbirth}","first_name":"${req.body.first_name}","last_name":"${req.body.last_name}","zipcode":"${req.body.zipcode}","tcpp":"yes","emailoptin":"${req.body.emailoptin}"}`);
form.append("withTriggeredSend", "");
form.append("isJourneyBuilderIntegrated", "false");
const res = await fetch("https://test.com", {
method: "POST",
mode: 'cors',
body: form
});
const data = await res.text();
console.log(' data', data);
} catch (error) {
console.log(" error");
console.log(error);
}
}
});
app.get("*", function(req, res, next) {
let err = new Error("Page Doesn't Exist");
err.statusCode = 404;
next(err);
});
app.listen(port, (err) => {
if (err) {
return console.error(err);
}
return console.log(`server is listening on ${port}`);
});
module.exports = app;
Upvotes: 0
Views: 844
Reputation: 943569
Response to preflight request doesn't pass access control check
You're making a preflighted request.
app.post("/sample", cors(corsOptions), (req, res, next) => {
… but you've only enabled CORS for POST requests.
Since the preflight request is an OPTIONS request, it won't get permission.
The documentation for the module you are using has a section about preflight requests which gives a couple of options including just using app.options("/sample", cors(corsOptions))
.
Upvotes: 1