Repository: denoland/fresh
File: src/server/context.ts (TypeScript)

Code before:
      this.#extractResult.middlewares,
      handlers.errorHandler,
      router.getParamsAndRoute(handlers),
      renderNotFound,
      basePath,
    );
    const trailingSlashEnabled = this.#state.config.router?.trailingSlash;
    const isDev = this.#dev;

    if (this.#dev) {
      this.#revision = Date.now();
    }

    // deno-lint-ignore no-this-alias
    const _self = this;

    return async function handler(
      req: Request,
      connInfo: ServeHandlerInfo = DEFAULT_CONN_INFO,
    ) {
      const url = new URL(req.url);

      const aliveUrl = basePath + ALIVE_URL;

      if (isDev) {
        // Live reload: Send updates to browser
        if (url.pathname === aliveUrl) {
          if (req.headers.get("upgrade") !== "websocket") {
            return new Response(null, { status: 501 });
          }

          // TODO: When a change is made the Deno server restarts,
          // so for now the WebSocket connection is only used for
          // the client to know when the server is back up. Once we
          // have HMR we'll actively start sending messages back
          // and forth.
          const { response, socket } = Deno.upgradeWebSocket(req);

          socket.addEventListener("open", () => {
            socket.send(
              JSON.stringify({
                type: "initial-state",
                revision: _self.#revision,
              }),
            );
          });

          return response;
        } else if (
          url.pathname === withBase(DEV_CLIENT_URL, basePath) ||
          url.pathname === withBase(`${DEV_CLIENT_URL}.map`, basePath)

Review comment (bug):
Can you also check further down whether the original pathname matches the changed pathname? Because if it doesnt (there were double slashes), we should redirect to the normalized variant. Otherwise there will be a weird edge case where this logic matches as if there are no double slashes, but when a user does `new URL(req.url)`, they still get the "old" non-normalized URL.

Code after:
      this.#extractResult.middlewares,
      handlers.errorHandler,
      router.getParamsAndRoute(handlers),
      renderNotFound,
      basePath,
    );
    const trailingSlashEnabled = this.#state.config.router?.trailingSlash;
    const isDev = this.#dev;

    if (this.#dev) {
      this.#revision = Date.now();
    }

    // deno-lint-ignore no-this-alias
    const _self = this;

    return async function handler(
      req: Request,
      connInfo: ServeHandlerInfo = DEFAULT_CONN_INFO,
    ) {
      const url = new URL(req.url);
      // Syntactically having double slashes in the pathname is valid per
      // spec, but there is no behavior defined for that. Practically all
      // servers normalize the pathname of a URL to not include double
      // forward slashes.
      url.pathname = url.pathname.replaceAll(/\/+/g, "/");

      const aliveUrl = basePath + ALIVE_URL;

      if (isDev) {
        // Live reload: Send updates to browser
        if (url.pathname === aliveUrl) {
          if (req.headers.get("upgrade") !== "websocket") {
            return new Response(null, { status: 501 });
          }

          // TODO: When a change is made the Deno server restarts,
          // so for now the WebSocket connection is only used for
          // the client to know when the server is back up. Once we
          // have HMR we'll actively start sending messages back
          // and forth.
          const { response, socket } = Deno.upgradeWebSocket(req);

          socket.addEventListener("open", () => {
            socket.send(
              JSON.stringify({
                type: "initial-state",
                revision: _self.#revision,
              }),
            );
          });