cmorten / opine

Minimalist web framework for Deno ported from ExpressJS.
https://github.com/cmorten/opine/blob/main/.github/API/api.md
MIT License
854 stars 43 forks source link

Unable to serve static files #62

Closed mphelp closed 4 years ago

mphelp commented 4 years ago

Unable to serve static files

Setup:

I try to run your example: deno run --allow-net --allow-read https://raw.githubusercontent.com/asos-craigmorten/opine/main/examples/static-files/index.ts

And the app runs and says this:

listening on port 3000
try:
  GET /hello.txt
  GET /js/app.js
  GET /js/helper.js
  GET /css/style.css
try the files served under `static/`:
  GET /static/hello.txt
  GET /static/js/app.js
  GET /static/js/helper.js
  GET /static/css/style.css
try the css served on the root:
  GET /style.css

But then nothing seems to actually be served up either in browser or Postman

Screen Shot 2020-09-08 at 11 56 05 AM

@asos-craigmorten Would really appreciate your help! thanks

asos-craigmorten commented 4 years ago

Hi @mphelp 👋

Thanks for raising this! I suspect this might be a case of copy paste error with the example docs! From memory static serving might not work from a remotely run example (or this could be a bug!)

Are you able to confirm if you have this issue when running the example locally? (Either by cloning and running, or creating a similar app importing the opine module from a registry etc)

I’m out atm but will give it a check when I’m back at my laptop!

mphelp commented 4 years ago

@asos-craigmorten Thanks Craig for answering this. Once run locally (git clone), the example works just fine.

In my own app, can you please explain why this worked for static files:

app.use(serveStatic(join(__dirname, "public")));
app.use("/", (req, res, next) => {
  res.type("text/html").send(html);
});

But not this, which I had previously?

app.use("/", (req, res, next) => {
  res.type("text/html").send(html);
});
app.use(serveStatic(join(__dirname, "public")));
asos-craigmorten commented 4 years ago

Fab - I will update the example docs to make it clear these work locally, not via a remote (URL) deno run.

As for why adding the serveStatic middleware as the second middleware layer doesn't work in your example, it is due to your use of app.use().

See the docs here.

app.use([path,] callback [, callback...])

Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches path.

...

A route will match any path that follows its path immediately with a "/". For example: app.use('/apple', ...) will match "/apple", "/apple/images", "/apple/images/news", and so on.

So in your case, by defining app.use("/", ...) first that particular middleware is catching all requests whose base matches /, which will be all requests. Hence, I recommend you either place that middleware handler last or use a specific handler, e.g. app.get() (see docs) which matches exact routes.