Code Monkey home page Code Monkey logo

fastify-static's Introduction

CI Package Manager CI Web SIte js-standard-style CII Best Practices

NPM version NPM downloads Security Responsible Disclosure Discord Contribute with Gitpod Open Collective backers and sponsors


An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests as possible, without sacrificing security validations and handy development?

Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture. It is inspired by Hapi and Express and as far as we know, it is one of the fastest web frameworks in town.

The main branch refers to the Fastify v4 release. Check out the v3.x branch for v3.

Table of Contents

Quick start

Create a folder and make it your current working directory:

mkdir my-app
cd my-app

Generate a fastify project with npm init:

npm init fastify

Install dependencies:

npm i

To start the app in dev mode:

npm run dev

For production mode:

npm start

Under the hood npm init downloads and runs Fastify Create, which in turn uses the generate functionality of Fastify CLI.

Install

To install Fastify in an existing project as a dependency:

Install with npm:

npm i fastify

Install with yarn:

yarn add fastify

Example

// Require the framework and instantiate it

// ESM
import Fastify from 'fastify'
const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

// Declare a route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Run the server!
fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

with async-await:

// ESM
import Fastify from 'fastify'
const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

fastify.get('/', async (request, reply) => {
  reply.type('application/json').code(200)
  return { hello: 'world' }
})

fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

Do you want to know more? Head to the Getting Started.

Note

.listen binds to the local host, localhost, interface by default (127.0.0.1 or ::1, depending on the operating system configuration). If you are running Fastify in a container (Docker, GCP, etc.), you may need to bind to 0.0.0.0. Be careful when deciding to listen on all interfaces; it comes with inherent security risks. See the documentation for more information.

Core features

  • Highly performant: as far as we know, Fastify is one of the fastest web frameworks in town, depending on the code complexity we can serve up to 76+ thousand requests per second.
  • Extensible: Fastify is fully extensible via its hooks, plugins and decorators.
  • Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function.
  • Logging: logs are extremely important but are costly; we chose the best logger to almost remove this cost, Pino!
  • Developer friendly: the framework is built to be very expressive and help the developer in their daily use, without sacrificing performance and security.

Benchmarks

Machine: EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD.

Method:: autocannon -c 100 -d 40 -p 10 localhost:3000 * 2, taking the second average

Framework Version Router? Requests/sec
Express 4.17.3 14,200
hapi 20.2.1 42,284
Restify 8.6.1 50,363
Koa 2.13.0 54,272
Fastify 4.0.0 77,193
-
http.Server 16.14.2 74,513

Benchmarks taken using https://github.com/fastify/benchmarks. This is a synthetic, "hello world" benchmark that aims to evaluate the framework overhead. The overhead that each framework has on your application depends on your application, you should always benchmark if performance matters to you.

Documentation

中文文档地址

Ecosystem

  • Core - Core plugins maintained by the Fastify team.
  • Community - Community supported plugins.
  • Live Examples - Multirepo with a broad set of real working examples.
  • Discord - Join our discord server and chat with the maintainers.

Support

Please visit Fastify help to view prior support issues and to ask new support questions.

Contributing

Whether reporting bugs, discussing improvements and new ideas or writing code, we welcome contributions from anyone and everyone. Please read the CONTRIBUTING guidelines before submitting pull requests.

Team

Fastify is the result of the work of a great community. Team members are listed in alphabetical order.

Lead Maintainers:

Fastify Core team

Fastify Plugins team

Great Contributors

Great contributors on a specific area in the Fastify ecosystem will be invited to join this group by Lead Maintainers.

Past Collaborators

Hosted by

We are a At-Large Project in the OpenJS Foundation.

Sponsors

Support this project by becoming a SPONSOR! Fastify has an Open Collective page where we accept and manage financial contributions.

Acknowledgements

This project is kindly sponsored by:

Past Sponsors:

This list includes all companies that support one or more of the team members in the maintenance of this project.

License

Licensed under MIT.

For your convenience, here is a list of all the licenses of our production dependencies:

  • MIT
  • ISC
  • BSD-3-Clause
  • BSD-2-Clause

