Cherrypy, serving static files takes a lot of time when page opened in more than one browser, files are never loaded from cache - cherrypy

I'm using Cherrypy 3.6.0 framework. I have problem with long time loading pages (serving static files takes a lot of time) when I open page in more than one browser. In that case, for example, bootstrap.min.css file which has 120kB can load 5-10 seconds. What is worse, static files are never cached, so every time page is loaded static files are again loaded and again it takes multiple seconds before page will load. When server respond 304 Not modified it also takes the same amount of time before client side receive this answer (there is no difference in response time no matter if static file is loaded or server respond 304). My serving static files configuration:
cherrypy.tree.mount(None, '/static', config={
'/': {
'tools.staticdir.on': True,
'tools.staticdir.dir': static_dir,
'tools.sessions.on': False,
'tools.caching.on': True,
'tools.caching.force' : True,
'tools.caching.delay' : 0,
'tools.expires.on' : True,
'tools.expires.secs' : 60*24*365
}
}
)
I can't understand how it is possible that fetching 120kB file can take so much time... Maybe someone can give me advise where can I look for reason of this problem?
EDIT:
Headers:
Remote Address:192.168.100.100:80
Request URL:http://192.168.100.100/static/css/bootstrap.min.css
Request Method:GET
Status Code:304 Not Modified
Request Headersview source
Accept:text/css,*/*;q=0.1
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie:session_id=.......................................
Host:192.168.100.100
If-Modified-Since:Mon, 22 Dec 2014 12:30:51 GMT
Referer:http://192.168.100.100/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Response Headersview source
Date:Fri, 14 Jan 2000 23:51:25 GMT
Server:CherryPy/3.6.0
Vary:Accept-Encoding
In timining overlap I have:
Stalled: 9.619ms
Request sent: 0.171ms
Waiting (TTFB): 5.02s
Content download: 1.000ms
I checked what is TTFB and this is the duration from the virtual user making an HTTP request to the first byte of the page being received by the browser. So something is wrong with server responsiveness...
EDIT2:
I have created minimal app which only loads static files and problem still occurs. This is app code:
server:
import cherrypy
def start():
import app
app.application()
cherrypy.config.update({'server.socket_host': '0.0.0.0', 'server.socket_port': 9061 })
engine = cherrypy.engine
engine.autoreload.unsubscribe()
try:
engine.start()
except:
sys.exit(1)
else:
engine.block()
if __name__ == '__main__':
start()
app:
import cherrypy
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('/tmp/cherry/'))
static_dir = '/media/vbox_shared/new_web/app/static'
class Test(object):
#cherrypy.expose
def index(self):
template = env.get_template('test.html')
return template.render()
def application():
cherrypy.tree.mount(Test(), '/', config = {})
cherrypy.tree.mount(None, '/static', config={
'/': {
'tools.staticdir.on': True,
'tools.staticdir.dir': static_dir
}
})
html:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<link rel="stylesheet" href="/static/css/style.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/chosen.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/jquery.jgrowl.min.css"/>
<link rel="stylesheet" href="/static/css/m-buttons.min.css"/>
<title>Streams</title>
<title>test</title>
</head>
<body>
<h1>test</h1>
<script src="/static/js/jquery-1.11.1.min.js"></script>
<script src="/static/js/jstree.min.js"></script>
<script src="/static/js/functions.js"></script>
<script src="/static/js/stream.js"></script>
<script src="/static/js/chosen.jquery.min.js"></script>
<script src="/static/js/chosen.proto.min.js"></script>
<script src="/static/js/jquery.jgrowl.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
links to screenshots:
http://i58.tinypic.com/21m8ar5.png
http://i60.tinypic.com/euh6p0.png
EDIT3:
I have reduced my app to:
import cherrypy
class HelloWorld(object):
def index(self):
return """
<html>
<head>
<link rel="stylesheet" href="/static/css/style.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/chosen.min.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/jquery.jgrowl.min.css"/>
<link rel="stylesheet" href="/static/css/m-buttons.min.css"/>
<title>Streams</title>
<title>test</title>
</head>
<body>
<h1>test</h1>
<script src="/static/js/jquery-1.11.1.min.js"></script>
<script src="/static/js/jstree.min.js"></script>
<script src="/static/js/chosen.jquery.min.js"></script>
<script src="/static/js/chosen.proto.min.js"></script>
<script src="/static/js/jquery.jgrowl.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>"""
index.exposed = True
conf = {
'/static':
{
'tools.staticdir.on': True,
'tools.staticdir.dir':'/media/vbox_shared/new_web/app/static'}
}
cherrypy.config.update({'server.socket_host': '0.0.0.0', 'server.socket_port': 9066 })
cherrypy.quickstart(HelloWorld(), config=conf)
And problem still occurs. When I open main page in IE, FF, Safari and Chrome - some static files are loading more than 10 seconds ...

You must have omitted some headers and some configuration. CherryPy sends Vary: Accept-Encoding only for gzipped responses. Normally it sends Last-Modified, Content-Type, Content-Length and some others. Also note that Cache-Control: max-age=0 means you do a refresh request asking server to validate the resource.
In the answer I linked in the comment I showed that normally 304 Not Modified only costs CherryPy a os.stat call which is instant, unless your disk is broken.
What I suggest you to do is to run a separate CherryPy app on the same static directory with only tools.staticdir on, to avoid possible misconfiguration, session lock issues etc. Then gradually append configuration and measure the response time e.g. with Apache's ab -c 10 -n 1000 http://192.168.100.100/static/css/bootstrap.min.css.

Related

Office.js Office.context.ui.messageParent not working in Excel

We have an excel add-in hosted in azure where the Office.context.ui.messageParent API messages aren't being sent/received on the desktop. There's no errors, the message just doesn't get caught at the event listener.
We use the dialog for MFA and we have it working locally for both desktop and web but when we deploy to a stage add-in hosted in azure this issue occurs just on the desktop.
This works:
dialog url (https://localhost:3000/dist/callback.html)
taskpane url (https://localhost:3000/dist/taskpane.html)
This doesn't:
dialog url (https://ip-dev-custom-functions.azurewebsites.net/addin/callback.html)
taskpane url (https://ip-dev-custom-functions.azurewebsites.net/addin/taskpane.html)
Surprisingly the DialogEventReceived is being triggered but not the message DialogMessageReceived.
callback.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta http-equiv="Expires" content="0"/>
<meta http-equiv="Cache-Control" content="private, no-cache, no-store"/>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Expires" content="-1"/>
<title></title>
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
</head>
<body>
<script>
if (window.opener)
window.opener.postMessage({type: 'interstitial', url: document.location.href}, "*");
Office.initialize = function (reason) {
console.log("Sending auth complete message through dialog: " + document.location.href);
Office.context.ui.messageParent(document.location.href);
}
</script>
</body>
</html>
snippet of the taskpane.html where's the event listener:
Office.context.ui.displayDialogAsync(url, {
height: dim.height,
width: dim.width,
promptBeforeOpen: false
}, async (result) => {
_loginDialog = result.value;
_loginDialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
_loginDialog.addEventHandler(Office.EventType.DialogEventReceived, (ev) => {
console.log("## EVENT RECEIVED ##", ev);
});
});
function processMessage(arg) {
console.log("Message received in processMessage: " + JSON.stringify(arg));
_lastCallback(arg.message);
_loginDialog?.close();
_loginDialog = null;
}
Based on Authenticate and authorize with the Office dialog API, the correct flow is:
The add-in should launch the page in the dialog in add-in's domain, then redirect to the sign-in page, and then redirect to another page with the same domain as the first page in dialog again.
Otherwise, the messageParent API won't work, because it only trust the domain of the page used in the displayDialogAsync() API. In your scenario, the sign-in page (launched first time in the dialog) and the callback page are in different domains, which causes the problem.
Thanks.

How to change the line "var domToPdf = require('dom-to-pdf');"

I want to use a NodeJs Module on the browser. I read, that I can do this with http://browserify.org/.
Concret I want to use this NodeJs Module: https://github.com/ovvn/dom-to-pdf
So I create a bundle.js form this like explained here: http://browserify.org/
You can see my bundle in my github repo: https://github.com/astridx/dom-to-pdf/blob/javascriptexport_browserify/bundle.js
But now I do not know how to go on. I created an example: https://github.com/astridx/dom-to-pdf/blob/javascriptexport_browserify/example/index.html
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./../bundle.js"></script>
</head>
<body>
<div id="test">TODO write content</div>
<script>
var domToPdf = require('dom-to-pdf');
var element = document.getElementById('test');
var options = {
filename: 'test.pdf'
};
domToPdf(element, options, function () {
console.log('done');
});
</script>
</body>
</html>
But I do not know how to change the line var domToPdf = require('dom-to-pdf');
Can someone give me a hint?
Try using import instead, but you might need babel for that to work properly.
e.g import domToPdf from 'dom-to-pdf';

How to re-translate image from other website (hiding source URL)

I have a link to the image like
this or that.
I'm trying to re-translate this image from other source URL to some link, f.e http(s)://examplewebsite.com/john.
So, it doesn't need to be a redirect, but rather "showing" image on a different link. I've tried using express.static but it doesn't work.
Thanks in advance
If I understand it right, you have your express server and you want to include foreign images in response while hiding source url
In the simplest form, every time someone requests your page, you would fetch the image you want, encode it in base64 and include this base64 as src for the img
const express = require('express')
const fetch = require('node-fetch')
const app = express()
const port = 3000
app.get('/', (req, res) => {
fetch('https://www.gravatar.com/avatar/fdb4d2674d818861be4a4139469ebe59?s=48&d=identicon&r=PG&f=1')
.then(res => res.buffer())
.then(buffer => {
res.send(`
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>hello</p>
<img src="data:image\png;base64, ${buffer.toString('base64')}" alt="image">
</body>
</html>
`)
})
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
ideally you would create a separate endpoint for these images and also cache them (in memory or on hard drive) to not re-download them every time you need them

How to expose a static html page from ionic

I have a static html page which intercept authorization message, I'd like to expose this on the domain. It looks like so:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>JwtAuthDemo - Facebook Auth</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="assets/util.js"></script>
</head>
<body>
<script>
// if we don't receive an access token then login failed and/or the user has not connected properly
var accessToken = getParameterByName("access_token");
var message = {};
if (accessToken) {
message.status = true;
message.accessToken = accessToken;
}
else
{
message.status = false;
message.error = getParameterByName("error");
message.errorDescription = getParameterByName("error_description");
}
window.opener.postMessage(JSON.stringify(message), "http://localhost:5000");
</script>
</body>
</html>
If I place this page next to the index.html page it is not exposed, however when I place it inside the assets folder it can be access. I'm guessing I have to explicitly expose the page in one of the json config files however I'm not to sure how to do so?
I'd prefer not to have my redirect url be www.mydomain.com/assets/oauth-response-parser.html. I'd like to keep this in my application seeing as it's part of the application.
How can I expose a static html page from Ionic as a sibling to the index.html page ?
You can automatically get files to your assets directory by specifying that you want to run a custom script during your ionic builds.
In your package.json you'd have a 'config' section where you can specify this script:
...
"config": {
"ionic_copy": "./config/customCopy.config.js"
},
...
and then your customCopy.config.js would contain an entry to copy over your html into assets:
module.exports = {
copyAssets: {
src: ['{{SRC}}/assets/**/*'],
dest: '{{WWW}}/assets'
}
}
More info on this process at the ionic app scripts page
I hope this steers you in the right direction.

Node.js how to get http message (request, response) from net server (tcp server)?

I have the following code :
var net = require('net');
var fs = require('fs');
var path = require('path');
path = path.join(__dirname, 'index.html');
var fileAsAstream = fs.createReadStream(path);
var server = net.createServer(function (socket) {
socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 10\r\n\r\n");
fileAsAstream.pipe(socket);
console.log("server is up. port 8081");
});
server.listen(8081);
index.html
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
(1) Why does chrome make two connections to the server when I try http://localhost:8081 ? How can I make it work with one connection? And how I can format the html file in the browser during this tcp server.
or if there is something that can help me.
(2) It just reads the html file one time when I try to make two connections at telnet.
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 10
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Connection to host lost.

Resources