Programatically setting URL parameters to the form's action attribute in Javascript

Issue

I want to post some Form data to my Server. I’m setting this element programatically and setting it’s URL parameters to the action attribute but it’s not taking those attributes. What am I doing wrong? Below is my code:

for(let i = 0; i < itemsDatabase.length; i++){

    document.getElementById("div-section-container").innerHTML += `

    <div class="div-results-container">
    
    <h2>${itemsDatabase[i].name}</h2>

    <img src = ${itemsDatabase[i].image} class="img-result">

    <p>${itemsDatabase[i].desc}</p>  

    <form method= "POST" action= "/favorites/add/name/${itemsDatabase[i].name}/desc/${itemsDatabase[i].desc}/img/${itemsDatabase[i].image}/id/${itemsDatabase[i].id}">
    <button class = "btn-favourite" type="submit">Mark As Favourite</Button>
    
    </div>
    
    `; 
}

My server code is :

app.post("/favorites/add/name/:name/desc/:desc/img/:img/id/:id", (req, res)=>{
  console.log(`Post request received`);
  console.log(req.params);
})

Getting this on the Browser:

Cannot POST
/favorites/add/name/blue%20nightshade/desc/A%20plant%20that%20grows%20in%20the%20quieter%20areas%20of%20Hyrule.%20At%20night,%20it%20gives%20off%20a%20soft%20glow.%20Cook%20with%20it%20to%20increase%20your%20stealth./img/https://botw-compendium.herokuapp.com/api/v2/entry/blue_nightshade/image/id/198

I’m getting a 404 not found

Solution

The problem would appear to be that https://botw-compendium.herokuapp.com/api/v2/entry/blue_nightshade/image is not a valid value for the :img parameter, which must not contain slashes to be matched by the pattern /favorites/add/name/:name/desc/:desc/img/:img/id/:id.

You could circumvent that by url-encoding the values:

`<form method="POST" action="/favorites/add/name/${encodeURIComponent(itemsDatabase[i].name)}/desc/${encodeURIComponent(itemsDatabase[i].desc)}/img/${encodeURIComponent(itemsDatabase[i].image)}/id/${encodeURIComponent(itemsDatabase[i].id)}">
  <button type="submit" class="btn-favourite">Mark As Favourite</Button>
</form>`

However, as suggested by @Jae, it would be much better to simple send those parameters as POST parameters instead of putting them into the path, via hidden inputs:

`<form method="POST" action= "/favorites/add">
  <input type="hidden" name="name" value="${itemsDatabase[i].name}">
  <input type="hidden" name="desc" value="${itemsDatabase[i].desc}">
  <input type="hidden" name="img" value="${itemsDatabase[i].image}">
  <input type="hidden" name="id" value="${itemsDatabase[i].id}">
  <button type="submit" class="btn-favourite">Mark As Favourite</Button>
</form>`

Btw, to prevent XSS attacks, you should escape all interpolated values, regardless whether they are in src, action or value attributes, or whether they are element contents:

const containerContent = '';
for (let i = 0; i < itemsDatabase.length; i++){
  containerContent += `
    <div class="div-results-container">
      <h2>${ escapeHtml(itemsDatabase[i].name) }</h2>
      <img src=${ escapeHtml(itemsDatabase[i].image) } class="img-result">
      <p>${ escapeHtml(itemsDatabase[i].desc) }</p>  
      <form method="POST" action= "/favorites/add">
        <input type="hidden" name="name" value="${ escapeHtml(itemsDatabase[i].name) }">
        <input type="hidden" name="desc" value="${ escapeHtml(itemsDatabase[i].desc) }">
        <input type="hidden" name="img" value="${ escapeHtml(itemsDatabase[i].image) }">
        <input type="hidden" name="id" value="${ escapeHtml(itemsDatabase[i].id) }">
        <button type="submit" class="btn-favourite">Mark As Favourite</Button>
      </form>
    </div>`; 
}
document.getElementById("div-section-container").innerHTML += containerConent;

Answered By – Bergi

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published