HTTP / 2: stream.end using For-Loop

How can a thread be closed within a for-loop ?

I am trying to create a push-stream HTTP / 2 resource in a loop while reading a .json configuration file. If there is only one resource in resurce.file,type , clicking will succeed. If there is more than one resource in the configuration, only the first specified resource is transferred, and the remaining resource is not pushed, and the client never receives the remaining files and does not complete the parsing.

I think that only the first resource stream ends, and the remaining open threads do not close.

I commented the way I think the code should function:

 // Verify if client can be pushed to: if (res.push) { // Read what resources should be pushed via config.json5: for(var i = 0; i < confg.resource.length; i++) { // Compare what URL requested the resources & pass the relevant files: if (req.url == confg.resource[i].url) { // Request the resource(s) to stream: var ps = fs.readFileSync('../build' + confg.resource[i].file) // Push the relevant resource stream(s): , stream = res.push(confg.resource[i].file , { // ..and set the content type; res: {'content-type': confg.resource[i].type}, }); // Close the resource stream(s): stream.end(ps, function() { // TODO(CelticParser): Remove for production ->v console.log("Pushed Sream"); }); } } } 

.config.json5:

 resource: [ // HTTP/2 Push-Streams { file: '/js/theme.min.js', type: 'script' }, { file: '/css/theme.min.css', type: 'style', url: '/' } ] 

Using the example above

If /js/theme.min.js specified first and /css/theme.min.css specified in seconds in the configuration, /js/theme.min.js will be downloaded by the browser, and the other file will not be downloaded and the client will freeze (not parsing continues). If the order of the resource lists is exchanged, the same thing happens. If there is only one file in the configuration, everything works as expected.

Any help would be greatly appreciated.

+5
source share
1 answer

The problem is in config.json5 . You check the requested url before transferring the files here:

 // Compare what URL requested the resources & pass the relevant files: if (req.url == confg.resource[i].url) { ... } 

But in your json only one element can pass the test, the other is missing the url property. Change your config to this (add url: '/' to the first element) and it will work:

 { resource : [ { file : '/js/theme.min.js', type : 'script', url : '/' }, { file : '/css/theme.min.css', type : 'style', url : '/' } ] } 

Tested by this small application, following the example of the http2 server , as well as with the server code.

server.js

 var fs = require("fs"); var path = require("path"); var http2 = require("http2"); var config = require("./config.json"); var options = { key : fs.readFileSync("./localhost.key"), cert : fs.readFileSync("./localhost.crt") }; //---------------------------------------------------- http2.createServer(options, function(req, res) { if (res.push) { config.resource.forEach(function(resource){ if (req.url === resource.url) { var push = res.push(resource.file, { res: {"content-type": resource.type } }); push.writeHead(200); fs.createReadStream(path.join("../build", resource.file)).pipe(push); } }); } res.writeHead(200); res.end(); }).listen(8080); 

The config.json file contains the corrected configuration described above.

Output

 Receiving pushed resource: ./js/bootstrap.min.js -> /Developer/so/tests/push-0 Receiving pushed resource: ./css/bootstrap.min.css -> /Developer/so/tests/push-1 
+1
source

Source: https://habr.com/ru/post/1237820/


All Articles