fastify-static's People

Contributors

allevo avatar cameronbraid avatar cemremengu avatar climba03003 avatar coreyfarrell avatar dependabot-preview[bot] avatar dependabot[bot] avatar dwickern avatar eomm avatar fdawgs avatar frikille avatar gj avatar greenkeeper[bot] avatar gurgunday avatar is2ei avatar jelenkee avatar jsumners avatar mav-rik avatar mcollina avatar mse99 avatar mylesborins avatar nigelhanlon avatar nwoltman avatar olmesm avatar rafaelgss avatar rluvaton avatar ryhinchey avatar salmanm avatar uzlopak avatar wight554 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastify-static's Issues

provide clearer error if "root" does not exist

If root points to a non-existing directory the error printed is:

Error: ENOENT: no such file or directory, stat '/Users/username/project/some-directory'
    at statSync (fs.js:851:3)

Instead, maybe we can print "please verify the specified "root" directory exists"?

Server Side Caching

Hi,
Is there any way to configure a server side caching of static assets?
Using something like fastify-caching.
PS: I have deployed fastify using docker containers so I cannot rely on iobuffer performance as it is being shared by multiple apps.

setNotFoundHandler not triggering hooks

🐛 Bug Report

The docs for setNotFoundHandler specify it's possible to use hooks to be triggered before the handler is triggered:

You can also register a preValidation and preHandler hook for the 404 handler.

When using fastify-static these hooks are not being triggered.

To Reproduce

If you run this code you will see the preHandler hook is not being triggered. Disabling the fastify-static plugin solves the problem.

const path = require('path');

const fastify = require('fastify')({
	logger: true
});

fastify.register(require('fastify-static'), {
	root: path.join(__dirname, '/static/')
});

fastify.setNotFoundHandler({
	preHandler: (request, reply, next) => {
		console.log('preHandler!');
		next();
	}
}, function (request, reply) {
	reply.status(404);
	reply.send();
});

fastify.listen(5555, '0.0.0.0', function (err, address) {
	if (err) {
		fastify.log.error(err)
		process.exit(1)
	}
	fastify.log.info(`server listening on ${address}`)
});

Expected behavior

When the setNotFoundHandler callback is triggered it should also trigger the hooks defined for this handler.

Your Environment

  • node version: 12
  • fastify version: >=2.0.0
  • os: Mac

Feature Request: Option to ignore ENOENT in checkRootPathForErrors

The npm start for one of my web apps runs a fastify server which uses fastify-static twice:

fastify
  .register(fastifyStatic, {
    prefix: '/dev/',
    root: path.resolve('src')
  })
  .register(fastifyStatic, {
    prefix: '/app/',
    root: path.resolve('dist')
  })

The src directory always exists, this is the unmodified source. dist may or may not exist, it is the product of gulp build. Right now I use fs.mkdirSync(path.resolve('dist'), {recursive: true}) before initializing the fastifyStatic plugin to suppress the "root" path "${rootPath}" must exist error. It would be nice if I did not have to force creation of the empty folder for this to work, just let normal 404 logic deal with ENOENT at request time.

Are you open to this?

Several directory

Hello, how i can set several directory? I didn't see this example in doc.

try

fastify.register( require('fastify-static'), { root: path.join(__dirname, 'dist'), prefix: '/dist/' } )
fastify.register( require('fastify-static'), { root: path.join(__dirname, 'public'), prefix: '/public/' } )

Error

node_modules\fastify\lib\decorate.js:19
throw new FST_ERR_DEC_ALREADY_PRESENT(name)

will great see array format

[
{ root: path.join(__dirname, 'dist1'), prefix: '/dist1/' },
{ root: path.join(__dirname, 'dist2'), prefix: '/dist2/' },
{ root: path.join(__dirname, 'dist3'), prefix: '/dist3/' }  
]

Don't persist path error on startup for forever

When I initialize fastify-plugin in folder /static and the path does not exists 404 error is thrown. When I create the folder /static after that the error still persists and the user doesn't know what's going on. We don't have to persist that error the path is already checked by send module and can be handled by the error events.

