Skip to content

Commit

Permalink
Add Type Safety Guards to turbo/fetch_requests
Browse files Browse the repository at this point in the history
Through the exercise of attempting to [port the `turbo/fetch_requests`
module to
TypeScript](hotwired#392 (comment)),
we've identified some potential edge cases in the algorithm that
determines a request's HTTP method.

Even if the migration to TypeScript doesn't come to fruition for some
time, those edge cases should be addressed sooner rather than later.

This commit adds more "type safety" motivated conditionals and guards to
make sure that values are present before overriding them.
  • Loading branch information
seanpdoyle committed Nov 18, 2022
1 parent 2a80b2c commit c804ecd
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
36 changes: 33 additions & 3 deletions app/assets/javascripts/turbo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4025,12 +4025,13 @@ function encodeMethodIntoRequestBody(event) {
if (event.target instanceof HTMLFormElement) {
const {target: form, detail: {fetchOptions: fetchOptions}} = event;
form.addEventListener("turbo:submit-start", (({detail: {formSubmission: {submitter: submitter}}}) => {
const method = submitter && submitter.formMethod || fetchOptions.body && fetchOptions.body.get("_method") || form.getAttribute("method");
const body = isBodyInit(fetchOptions.body) ? fetchOptions.body : new URLSearchParams;
const method = determineFetchMethod(submitter, body, form);
if (!/get/i.test(method)) {
if (/post/i.test(method)) {
fetchOptions.body.delete("_method");
body.delete("_method");
} else {
fetchOptions.body.set("_method", method);
body.set("_method", method);
}
fetchOptions.method = "post";
}
Expand All @@ -4040,6 +4041,35 @@ function encodeMethodIntoRequestBody(event) {
}
}

function determineFetchMethod(submitter, body, form) {
const formMethod = determineFormMethod(submitter);
const overrideMethod = body.get("_method");
const method = form.getAttribute("method") || "get";
if (typeof formMethod == "string") {
return formMethod;
} else if (typeof overrideMethod == "string") {
return overrideMethod;
} else {
return method;
}
}

function determineFormMethod(submitter) {
if (submitter instanceof HTMLButtonElement || submitter instanceof HTMLInputElement) {
if (submitter.hasAttribute("formmethod")) {
return submitter.formMethod;
} else {
return null;
}
} else {
return null;
}
}

function isBodyInit(body) {
return body instanceof FormData || body instanceof URLSearchParams;
}

addEventListener("turbo:before-fetch-request", encodeMethodIntoRequestBody);

var adapters = {
Expand Down
Loading

0 comments on commit c804ecd

Please sign in to comment.