Deploys and Redirects with Functions and Express.js

Hi, I am trying to deploy a react app with lambda functions.

Here’s my repo: https://github.com/dyelax/netlify-lambda-test
And deployed url: https://dyelax-lambda-test.netlify.app

For convenience, here is my netlify.toml and the functions in question:

netlify.toml

[build]
  functions = "lambda-build"
  command = "npm run build"
  publish = "build"

[[redirects]]
  from = "/e/*"
  to = "/.netlify/functions/express"
  status = 200

[[redirects]]
  from = "/d/*"
  to = "/.netlify/functions/default"
  status = 200

src/lambda-functions/default.js

import App from '../App.js'
import React from 'react';
import ReactDOMServer from 'react-dom/server';

exports.handler = async (event, context) => {
  const app = ReactDOMServer.renderToString(<App path={event.path} />);

  return {
    statusCode: 200,
    body: app,
  };
};

src/lambda-functions/express.js

import App from '../App.js'
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import express from 'express'
import serverless from 'serverless-http'

const app = express();
const router = express.Router();

router.get('*', async (req, res) => {
  const app = ReactDOMServer.renderToString(<App path={req.path} />);
  return res.status(200).send(app);
});

app.use('/.netlify/functions/express', router);
exports.handler = serverless(app);

I have two questions:

  1. The functions work when I run netlify dev locally, but they aren’t working when I deploy.

Locally, the route .netlify/functions/default/123 prints .netlify/functions/default/123 on the screen, as expected. when deployed, the same route says “page not found.” You can test this at https://dyelax-lambda-test.netlify.app/.netlify/functions/default/123.

Is there anything that needs to be set up in particular to deploy lambda functions?

  1. I want to redirect certain URLs to certain functions. Using netlify dev (where the functions are working), redirects work for the default function syntax but not for Express. I think the issue has to do with the status code not being set correctly, but even if I explicitly set res.status(200) in the express function, the redirect doesn’t work. The express function works fine when I navigate directly to .netlify/functions/express, but using e/123, I see “Cannot GET /e/123” and the logs show:
Request from ::1: GET /.netlify/functions/express
Response with status 404 in 38 ms.
Request from ::1: GET /.netlify/functions/express.html
Response with status 404 in 1 ms.
Request from ::1: GET /.netlify/functions/express.htm
Response with status 404 in 0 ms.
Request from ::1: GET /.netlify/functions/express/index.html
Response with status 404 in 32 ms.
Request from ::1: GET /.netlify/functions/express/index.htm
Response with status 404 in 32 ms.

Hey @dyelax,
The first (and maybe only!) issue is that your functions are not getting uploaded. I can tell because when I look here:
https://app.netlify.com/sites/dyelax-lambda-test/deploys/5efcee4e44b20900088a64b4
there’s nothing under “Published deploy” at the top that says “View Functions in production”

It looks like you’ve set your functions directory in the netlify.toml to be “lambda-build” but in your repo, the directory is called “lambda-functions”- could you try changing that and see if it fixes things for you?

Hi @jen, thanks for the reply! I’ve resolved my first problem: When I run netlify dev locally, I get a message that says “Function builder netlify-lambda detected: Running npm script lambda-build”. This doesn’t happen when I push to deploy, so I needed to change my build command from npm run build to npm run build && npm run lambda-build. The deployed site now runs the functions.

However, I’m still having the redirect issue. When I use the full /.netlify/functions/express/123 route, I get a 200 response and everything works fine, but when I try the redirect /e/123, I get a 404 if I specify status = 200 in the toml redirect rule. If I get rid of status = 200 in the toml, the redirect works, but doesn’t keep the shortened URL (it switches the url to the full /.netlify/functions/express/123, which I don’t want). I think this indicates that my express function isn’t returning a 200 status for the redirect. Any ideas why that might be?

Hey @dyelax,
I think this is about Express routing and our redirects. To be honest, I don’t fully understand how all the paths change as requests flow through Netlify’s server and the lambda function, but could you try something like this?

router.get("/e/*", (req, res) => {
...
})

app.use("/", router);

I made a test here and seems to work as you’re hoping: https://boring-lovelace-8012f2.netlify.app/e/123