btw: Isn't possible to use serve-static as middleware ?

dynamic reply

Is able to sendFile work with dynamic content from buffer?
I want to send file without saving on disk

reply is file

hello, how i can send file?
In example

const fastify = require('fastify')({
    logger: false,
    http2: true,
    https: {
        key: fs.readFileSync(path.join(__dirname, '/certificate/localhost/', 'key.pem')),
        cert: fs.readFileSync(path.join(__dirname, '/certificate/localhost/', 'cert.pem'))
    }
});

fastify.register(require('fastify-favicon'));
fastify.register(require('fastify-cookie'))
//STATIC
fastify.register( require('fastify-static'), { root: path.join(__dirname, 'dist'), prefix: '/dist/', decorateReply: false } )
fastify.register( require('fastify-static'), { root: path.join(__dirname, 'public'), prefix: '/public/', decorateReply: false } )

fastify.get('/another/path', function (req, reply) {
  reply.sendFile('myHtml.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly
})

try

fastify.get('/robots.txt', function (req, reply) {
    reply.sendFile( path.join( __dirname, '/public/', 'robots.txt' ) )
})

error

reply.sendFile( path.join( __dirname, '/public/', 'robots.txt' ) )
          ^
TypeError: reply.sendFile is not a function

server http2, whats wrong?

Feature Request: sendFile without serving anything

On my site each user has subdomain:

ilya.mysite.com/his/file
homer.mysite.com/index.html

I can't just tell serve this folder, I first retrieve username (homer), then serve his folder (users/homer). Ideally I would like to use reply.sendFile(path), but couldn't do it without specifying root folder (and serving file I don't want to server). Would be nice to have reply.sendFile separately from everything else.

Thanks!

Option to redirect requests for directory.

Take the following files within the root directory:

index.html
sub/index.html

Configure fastify-static to include index: 'index.html'. In this case http://localhost/ serves the root index.html, http://localhost/sub/ serves sub/index.html. But http://localhost/sub is a 404 error. Would you accept an option that would hook send.on('directory') to perform a 301 redirect of such requests to the path including the trialing slash? Such that http://localhost/sub would be 301 with Location: http://localhost/sub/. I haven't tested this yet but the send documentation tells how to accomplish this. I'm assuming that directory redirects would need to be opt-in rather than opt-out? Either would be fine with me, just figured I'd ask since fastify-static is in the middle of a semver-major release.

Multiple instances

How to declare plugin twice ?

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'landing/public'),
  prefix: '/landing/', // optional: default '/'
})

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'admin/dist'),
  prefix: '/admin/', // optional: default '/'
})

Using fastify-compression breaks Response time for static assets on browser

