Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handlers URL for context.serve / support SPA #2904

Closed
tinovyatkin opened this issue Feb 8, 2023 · 6 comments
Closed

Error handlers URL for context.serve / support SPA #2904

tinovyatkin opened this issue Feb 8, 2023 · 6 comments

Comments

@tinovyatkin
Copy link

tinovyatkin commented Feb 8, 2023

Thank you for great enhancements for esbuild server on 0.17.x!

It would be fantastical if we can specify URL for error handler for context.serve and open a way to support SPA / routing, like:

const server = await context.serve({
  port: PORT,
  servedir: config.outdir,
  errorUrls: {
    404: '/index.html',
  },
  onRequest({ method, path, status, timeInMS }) {
    console.log(`%s %s: %d in %d ms`, method, path, status, timeInMS);
  },
});

alternatively (but probably way more complex to implement) would be an addition of a hook for context.serve like

const server = await context.serve({
  port: PORT,
  servedir: config.outdir,
  onResolve({ method, pathname, servedir }) {
    if (!fs.existSync(path.resolve(servedir, pathname.slice(1))))
      return './index.html';
  },
  onRequest({ method, path, status, timeInMS }) {
    console.log(`%s %s: %d in %d ms`, method, path, status, timeInMS);
  },
});
@mbrevda
Copy link

mbrevda commented Mar 6, 2023

Yes, this would be great. Especially considering the extremely popular use case of a SPA, it would be great if this could be handled without needing a proxy

edit: for now, here is how I'm handling it:

import http from 'node:http'
import fs from 'node:fs'

// esbuild's built in server servers static files and doesn't allow for
// any form of routing. This is a simple proxy server that forwards
// requests to esbuild's server and returns the index.html if esbuild
// returns a 404.
export default function esbuildServerProxy({host, port, servedir}) {
  return http
    .createServer((req, res) => {
      const options = {
        hostname: host,
        port,
        path: req.url,
        method: req.method,
        headers: req.headers
      }

      // Forward each incoming request to esbuild
      const proxyReq = http.request(options, proxyRes => {
        // If esbuild returns "not found", send the index.html instead
        if (proxyRes.statusCode === 404) {
          const index = fs.createReadStream(`${servedir}/index.html`)
          return index.pipe(res)
        }

        // Otherwise, forward the response from esbuild to the client
        res.writeHead(proxyRes.statusCode, proxyRes.headers)
        proxyRes.pipe(res, {end: true})
      })

      // Forward the body of the request to esbuild
      req.pipe(proxyReq, {end: true})
    })
    .listen(3000)
}

and called like:

  const {host, port} = await ctx.serve({servedir})
  const proxy = esbuildServerProxy({host, port, servedir})

@marlun
Copy link

marlun commented Jul 15, 2023

I'm also having "problems" with this, it's so close to being a very simple solution covering my needs, all I need is the client side routing ability.

@mbrevda do you have a working repo for this example? I can't get it to work.

@mbrevda
Copy link

mbrevda commented Jul 15, 2023

I don't

@evanw
Copy link
Owner

evanw commented Jul 18, 2023

My proposed solution for this is a new --serve-fallback=<./some-file.html> flag. This file would be served by esbuild's dev server if a file at the requested path doesn't exist.

It seems like this would be a better fit for the desired SPA use case than the proposed solution. If the proposed errorUrls solution were to be implemented, then (I assume) it would only be used when esbuild would otherwise serve a 404 error. But that wouldn't happen when esbuild serves an automatically-generated directory listing. For a SPA it seems like it would be better to serve a fallback page instead of a directory listing in that case.

@mbrevda
Copy link

mbrevda commented Jul 19, 2023

That would be great @evanw, and should address the issue elegantly!

@evanw evanw closed this as completed in c8f97d3 Jul 19, 2023
@mbrevda
Copy link

mbrevda commented Jul 19, 2023

thanks so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants