Whats the difference between a Controller and a Middleware

You should see middleware as a step in your API and controllers as the entity that will actually respond to the requests.

Bellow is an example where authenticationMiddleware is a middleware because it is a step during the processing but should not return the response. It can though, in case of error.

Then getItems actually handle the logic specific to this calls.

As a rule of thumb, middleware are often reused more than once and often they do not response. On contrary, controller respond and are most of the time specific to one endpoint.

const express = require("express");
const app = express();

function authenticationMiddleware(req, res, next) {
  // Check that the user is authenticated using req.headers.Authorization
  // for example

  if (authenticated) {
    // The user is authenticated, we can go to the next step
    next();

  } else {
    // The user is not authenticated, we stop here
    res.status(401);
    res.send("Error during authentication");
  }
}

function getItems(req, res, next) {
  // Here we focus on the actual response, we assume that the user is authenticated
  res.send({ items: [] });
}

app.get("/items", authenticationMiddleware, getItems);
app.post("/items", authenticationMiddleware, createItems); // Re-use the same middleware

app.listen(3000);

If you're referring to the node/express terminology, middleware are simply the callbacks used by the routing functions/methods (get, set, delete, use, etc). Callbacks can either send or not send responses back to the client. The callbacks are really the 'controllers' if you'd like to call them that (eg: ASP.NET Core MVC) but that's up to you. Below is a quote from Express. Note the term 'middleware' and where there's no mention of a 'controller'.

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.

Middleware functions can perform the following tasks:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware function in the stack.

'Express' also defines different types of middleware which is useful:

  • Application-level middleware
  • Router-level middleware
  • Error-handling middleware
  • Built-in middleware Third-party middleware

Here's another nice look at it from Mozilla's pov that does mention a few controller/callback examples.

Beyond that, you can define what a 'controller' is within your team and the naming convention follows from there. Key is your SOLID profile and how you separate your concerns.