Config
fastify.register(require('fastify-compress'), { threshold: 0 });
fastify.register(fastifyStatic, __PROD__ ? { root: path.resolve(path.join(__dirname, '/../', 'public')), prefix: '/public/', setHeaders: function (res, path, stat) { res.setHeader('Content-Encoding', 'gzip') // console.log(stat) } }
tracelog on server
{"level":30,"time":1524127887660,"msg":"incoming request","pid":11241,"hostname":"utkarsh-Lenovo-ideapad-300-15ISK","reqId":9,"req":{"id":9,"method":"GET","url":"/public/assets/15_e8d859185f2e2b063a5c.js","remoteAddress":"127.0.0.1","remotePort":37776},"v":1}
{"level":30,"time":1524127887668,"msg":"request completed","pid":11241,"hostname":"utkarsh-Lenovo-ideapad-300-15ISK","reqId":9,"res":{"statusCode":200},"responseTime":7.410842999815941,"v":1}

Browser
image

PS Request is being made on localhost and if I remove compression it works properly but without compression ofcourse.

An in-range update of request is breaking the build 🚨

☝️ Greenkeeper’s updated Terms of Service will come into effect on April 6th, 2018.

Version 2.84.0 of request was just published.

Branch Build failing 🚨
Dependency request
Current Version 2.83.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

request is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details

Commits

The new version differs by 6 commits.

  • d77c839 Update changelog
  • 4b46a13 2.84.0
  • 0b807c6 Merge pull request #2793 from dvishniakov/2792-oauth_body_hash
  • cfd2307 Update hawk to 7.0.7 (#2880)
  • efeaf00 Fixed calculation of oauth_body_hash, issue #2792
  • 253c5e5 2.83.1

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Remove the dependency on send?

I think the send module does not really fit our needs here, and we should look for a long term solution (see #46 for some hacky details). Basically the gist is that it does not implement the Streams 2/3 API, so we cannot pass it down to reply.send().

I will engage on the send repo to see if there is work we can do there, if we should fork it, or if we should lift some piece of code from there in here. See: pillarjs/send#159.

cc @diffcunha

Fastify-static http2/https typescript warning

When using fastify with https/http2 like this:

import fastifyStatic from 'fastify-static'

const https: fastify.FastifyInstance<Http2SecureServer, Http2ServerRequest, Http2ServerResponse> = fastify({
  logger: log,
  ignoreTrailingSlash: true,
  http2: true,
  https: { allowHTTP1: true }
})

https.register(fastifyStatic, { root: path.resolve(__dirname, '../../public'), prefix: '/public/' })

You will get typescript warning:

error TS2345: Argument of type '(instance: FastifyInstance<Server, IncomingMessage, ServerResponse>, options: { root: string; prefix?: string | undefined; ... 14 more ...; maxAge?: string | ... 1 more ... | undefined; }, callback: (err?: FastifyError | undefined) => void) => void' is not assignable to parameter of type '(instance: FastifyInstance<Http2SecureServer, Http2ServerRequest, Http2ServerResponse>, options: { ...; }, callback: (err?: FastifyError | undefined) 
=> void) => void'.
  Types of parameters 'instance' and 'instance' are incompatible.
    Type 'FastifyInstance<Http2SecureServer, Http2ServerRequest, Http2ServerResponse>' is not assignable to type 'FastifyInstance<Server, IncomingMessage, ServerResponse>'.
      Types of property 'server' are incompatible.
        Type 'Http2SecureServer' is not assignable to type 'Server'.

What is the reason of this?

reply.notFound is not a function

Hello,

I use fastify-static 0.6.0 with fastify 1.2.1. When I try to call an unknown static file, I don't receive any 404 error, and my application crashed after this error :

TypeError: reply.notFound is not a function
at SendStream. (/var/www/node_modules/fastify-static/index.js:42:15)
at emitOne (events.js:116:13)
at SendStream.emit (events.js:211:7)
at SendStream.error (/var/www/node_modules/send/index.js:270:17)
at SendStream.onStatError (/var/www/node_modules/send/index.js:421:12)
at onstat (/var/www/node_modules/send/index.js:727:26)
at FSReqWrap.oncomplete (fs.js:152:21)

Feature Request: Add the ability to serve a folder directly from the terminal

It should have the ability to serve a folder directly from the terminal.

For example:
Lets say I installed fastify-static globally with -g flag, now I should be able to serve a folder with below commant
fastify-static . //serve current folder
fastify-static app/public/ -p 80 //serve the folder app/pblic on post 80

Proposal: dir index

🚀 Feature Proposal

I'd like to implement a feature to get the "index" of the directory, if the request is the dir root or "index" or "index.html" - all of that optional and configurable. Output format can be json or html; for html a string for template is required.
Next improvement could optionally add files stats to output

Motivation

Can be useful to have an index for dir navigation or to quickly expose files

Example

A draft example could be

json

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'public'),
  prefix: '/public/',
  index: { // optional
    format: 'json', // optional, default json (?), can be both ?
    names: ['/index', '/index.json', '/'] // optional, default '/'
  }
})

request
GET .../public/images or GET .../public/images/index.json

response

{
  "dirs": ["house", "office"],
  "files": ["bed.jpg", "kitchen.png"]
}

html

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'public'),
  prefix: '/public/',
  index: { 
    format: 'html',
    template: '<html> ... TDB ... </html>',
    names: ['/index', '/index.html', '/'] // optional, default '/'
  }
})

