gevent static file rendering - wsgi

How to serve static files like css with a WSGI application written using werkzeug and pure
python.. No frameworks used..
this is my server..
from gevent import pywsgi
from Index import application
import os
application = SharedDataMiddleware(application, {
'/hello/template/': os.path.join(os.getcwd(), 'template')
})
print 'Serving on https://127.0.0.1:4000'
server = pywsgi.WSGIServer(('0.0.0.0', 4000), application,spawn=10000)
# to start the server asynchronously, call server.start()
# we use blocking serve_forever() here because we have no other jobs
server.serve_forever()
The template is the the path to static files like css and images. but this is only serving the application and not the static files. is there a feature where in gevent serves static files .. ? I did not find the documentation useful.

Serving static files directly from your WSGI application is a waste of resources, both CPU and memory, and it will not scale.
For public static files you should configure your front-end webserver to serve them directly.
For private static files you can do access control and construct a response header in your WSGI app, and then let the front-end webserver do the heavy lifting of actually sending the file contents. Take a look at X-Sendfile (Apache) or X-Accel-Redirect (Nginx).

Related

Core Nodejs static file serving

How to serve static files with core Nodejs(not using any framework). Also, Indicate a public folder as static folder like express middleware.
express.static(root, [options])
In my code, static files are working/serving with local development, but not working/serving some static files like .css/fonts over the https on deployment.

How can I connect my NodeJS/Express backend to my VueJS frontend using only one port on my local machine?

