Coder Social home page Coder Social logo

Comments (8)

DylanPiercey avatar DylanPiercey commented on July 24, 2024

Would be good to know why fastify isn't working with what we have since their docs say you can reply with a stream.

Either way it seems if we want to use the raw response we must also call https://www.fastify.io/docs/latest/Reference/Reply/#hijack

from fastify.

J-Hoh avatar J-Hoh commented on July 24, 2024

Short update:
Looking into what fastify does when you pass a stream to the reply.send() method revealed that it's pretty much the same as a direct pipe into the raw stream, EXCEPT that it's first setting headers on the raw response.

It seems my "solution" only works when sending absolutely no headers (the fastify reply.type() does not get sent before the raw pipe!).
EDIT: Sending a "Content-Type" header with the stream makes it wait till the stream is done. However that poses another problem... my main project suddenly gets recognized as plain text, so no html rendering...

from fastify.

J-Hoh avatar J-Hoh commented on July 24, 2024

Had another look and it seems like compression is the culprit...
The fastify-compression plugin does not handle html streams properly (who expects them to be used like marko does). This could be (temporarly) fixed by not compressing marko stream outputs via setting a header:
this.request.headers["x-no-compression"] = "true";
The Header is being checked by the plugin and - if present - no compression will happen.

This alone doesn't completely eliminate the problem tho, as in development mode, the webpack-dev-server somehow also compresses the passthrough'd stream (gzip) thus staggering/buffering the response.
The direct stream.pipe.(reply.raw) somehow circumvents this compression. reply.send(stream) does not.

from fastify.

DylanPiercey avatar DylanPiercey commented on July 24, 2024

Good find, I think the main issue is that fastify-compress does not expose an equivalent api to https://github.com/expressjs/compression#resflush.

We may want to make a PR there and/or figure out a way to achieve the same.

from fastify.

DylanPiercey avatar DylanPiercey commented on July 24, 2024

I need to test this, but we may be able to do something like:

stream.once("pipe", to => {
  if (to.flush) stream.flush = to.flush.bind(to)
});

from fastify.

J-Hoh avatar J-Hoh commented on July 24, 2024

Will test around with that aswell, looks promising.

Another workaround would be to simply change how the fastify-compression compresses streams, as it does expose these options!

fastify.register(fastifyCompress, {
	zlibOptions: {
		// flush: constants.Z_PARTIAL_FLUSH, // EDIT: Deprecated, use Z_SYNC_FLUSH instead
		flush: constants.Z_SYNC_FLUSH,
	},
	brotliOptions: {
		flush: constants.BROTLI_OPERATION_FLUSH,
	},
})

These are literally the options passed to the stream compression functions from zlib (createBrotliCompress/createGzip/createDeflate), which by default would compress the entire stream once it reached its end, as that's the "best" way to compress data.
This might be a desired setting, but your find definitely makes it more easy to use.

from fastify.

DylanPiercey avatar DylanPiercey commented on July 24, 2024

So it turns out that because of the way they wrap the stream the flush api from the compression stream is not exposed (https://nodejs.org/dist/latest-v16.x/docs/api/zlib.html#flushing).

It would be great to figure out how to possibly enable this in fastify-compress and maybe we should make an issue over there.

Your configuration above is a good alternative, we could also just document that as a solve. I wonder if there is a way we could have it so that when a Marko template is rendered we automatically configure these? Also it seems like we should use Z_SYNC_FLUSH instead.

from fastify.

DylanPiercey avatar DylanPiercey commented on July 24, 2024

@J-Hoh I just updated the docs to highlight this issue. Thanks for bringing it up!

I can't find a way to automate this with the ways fastify-compress works currently and I'm not quite sure what'd be the best way to tweak that module also.

I do think simply changing the config for that module is a good enough work around though, and I'll make sure our examples are updated accordingly!

from fastify.

Related Issues (4)

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.