request
GET .../public/images or GET .../public/images/index.html

response

<html>

  DIRS
  <a href="/public/house">house</a>
  <a href="/public/office">office</a>

  FILES
  <a href="/public/bed.jpg" target="_blank">bed.jpg</a>
  <a href="/public/kitchen.jpg" target="_blank">kitchen.jpg</a>
</html>

Support for static compression?

Not sure if this is the right place to ask but is it possible to support static compressed files: For example if a request is received for http://localhost/bundle.js with Accept-Encoding: brotli, I want to serve the already compressed bundle.js.br instead of compressing bundle.js on the fly. Same if gzip compression is requested, I'd want fastify-static to send bundle.js.gz if it exists. For my goal if the pre-compressed file does not exist then I'd want to send the uncompressed file, lack of pre-compressed file would mean that the build system determined that the compressed file was actually larger.

Am I correct that for fastify-static to support this it would need to be supported by send? They have a PR to add this feature but it appears to have stalled.

Optional trailing "/" after prefix

🐛 Bug Report

I am trying to serve static content over /docs prefix, but being redirected to /docs/ since trailing slash is appended by default.

To Reproduce

Register route with prefix that does not have trailing /, start application, assuming everything done right static content in docs folder will be available at /docs/ instead of /docs.

app.register(fastifyStatic, {
    root: path.join(__dirname, 'docs'),
    prefix: '/docs'
  });

Expected behavior

Static content be available at /docs instead of /docs/.

Your Environment

  • node version: 12
  • fastify version: 2.13.1
  • os: Linux

async style not supported

🐛 Bug Report

When async style is used, undefined promise error is always logged.
Originally filed in as help issue 106

To Reproduce

Steps to reproduce the behavior:

Change the example in in project to use async and watch logs.

'use strict';

const path = require('path');
const fastify = require('fastify')({ logger: { level: 'trace' } });

fastify
  .register(require('../'), { root: path.join(__dirname, '/public') })
  .get('/', async (request, reply) => {
    reply.sendFile('index.css');
  });

fastify.listen(3000, err => {
  if (err) throw err;
});

Expected behavior

No promise undefined error to be logged as per Promise resolution documentation.

Your Environment

  • node version: 12.7.0
  • fastify version: 2.8.0
  • os: Mac

percent-encoded URLs might fail in glob mode

🐛 Bug Report

When trying to access a URL containing (for example) %20 to indicate a space in the filename with fastify-static configured with wildcard: false:

  • if only the file with a space in its name is present, 404 is returned
  • if only a file with %20 in its name is present, 404 is returned
  • if both a file containing a space in its name and a file containing %20 in its name is present, the file containing the space in its name is served.

To Reproduce

Steps to reproduce the behavior:

var  fastify = (require('fastify'))({});

fastify.register(require('fastify-static'), {
  root: __dirname,
  prefix: '/',
  wildcard: false
});

fastify.listen().then(console.log);
touch 'a .md'

Start JS script, try to get /a%20.md: 404

touch 'a%20.md'

Start JS script, try to get /a%20.md: OK

rm 'a .md'

Start JS script, try to get /a%20.md: 404

Expected behavior

Since the file containing the space in its name is served properly, it should be available as containing %20 in its name. This means glob should use percent-encoded URLs for non-unreserved characters (as defined in RFC3986).

Your Environment

  • node version: 14
  • fastify version: 3.4.1
  • os: Linux

Support preRequest hooks

🚀 Feature Proposal

Support preRequest hooks, or a middleware like option, for intercepting before handling serving statics.

Motivation

For cases like, filter files, or serve statics depends on request attributes. In my case, I want to serve .map file only to developer instead of all end users.

We could implement this with a hook, or middleware, or something else?

Can no longer use the catch all route

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'public'),
})

// the catch all route below will never be called 😥
fastify.get('*', function (request, reply) {
  console.log('Catch all')
  reply.send('*')
})

Set content type: The character encoding of the plain text document was not declared

Whe using http2: true with fastify, I get:

The character encoding of the plain text document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the file needs to be declared in the transfer protocol or file needs to use a byte order mark as an encoding signature.

