I’m having trouble serving static files (image assets, etc.) for a small game I’m working on in Phaser. I’m using flask-socketio on the server (and socket.io on the client-side) for networking which is why I’m trying to get this working under Flask. As far as I can tell, I must use Flask to serve the static resources because otherwise I run into the problem of the Same-origin policy.
Indeed, I tried serving the assets with nginx on a different port but I got this message in my browser console (Safari in this case): SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
I looked in the Flask documentation on how to serve static files and it said to use “url_for.” However, that only works for HTML template files. I’m trying to load the static resources inside my javascript code using the Phaser engine like so (just for example):
this.load.image('player', 'assets/player.png’); //this.load.image('player’, url);
where I cannot obviously use ‘url_for’ since it’s not a template file but javascript code.
So my question is, how do I serve my static resources so that I don’t violate the same-origin policy?
Is there another secure way to serve static resources in Flask besides using ‘url_for’?
Or should I be using nginx as a reverse proxy? In the flask-socketio documentation I found this nginx configuration snippet: Flask-SocketIO documentation (please scroll down to where it says "Using nginx as a WebSocket Reverse Proxy”)
Regarding #2, I don’t quite understand how that should work. If I should be doing #2, can someone kindly explain how I should configure nginx if Flask is listening on port 5000? Where in that snippet do I configure the path to my static assets on the filesystem? And in my javascript code, what url path do I use to reference the assets?
Normally, one would set up Nginx (or some other general web server) on the "main" port, and then configure it to forward certain requests to your application server (in this case, Flask) on a secondary port which is invisible/unknown to the client browser. Flask would provide the result to Nginx which would then forward the result to the user.
This is called a reverse-proxy, and Nginx is widely considered a good choice for this setup. In this way, all files are served to the client by Nginx, so the client doesn't notice that some of them actually come from your application server.
This is good from an architectural standpoint, because it isolates your webapp (somewhat) from the client, and allows it to conserve resources, e.g. by not serving static files and by having Nginx cache some of the webapp's results when it makes sense to do so.
If you're doing development, this may seem like a lot of overhead; but for production it makes a lot more sense. However, it is a good idea to have your dev environment mimic your prod environment as closely as possible.
Related
I have a vue.js SPA which I want to deploy on different servers without recompiling the frontend for each deploy. The SPA connects to a backend, with a url yet unknown to the spa. Is there a way I can dynamically tell the frontend at runtime where the backend is?
Many articles and forum threads suggest to just use different config files for different environments and build them in at build time, but that is not an option for me because I simply don't know where the frontend/backend will be deployed when building it.
EDIT: The project is an open source project, so I can't really make an assumption about how people will deploy it. I've always kind of "assumed" it would be deployed on a seperate sub domain, with the frontend being reachable at / and the backend with a proxy at /api because that's how I set up my server.
However, I've seen people deploying the api at a totally different sub domain (sometimes even with different ports) than the frontend or on a sub path or even a mixture between the two.
Things I've considered so far:
Putting the config in a conf.js which would then expose the backend url via window.config.backendUrl or similar and load that file in my index.html from a <script> tag
Slightly similar to 1.: Put the config in a config.json and making a fetch request to it once the application loaded, then exposing the result of it in window.config.backendUrl
Inserting a <script>window.config.backendUrl = 'http://api.example.com'</script> in my index.html.
Serving the frontend with a custom made web server (based on express or similar) which parses either env or a different config file and then creates the <script> tag from 3. dynamically
Always "assuming" where the backend will be with some kind of list to work up, like "First look at /api then at ./api then at api.current-host.com etc."
Bundling the frontend with the backend - that way I would always "know" where the backend relative to the frontend is.
Yet all of theses options seem to me a bit hacky, I think there has to be a better way.
My favourite is the third option because it is the best trade off between configurability and performance IMHO.
If I was in the same situation I would have considered the following 2 approaches:
Deploying a JSON file with the same name but with different contents - so the frontend can always fetch its configuration by making AJAX call to /config.json but this file will depend on where you deploy and will be generated during the deployment step
Using a single API endpoint with a fixed/constant URL (completely separate from your backends) - so that frontend always calls this API endpoint to get its configuration at startup and the actual URL of the corresponding backend for its further operation.
Basically (2) is just the dynamic version of the static configuration in (1).
If I have nodejs serve every file on my website, does it load faster than just plain HTML? Say, for instance, I had a site with loads of pictures. Does having expressjs serve them make the content load faster on page load?
No.
Nodejs has an http server module 'baked-in', but it's not necessarily faster than using any other HTTP server like Apache or Nginx.
In fact, you're likely to have Apache or Nginx fronting Node so that you can enable multiple domains on any given server.
If you're looking for blazing fast HTML service, you should look into cacheing your HTML pages in-mem using something like Redis.
No. It is more likely to make it slower since your application won't be optimised (compared to most HTTP servers) for serving static content.
I'm new to AJAX development. Due to same-origin policy, the most inconvenient thing for me so far is to modify the host information string (such as absolute URLs) in JavaScript files every time whenever I try to deploy the local files to the remote. I thought about writing a shell script for doing this but it seems awkward and not flexible. What's the best practice for doing this?
EDIT:
What if I wanna debug the remote AJAX app instead?
Add Access-Control-Allow-Origin: * header to your response. It's depends on what backend or server side you are using. There are some reference:
HTTP Access Control
Enable CORS in Apache
Website about "enable cross-origin resource sharing"
I want to build a single page application using Ember.js in the client, and Sails.js for a REST API.
I would like to completely separate the client from server, and was thinking to host all the client assest (css, img and index.html) in a CDN or s3, while the server will probably be hosted on Horoku.
How do I avoid cross-domain problem? using a CNAME maybe?
Is this common practice?
What tools are available for such a deployment process?
Thanks!
You can use Cross-Origin Resource Sharing (CORS) for this. CORS is a way for web servers to let web browsers know which third-party domains (origins) are allowed to access their content. So basically, you want to ensure that whatever CDN you use supports CORS headers, so that you can tell the CDN the domain of the server that will be loading the resources.
Here's an article on turning CORS on for Amazon S3. It's based around using a CDN to server web fonts, but the concept applies equally to all protected files (i.e. everything besides CSS, images and Javascript files loaded in the HTML).
You could also use another Sails server as your CDN, as it supports CORS out of the box (docs here). It would probably take some tweaking to do all the fancy caching that high-end CDNs do, but it can be done!
In a system that I'm building I want to serve
Static files (static HTML pages and a lot of images), and
Dynamic XML generated by my servlet.
The dynamic XML is generated from my database (through Hibernate) and I use Restlets to serve it in response to API calls. I want to create a static file server (e.g. Apache) so that this does not interfere with the dynamic server traffic. Currently both servers need to run on the same machine.
I've never done something like this before and this is where I'm stuck:
The static HTML pages contain JavaScript that makes API calls to the dynamic server. However, since the two servers operate on different ports, I get stuck with the same origin problem. How can this be solved?
As a bonus, if you can point me to any resources that explain how to create such a static/dynamic content serving system, I'll be happy.
Thanks!
You should setup mod_proxy in apache to forward dynamic requests to whatever backend server you are using. Your existing setup (ie. two separate ports) is perfect, you just need to tell apache 'proxy dynamic requests to my backend server without letting the browser know'.
This page should get you started - http://httpd.apache.org/docs/1.3/mod/mod_proxy.html
You need to load a script tag from the Reslet server... have a look at JSONP and this SO post