0

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

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Amey079
  • 131
  • 7
  • Since you are already using POST, why not use hidden fields and POST params instead? To answer your question though, this seems more like a server problem than your form. Do you have any error logs from the server side? – Jae Oct 07 '22 at 23:13
  • I'm not getting the post request on the server. Also, how do I use hidden fields and POST params? Sorry I'm learning – Amey079 Oct 07 '22 at 23:18
  • @Amey079 If you're getting a 404 not found, then the browser *did* make a request and the server *did* handle it. – Bergi Oct 07 '22 at 23:51

1 Answers1

0

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;
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks a lot! Using hidden inputs worked like a charm! I didn't have an option since I was generating the HTML including the form Programatically. – Amey079 Oct 08 '22 at 00:08