How do I set the content type for files?
Right now I serve my test.html file like this (it test the api):

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, '/public'),
  prefix: '/public/', // optional: default '/'
})

Thanks!

How to use a Layout ?

Hi,
I would like to know if it's possible to use a Layout with Fastify-Static.

  • Every page have the same header
  • Every page have the same footer
  • Every page have the same style and layout

Can you share a solution or it's not possible ?

Thank you

How can i get my image that saved in server?

Hello, can i get my image that saved in my server?
so i saved my image at public in root folder, can i get it and show it in my frontend app?
Thank you

this give me an error

fastify.register(require('fastify-static'), {
root: path.join(__dirname)
})

fastify.get('*', function (req, reply) {
    reply.sendFile('client/build', 'index.html')
})

fastify.get('/api/gambar', function (req, reply) {
    reply.sendFile('public/gambar', 'noimage.png')
})

Not working with svelte/sapper middleware

🐛 Bug Report

Using fastify-static plugin with sapper middleware gives 404 on any static file

To Reproduce

Follow these steps: https://www.matthewcantelon.ca/blog/sapper-fastify/
The static files are not served (it gives 404) while it works with sirv

fastify.use(sirv('static'))

Without the sapper middleware, it works
Would it be an issue with the plugin not doing sth at the end that let the middleware "break"?

Expected behavior

The static files should be served

Your Environment

  • node version: v13.2.0
  • "fastify": "^2.10.0"
  • "fastify-static": "^2.5.1"
  • "sirv": "^0.4.2"
  • os: Linux
  • any other relevant information

Type link directly return 404 error

I've error when i typed my link directly like this localhost:5000/katalog, it send me error 404. But if i move from link to link using (React Router Dom) it doesn't show me error.
Here's my screen recorder of this behaviour Youtube Video.
Why this happened?

Sporadic ERR_STREAM_PREMATURE_CLOSE

🐛 Bug Report

Seemingly at random, fastify-static will fail to serve a static file.

  • Refreshing/re-requesting the file usually fixes it
  • Happens for text responses and binary files such as PNGs
  • Happens with or without fastify-compress

Stack trace:

Error: Premature close
    at PassThrough.onclose ([redacted]/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:62:73)
    at PassThrough.emit (events.js:215:7)
    at emitCloseNT ([redacted]/node_modules/fastify-static/node_modules/readable-stream/lib/internal/streams/destroy.js:56:8)
    at processTicksAndRejections (internal/process/task_queues.js:79:21)

Error log in console:

{
  "level": 50,
  "time": 1574780438858,
  "pid": 12747,
  "hostname": "[redacted]",
  "reqId": 12,
  "req": {
    "method": "GET",
    "url": "/sa/Home_qVN1-2b1b950.js",
    "remotePort": 52715
   },
   "res": { "statusCode": 500 },
   "err" :{
     "type": "NodeError",
     "message": "Premature close",
     "stack": "Error: Premature close\n    at PassThrough.onclose ([redacted]/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:62:73)\n    at PassThrough.emit (events.js:215:7)\n    at emitCloseNT ([redacted]/node_modules/fastify-static/node_modules/readable-stream/lib/internal/streams/destroy.js:56:8)\n    at processTicksAndRejections (internal/process/task_queues.js:79:21)",
     "name": "Error",
     "code": "ERR_STREAM_PREMATURE_CLOSE"
    },
  "msg": "Premature close",
  "v": 1
}

To Reproduce

Steps to reproduce the behavior:

  1. Serve some static files with fastify-static
  2. Seemingly randomly, the above will happen for page assets
  3. The file indeed never makes it to the browser

Paste your code here:

import path from 'path'
import serveStatic from 'fastify-static'
import fp from 'fastify-plugin'

function staticAssets (server, opts, next) {
  server.register(serveStatic, {
    root: path.join(__dirname, '../browser'),
    prefix: '/sa/',
    maxAge: 9999999,
    immutable: true,
    dotfiles: 'ignore',
    index: false,
    decorateReply: false
  })

  server.register(serveStatic, {
    root: path.join(__dirname, '../server/magic-urls'),
    maxAge: 24 * 60 * 60, // 1 day
    dotfiles: 'ignore',
    index: false,
    decorateReply: false
  })
  next()
}