My Vue app is set up using Vue CLI (Webpack) and it's working as it should. My NodeJS/Express REST API is also working properly. However, to run them simultaneously I now start a local server for each of them -- each with its own port. I would like to have both of them communicate over one port.
Localhost:8080 should point to the home page of my Vue App and the API requests should follow localhost:8080/api/...
In my production environment I use one and the same port/URL by serving the Vue App as a set of static files ('dist' folder). In my development environment I don't know how to set this up, however.
I looked around for answers online, but feel lost among all the different terms I have come across (.env, crossenv, nginx, cors) and that I am running in circles.
What would be a good way of setting this up?
Thank you
Edit:
I ended up creating three modes to run my application:
Development
I use one script in a package.json to start the frontend and backend server on different ports, using pm2 to run the servers in the 'background' rather than blocking further commands in the terminal/cmd. I use configured a proxy inside my vue.config.js to redirect my API calls made in the frontend to the right base URL and used cors as middleware to allow requests to my API from other domains/ports.
Staging
I use one script in a package.json to build the Vue app into a folder ('dist' folder inside my backend folder) that is a collection of static files and start the backend server. My backend is set up to know when I want to go into staging mode and then serve the static files in the 'dist' folder.
Production
I use one script in a package.json to build the Vue app into a folder ('dist' folder inside my backend folder) that is a collection of static files and push my backend (incl. the built static files) to Heroku.
Well if you need to run both on the same port you could first build your app so that you receive a dist directory or whatever your output directory is named and set up an express server that serves that app and otherwise handles your api requests
const express = require("express");
const path = __dirname + '/app/views/';
const app = express();
app.use(express.static(path));
app.get('/', function (req,res) {
res.sendFile(path + "index.html");
});
app.get('/api', function (req,res) {
// your api handler
}
app.listen(8080)
Assuming that node and the 'app' will always run on the same server you can just use a template library like ejs.
You would then just bundle the app and api together, assuming that the front-end is tied to the backend, realistically you would not even need to hit the API as you could just return the records as part of the view, however if dynamic elements are needed you could still hit the API.
Now, with that said, if the API is something used by many applications then it would probably make sense to build that out as its own microservice, running on its own server and your frontend would be on its own. This way you have separation of concerns with the API and Vue app.

How to serve static files in AppEngine Standard and nodejs

The documentation says that you simply must update your app.yaml - like you would for any language within AppEngine. It also states later on that for local development, you probably want your server to respond to static requests as well. However, when I update my very simple app.yaml to be as such:
runtime: nodejs8
handlers:
- url: /apiEndPoint
script: auto
- url: /.*
static_dir: public
It seems all requests still end up coming in to my script - which will return a 404 in the prod instance, since those files won't be uploaded. I can force them to be uploaded, and then my nodejs server responds to the static requests - but I thought the idea of this app.yaml was to configure it so static files are served outside of my app logic?
So to be clear - you can host static files in production Nodejs Standard AppEngine without needing to use a JS server. However, for local development, you must find a way to serve those files locally when running on your machine. For this reason, you put the handler in Express, for static files, which should never be touched in production - since the app.yaml handler is the first-pass.
If you want to be positive Express.js is not serving up static files in production, you can do so by doing something like this:
// Production instances automatically have this environment variable.
const isLocal = (process.env.NODE_ENV !== "production");
if(isLocal) {
app.use(express.static('public'));
}
The static files are uploaded during deployment, but not in the same place as the app's code. They're uploaded in Google's infra dedicated for directly serving static content. This could be confirmed by increasing the log verbosity of the deployment command.
When a request URL matches one of the static handlers it should be directed to this dedicated infra, it shouldn't reach your app code. It should be relatively easy to confirm with an actual deployment.
As for the local development, I'm not exactly sure how the Node.Js server behaves (indeed, the docs appear to suggest Express may be needed to handle static files), but the Python one serves itself the static files based solely on the app.yaml static handler configs, without hitting any of the app code. Could be because of the still very new Node.JS standard environment support.
The static files that you want to serve need to be deployed along your application code with gcloud app deploy.
Your app.yaml file says:
Any request that matches /apiEndPoint will be routed to your Node.js app
Any other request URL will serve a static file from your public folder and not arrive to your application (once deployed).
For example: /index.html will serve public/index.html if this file has not been deployed, then it will return a 404 page.

Can't reach backend when url base is set

I have an application built using Express, Mongoose, React and Node. My application is hosted on a location which looks like the following: https://example.com/app_name which means that app_name is the base path for all of the static assets.
I'm using Webpack and setting publicPath to https://example.com/app_name. I can reach my static assets just fine, but when I attempt to do a call to my back-end, my requests are being routed to https://example.com/api/... instead of https://example.com/app_name/api/....
Is there a way to prefix my endpoint calls so that they use https://example.com/app_name/api/... instead of https://example.com/api/...through webpack or any other means?

How to enable static files (and less support) when hosting a nodejs app within IIS using IISNode

Background:
Nodejs app using expressjs.
Hosted on IIS using IISNode
Nodejs app is in virtual directory called /myVirtualDirectory
Problem:
You want to provide static files or css using less but the url that is passed to nodejs is the full url and doesn't match what would be expected with a standalone nodejs app.
Solution:
var express = require('express');
var app = express();
var lessMiddleware = require('less-middleware');
app.use('/myVirtualDirectory', lessMiddleware({
src: __dirname + '/public',
compress: true
}));
app.use('/myVirtualDirectory', express.static(__dirname + '/public'));
Note where we have specified the middleware to use we have passed in the url prefix for it to respond to. As long as this is the same as the name of the virtual directory this will match and your files will be served up as expected.
One of the benefits of hosting node.js apps in IIS using iisnode is that you can rely on the static file handler in IIS to serve your static files. The benefit is a substantial improvement in performance, since requests for static content are served by native code without ever invoking JavaScript.
To set up a node.js application hosted in IIS using iisnode to serve static files using IIS static file handler, use the URL rewriting module as described in http://tomasz.janczuk.org/2012/05/yaml-configuration-support-in-iisnode.html
To understand the performance benefits of using static file handler instead of node.js modules to serve static files, read http://tomasz.janczuk.org/2012/06/performance-of-hosting-nodejs.html.

Resources