Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions appengine/building-an-app/update/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"author": "Google Inc.",
"license": "Apache-2.0",
"dependencies": {
"cookie-parser": "^1.4.6",
"csurf": "^1.11.0",
"express": "^4.18.2"
},
"devDependencies": {
Expand Down
8 changes: 6 additions & 2 deletions appengine/building-an-app/update/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@

// [START gae_update_web_server_app]
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const csrf = require('csurf');
Comment on lines +19 to +20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To avoid hardcoding the HTML form in server.js and keep using the existing views/form.html template, we need to import the fs and path modules. This allows us to read the HTML file asynchronously and inject the CSRF token dynamically.

Suggested change
const cookieParser = require('cookie-parser');
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
const csrf = require('csurf');
const fs = require('fs').promises;
const path = require('path');
References
  1. For asynchronous file system operations in Node.js, use the promise-based fs.promises API when working with async/await.


const app = express();

// [START gae_enable_parser]
// This middleware is available in Express v4.16.0 onwards
app.use(cookieParser());
app.use(express.urlencoded({extended: true}));
app.use(csrf({cookie: true}));
// [END gae_enable_parser]

app.get('/', (req, res) => {
Expand All @@ -31,7 +34,8 @@ app.get('/', (req, res) => {

// [START gae_add_display_form]
app.get('/submit', (req, res) => {
res.sendFile(path.join(__dirname, '/views/form.html'));
const token = req.csrfToken();
res.send(`<!DOCTYPE html><html><head><title>My App Engine App</title></head><body><h2>Create a new post</h2><form method="POST" action="/submit"><input type="hidden" name="_csrf" value="${token}"><div><input type="text" name="name" placeholder="Name"></div><div><textarea name="message" placeholder="Message"></textarea></div><div><button type="submit">Submit</button></div></form></body></html>`);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Hardcoding the HTML form directly in server.js bypasses the existing views/form.html file, leaving it as dead code and breaking the tutorial structure. Instead, read the HTML file dynamically and inject the CSRF token into the form. Since this is an asynchronous file system operation, use the promise-based fs.promises API with async/await as per the project's guidelines.

app.get('/submit', async (req, res, next) => {
  try {
    const token = req.csrfToken();
    const template = await fs.readFile(path.join(__dirname, '/views/form.html'), 'utf-8');
    const html = template.replace(
      '<form method="POST" action="/submit">',
      `<form method="POST" action="/submit"><input type="hidden" name="_csrf" value="${token}">`
    );
    res.send(html);
  } catch (err) {
    next(err);
  }
});
References
  1. For asynchronous file system operations in Node.js, use the promise-based fs.promises API when working with async/await.

// [END gae_add_display_form]

Expand Down