export default fp(staticAssets, {
  fastify: '2.10',
  name: '[redacted]-static-assets'
})

This plugin is then registered like so:

import staticAssets from './static-assets'

fastify.register(staticAssets)

Expected behavior

A clear and concise description of what you expected to happen.

Paste the results here:

Your Environment

  • node version: 12.13.0
  • fastify version: 2.10.0
  • os: MacOS Mojave 10.14.6
  • Requesting assets with MacOS Firefox 71, but it doesn’t appear to be doing anything special in its devtools

setNotFoundHandler is broken with Fastify v2

I checked a bit and couldn't understand what the problem might be. I played around with the tests of setNotFoundHandler in main Fastify repo and they seem to be good.

Any ideas what might be wrong?

https://github.com/fastify/fastify-static/blob/master/test/static.test.js#L362

  not found responses can be customized with fastify.setNotFoundHandler() > /path/does/not/exist.html
  not ok should be equal
    +++ found
    --- wanted
    -text/plain
    +application/json; charset=utf-8
    compare: ===

  not found responses can be customized with fastify.setNotFoundHandler() > /path/does/not/exist.html
  not ok should be equal
    +++ found
    --- wanted
    -/path/does/not/exist.html Not Found
    +{"statusCode":404,"code":"ENOENT","error":"Not Found","message":"ENOENT: no such file or directory, stat 'C:\\Users\\cemre.mengu\\Desktop\\fastify-static\\test\\static\\path\\does\\not\\exist.html'"}
    compare: ===

Reloading a static page served by fastify-static gets stuck

In my test app, which simply uses fastify-static for serving index.html and some css files, etc, the page loads fine the first time. But pressing the reload button gets stuck. Chrome just shows the spinner on the tab, displaying nothing. It looks like the index.html file is served fine but requests for all other resources are pending forever.

If I clear the cache and the cookies, the page loads again fine. But only the first time. The same issue afterwards.

My env:

  • fastify: 1.0.0
  • fastify-static: 0.10.0
  • using http2 with tls-keygen-generated certificates

folders without trailing slash hang fastify

i'm using the below to select the public directory

fastify.register(require('fastify-static'), {
  root: path.join(__dirname, 'public')
});

inside public is index.html & 3 folders js, css & img as expected

if i browse to:
/css/stylesheet.css --> I get the correct sheet and it works OK
/css/ --> returns 404 which is expected
/css --> fastify hangs and does not return a response and the browser sits waiting for a response

Testing with Google Chrome & Microsoft Edge and both have the same issue

Inability to serve multiple prefixed root URL's

For a development server I'm working on I tried the following:

const path = require('path');
const fastify = require('fastify')();
const fastifyStatic = require('fastify-static');

fastify.register(fastifyStatic, {
	root: path.join(__dirname, 'node_modules'),
	prefix: '/node_modules/',
});

fastify.register(fastifyStatic, {
	root: path.join(__dirname, 'html/myapp'),
	prefix: '/myapp/',
});

This causes an exception from node_modules/fastify/lib/decorate.js:38:
Error: The decorator 'sendFile' has been already added to Reply!

Is it possible to fix this within fastify-static or should I write my own middleware that uses send directly?

An in-range update of fastify is breaking the build 🚨

Version 1.11.0 of fastify was just published.

Branch Build failing 🚨
Dependency fastify
Current Version 1.10.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

fastify is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes v1.11.0

Features

  • Added pluginTimeout option - #1088

Internals

  • Override address in listen instead of listenPromise - #1102
  • Rename and call unknown method tests from http2 - #1095
  • Ensure that error-in-post test is run - #1096
  • Add test for trust proxy with function - #1098

Documentation

  • Move Server-Methods into Factory - #1101
  • Update Validation-and-Serialization.md - #1094
Commits

