Why would my page have different dimensions when run from the server? - html

file:///Users/dg/Google%20Drive/code/websites/Q-Po/qpo/client/index.html
I have a page. When I access it from my local file system (via file:///*), pull up my developer console in Chrome, and type window.innerWidth, the result is 1162.
When I serve the same page from a Node server in the cloud via Express.js, like this...
var express = require('express'); //Require express for middleware use
const app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http); //IO is the server
app.use(express.static(__dirname + "/../client")); //Serve static files
app.get('/', function(req, res){
res.sendFile('./index.html');
});
... and then access it my browser at [url].com, I get window.innerWidth = 1278.
This apparently causes the served version of the page to scale down svg elements slightly (shown below.)
What gives?
local page (clipped horizontally -- focus on difference in scaling of elements in center between this and the below image:)
served page (also clipped horizontally)
The svg containers in the middle of the page are both 600x600, according to the element inspector, but they render at different actual sizes on my screen. How can this be?

Related

Rendering HTML + CSS with Node Express

I am using res.sendFile() to render my HTML page but the css styles are not being rendered as well.
I trie looking online for help and saw some people suggesting the use of express.static() to turn the files folder into a static one and that would make the css render, but honestly I didn't fully understand. I don't know if the css and html need to be on the same folder or not, or even how to structure the code after using static(). Can someone help me out?
Here's a snippet of the code
const express = require('express');
const userControl = require('./controller/userControl');
const routes = express();
routes.get('/login', (req, res)=>{
res.sendFile('login.html', {root: '../pages'});
});
Here's my file structure
(https://i.stack.imgur.com/R4mLY.png)

puppeteer doesn't render pages with images URLs without a protocol scheme

I'm trying to use puppeteer to render html email messages which contains images from urls which do not always contain a protocol scheme. For example: <img src="example.com/someimage.jpg" /a>, the src really should have been https://example.com/someimage.jpg or http://....
I'm well aware that the url should contain a protocol scheme but I don't have control over the html received in the message body of the emails. Many mail clients such as gmail will render such emails just fine. I would like to mimic this behavior in puppeteer.
Is there some way in Puppeteer to trap the error and then:
try https:// prepended to the href, and failing that
try http:// prepended to the href, and failing that
then display a broken image?
This is what I do to render the html:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setJavaScriptEnabled(false);
await page.setContent(htmlEmailBody);
const content = await page.$("body");
const imageBuffer = await page.screenshot({type: "jpeg", omitBackground: true, fullPage: true});
This works fine when all the urls have a scheme. What's the proper way to get this to work when some of the URLs don't always contain the scheme?
This question is related to puppeteer doesn't open a url without protocol but unfortunately it doesn't answer my question.

Display image that returns HTTP 503 in Firefox

I have a status badge image that returns the HTTP code 503 when the respective service is offline (but the webserver is still there serving calls). Now opening the image URL directly will display the image properly, regardless of the underlying 503 error code. But using it inside an <img> tag shows the broken image icon. How can I prevent that while still allowing the image itself to return a 503? (External services depend on that)
Here are some screenshots to illustrate what's going on:
The badge on the page:
The status message in the developer console:
The badge itself:
Note: This happens on Firefox. Not Chrome
Edit: Here are a few requested pieces information:
Firefox 78.0.2 (64-Bit)
It's served from the same domain. But the domain is essentially just proxying serveral underlying webservices. And this badge is originating from a different service but all on the same domain.
It's a SVG image if that makes any difference.
Since XMLHttpRequest can retrieve the output of any request, no matter the response code, it is possible to request for the image with XMLHttpRequest, and then convert the blob response type to a base64 format image, which can be loaded in the browser.
The CORS proxy I used in the sample code may not be necessary in the majority of cases, but could be useful in the case where the image you are trying to display has weird response headers that prevent access to the image from another domain.
Here is the sample code. It should work no matter the response code, CORS, etc.
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
// here, reader.result contains the base64-formatted string you can use to set the src attribute with
document.getElementsByTagName('img')[0].src = reader.result; // sets the first <img> tag to display the image, change to the element you want to use
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', "https://cors-anywhere.herokuapp.com/i.stack.imgur.com/8wB1j.png"); // don't include the HTTP/HTTPS protocol in the url
xhr.responseType = 'blob';
xhr.setRequestHeader('X-Requested-With', 'xhr');
xhr.send();
<img src="about:blank">
Everything works, as when you go into Inspect Element, you see that the src attribute of the <img> tag points to a base64 URL that can load in any browser.
You might want to compress or resize your images before uploading it to server , as they might be large enough to keep the server busy and show the error as most of the time, a 503 error occurs because the server is too busy.
More over the image is SVG so it might render dimesions before completing, hence I'd suggest
Try replacing the SVG with PNG or JPG
Also try for site like https://tinypng.com/ to compress the image size
This might work for you

How to convert HTML to image in Node.js

I need to convert an HTML template into an image, on a Node server.
The server will receive the HTML as a string. I tried PhantomJS (using a library called Webshot), but it doesn't work well with flex box and modern CSS. I tried to use Chrome headless-browser but it doesn't seem to have an API for parsing html, only URL.
What is the currently best way to convert a piece of HTML into image?
Is there a way to use headless Chrome in a template mode instead of URL mode? I mean, instead of doing something like
chrome.goTo('http://test.com')
I need something like:
chrome.evaluate('<div>hello world</div>');
Another option, suggested here in the comments to this post, is to
save the template in a file on the server and then serve it locally and do something like:
chrome.goTo('http://localhost/saved_template');
But this option sounds a bit awkward. Is there any other, more straightforward solution?
You can use a library called Puppeteer.
Sample code snippet :
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({
width: 960,
height: 760,
deviceScaleFactor: 1,
});
await page.setContent(imgHTML);
await page.screenshot({path: example.png});
await browser.close();
This will save a screenshot of the HTML in the root directory.
You can easily do it on frontend using html2canvas. On backend you can write the html on a file and access using a file URI (i.e: file:///home/user/path/to/your/file.html), it should work fine with chrome headless-browser and Nightmare (screenshot feature). Another option is to setup a simple HTTP server and access the url.

How to display static html page with image on Heroku

I'm trying to display an html page on Heroku that has an image tag. The image exists but I cannot figure out what path to use so that it can be found. I keep getting 404 errors with every absolute path I try, and I can't use a relative path, because it appends it to the place the html page was loaded from (which happens to be /api/errorcodes/x where x is a number that is used to find the original html page) I.E.
app.get('/api/errorcode/:errorcode', function(request, response) {
var errorcode = request.params.errorcode;
var doc = 'Error' + errorcode + '.html';
console.log('__dirname = ', __dirname);
response.sendFile(__dirname + '/views/pages/' + doc);
});
So the directory structure is as follows:
views/pages/Error1.html
views/pages/Error1.fld/img001.png
And Error1.html has <img src="/views/pages/Error1.fld/img001.png"> and returns 404 (The page Error1.html loads, but the image gets a 404 in the heroku logs).
I have also tried "/app/views/pages/Error1.fld/img001.png" as well as moving the image to /public and trying the same combinations from there. How do I tell the img tag where to find the image?!
Ok I finally figured this out. In case anyone else comes across this here is the answer:
Before declaring any routes, add the static middleware:
app.use(express.static(__dirname + '/public'));
"The static middleware has the same effect as creating a route for each static file you want to deliver that renders a file and returns it to the client" - excerpt from O'Reilly's Web Development With Node & Express book.
Then in the html file you can use <img src="/img/logo.png"> if your image file is at public/img/logo.png.