The new version differs by 11 commits.

  • c62ace8 Bumped v1.11.0
  • acf3950 Override address in listen instead of listenPromise (#1102)
  • e6bca66 Move Server-Methods into Factory (#1101)
  • ba9a629 Update Validation-and-Serialization.md (#1094)
  • e77cae9 Add test for trust proxy with function (#1098)
  • 6bce249 Ensure that error-in-post test is run (#1096)
  • 3895a75 Rename and call unknown method tests from http2 (#1095)
  • 1f750e6 Ignore pino in greenkeeper, it's a semver-major change
  • 28436d1 chore(package): update concurrently to version 4.0.0 (#1091)
  • a258482 Update TypeScript to 3.0.1 (#1092)
  • 50bcf6b Added pluginTimeout option. (#1088)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

render static file with route parameter

I am using plugin ponit-of-view and fastify-static, I have a route for example : fastify.get('/', function (request, reply) { reply.view('/index.ejs', { text: 'text' }); }) in the file index.ejs, I am importing a css file and js, it is work perfect.

But when I change route for this example: fastify.get('/:dynimic/route', function (request, reply) { reply.view('/index.ejs', { text: 'text' }); })
I have a problem, see below.
GET http://localhost:3000/astes/css/css.css net::ERR_ABORTED GET http://localhost:3000/astes/js/console.js net::ERR_ABORTED.

HTTP2 / Connection refused / 304 response

I recently started to use Fastify to have http2 support.

I just noticed if I reload my browser with caching enabled (so not using Chrome DevTools 'Disable Cache' option) almost every time I have a "Connection refused / 304" error and my asset is not loaded.

I'm running it on localhost now, using a self-signed certificate, added the certificate as an Always Trusted cert. I'm using Chrome 70.0.3538.110 on OSX.

image

Once I turn off the http2 in Fastify everything works fine.

image

I was wondering if could it be because http2 push is used? I was trying to simply have http2 protocol and static asset serving, i can live without http2 push. (it show the same symptoms as the node-auto-push, which I tried before fastify-static)

I have this error (using pm2) in the logs:

TypeError: Cannot read property 'Symbol(trailers)' of undefined
  at ServerHttp2Stream.onStreamTrailersReady (internal/http2/compat.js:377:36)
  at ServerHttp2Stream.emit (events.js:182:13)
  at Http2Stream.onStreamTrailers [as ontrailers] (internal/http2/core.js:311:15)

My index.js looks like this (removed unnecessary parts):

const fastify = require('fastify')({
  logger: {
    prettyPrint: DEBUG,
  },
  trustProxy: false,
  http2: true,
  https: {
    allowHTTP1: true,
    key: fs.readFileSync(path.join(__dirname, '.', 'https', SSLKey)),
    cert: fs.readFileSync(path.join(__dirname, '.', 'https', SSLCert)),
  },
});

const helmet = require('fastify-helmet');
const fastifyPug = require('fastify-pug');

const assetRoot = path.join(__dirname, '..', 'client', 'assets');

fastify.register(require('fastify-static'), {
  root: assetRoot,
});

fastify.register(require('fastify-compress'), {
  global: true,
});

fastify.register(helmet, {
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ['\'self\''],
      styleSrc: ['\'self\'', '\'unsafe-inline\''],
      scriptSrc: ['\'self\'', '\'unsafe-inline\''],
    },
  },
  featurePolicy: {
    features: {
      fullscreen: ['\'none\''],
      payment: ['\'none\''],
      syncXhr: ['\'none\''],
      microphone: ['\'none\''],
    },
  },
  frameguard: {
    action: 'deny',
  },
  hidePoweredBy: { setTo: 'Sun and love <3' },
  referrerPolicy: { policy: 'same-origin' },
});
fastify.register(fastifyPug, { views: `${path.join(__dirname)}/views` });

fastify.get('/', (request, reply) => {
  reply
    .code(200)
    .render('index.pug');
});

fastify.listen(SECUREPORT, HOST, (err) => {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
});

I'm stuck now, but really don't want to revert to http1.1 or to manually serve assets.
Can the Node 10 and its experimental http2 feature the cause?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.