Comments (10)
I'm going to work on this along with some other PRs and issues. It might make it into the next release.. not 100% on it yet though. I think it will rely mostly on implementing the picking up of a servor config file so that we don't have to keep adding cli flags.
from servor.
Thanks @thisguychris that does make things easier to comprehend. So essentially you want to reserve a specific route to make a request to another specified server with the same round sans the /api
? Something like:
if (url.match(config.proxy.path)) {
fetch(config.proxy.destination + url.replace(config.proxy.path, ''))
.then(json => res.json())
.then(json => res.send(json))
}
But probably as a raw stream rather than parsed json or whatever?
from servor.
Hey all 👋 servor does not currently support this behaviour. It is really meant to be a local replica of a static CDN like server (albeit with a few handy development features). I have never used servor in production rather I push my sites/apps I develop with it to something like Netlify or GitHub Pages.
That said, servor does have a node API which you could use to combine it with another server such as express for example. That kind of defeats the purpose though I guess.
Have you got an example of how the API might look like if we were to include such functionality in servor, how would you want to configure it etc?
from servor.
Hi. I have a similar use case. I already have a fairly simple Express instance that both serves html/js/css files and API requests. What I'd like to do is if env === dev, then serve static files and fallback through servor.
from servor.
Thanks for the fast response! I'll see if I can make a prototype and see what I really want to do. I guess for me, the functionality I'm looking for is live reload. This is probably not a universal problem, but my setup is basically mixing node.js urls with a html5 app. Sorry to subhero24 for derailing his topic maybe - in my case I am OK with serving Vue and API from the same server, although obviously ideally there would be different microservices for those.
My router is currently like
const {join} = require("path");
module.exports = function (express, router, debugController) {
return function (app, rootPath) {
debugController.setRouting(router);
router.get('/', function (req, res) {
return res.sendFile(`${rootPath}/site/index.html`);
});
router.get('/static/:page', function (req, res) {
return res.sendFile(`${rootPath}/site/${req.params.page}.html`);
});
for (const route of getVueRoutes()) {
// console.log(`-------------VUE- ${route} ---------`);
router.get(route, function (req, res) {
return res.sendFile(`${rootPath}/site/index.html`);
});
}
app.use(router);
app.use(express.static(join(rootPath, "site")));
}
};
function getVueRoutes() {
const requireModule = require("esm")(module);
const routes = requireModule('../site/routes.esm.js');
// console.dir(routes.default.routes);
return routes.default.routes.map(vueRouteObject => vueRouteObject.path).filter(foo => foo !== '*');
}
Here express
is a configured express instance, router
is an express-promise-router
and debugController
is just a controller, where setRoutes
adds a few API URLs. For root, and for Vue routes I serve the main vue app, index.html (ideally here would be some clever isomorphic functionality, but whatever).
Then I can serve some plain-html static files, and everything else (css, js, assets) I serve from the 'site' folder (invisible to browsers).
This is pretty clunky, but it does what I need. Mostly I want to see how far I can go with buildless Vue while compensating for some of the lost benefits of a build process. If I manage to make a usable snippet, I'll share it here today, or during the weekend.
from servor.
OK, that wasn't actually that hard. Not sure if this helps anyone, but... shrug :D I tried.
Of course for this to be sharable, it would need wrapping to a neat configurable module, basically passing along the router object, base path, index file path, etc.
To actually comment to the original question by @subhero24 :
- if you want to serve Vue + API from one Node process, you can use something like the first following code snippet
- if you want to proxy things from Servor, I guess the fastes would be to fork it and add something like the second code snippet (this one would work in Express, probably needs adjustments for plain http server)
Please note that fs
in this case is really bluebird.promisifyAll(require('fs'))
.
const {join} = require('path');
const fs = require('../container.js').get('fs');
const clients = [];
module.exports = function (express, router, debugController) {
return function (app, rootPath) {
debugController.setRouting(router);
router.get('/', serveIndex(rootPath));
router.get('/static/:page', function (req, res) {
return res.sendFile(`${rootPath}/site/${req.params.page}.html`);
});
router.get('/livereload', liveReloadController);
for (const route of getVueRoutes()) {
// console.log(`-------------VUE- ${route} ---------`);
router.get(route, serveIndex(rootPath));
}
app.use(router);
app.use(express.static(join(rootPath, 'site')));
if (process.env.ENV === 'dev' || process.env.NODE_ENV === 'development') {
console.log('Starting up file watcher for Servor.');
watchChanges(join(rootPath, 'site'));
}
}
};
function getVueRoutes() {
const requireModule = require('esm')(module);
const routes = requireModule('../site/routes.esm.js');
// console.dir(routes.default.routes);
return routes.default.routes.map(vueRouteObject => vueRouteObject.path).filter(foo => foo !== '*');
}
// servor stuff from here on:
const liveReloadScript = `<head>
<script>
const source = new EventSource('/livereload');
source.onmessage = e => location.reload(true);
console.log('[servor-express] listening for file changes');
</script>
`;
function serveIndex(rootPath) {
if (process.env.ENV === 'dev' || process.env.NODE_ENV === 'development') {
return async function (req, res) {
let content = await fs.readFileAsync(`${rootPath}/site/index.html`, 'utf8');
content = content.replace('<head>', liveReloadScript);
return res.send(content).end();
}
}
return function (req, res) {
return res.sendFile(`${rootPath}/site/index.html`);
}
}
function sendMessage (res, channel, data) {
res.write(`event: ${channel}\nid: 0\ndata: ${data}\n`);
res.write('\n\n');
}
function watchChanges(path) {
fs.watch(path, {recursive: true}, () => {
while (clients.length > 0) {
sendMessage(clients.pop(), 'message', 'reload');
}
});
}
function liveReloadController(req, res) {
res.writeHead(200, {
Connection: 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*'
});
sendMessage(res, 'connected', 'ready');
setInterval(sendMessage, 60000, res, 'ping', 'waiting');
clients.push(res);
}
how 2 proxy:
// rp = requst-promise
async function proxy(req, res) {
try {
const resp = await rp({
url: `http://127.0.0.1:80${req.path}`,
method: req.method,
resolveWithFullResponse: true,
headers: req.headers,
simple: false
});
return res
.append('content-type', resp.headers['content-type'] || 'application/json; charset=utf-8')
.send(resp.body)
.status(resp.statusCode)
.end();
}
catch (err) {
console.error(err);
return res
.send(err && err.body || 'Server error')
.status(err && err.statusCode || 500)
.end();
}
}
from servor.
Hi @lukejacksonn 👋🏻
I'm just dropping here to support this issue and add a use case. Ideally, you should just drop files in a CDN. In a microservice world, it's better to have a relative URL, as opposed to using it externally, because you skip the whole tango dance with CORs. And let's be honest, CORs is just a pain to configure 🤣.
We've been using this approach for years now, and hooking sites to Cloudflare, makes websites housed in Nginx served in a CDN fashion.
Ideally, the API would look like this, if we're using a config. If we are to use the cli, I propose we use -P
like what http-server
does.
{
"proxy": [
{ "path": "api/**", "destination": "https://xxx.api/" }
]
}
With the rise of browsers blocking third-party scripts by default. I think this approach would be more popular.
And I think this is going to be a norm, Netlify, Firebase, Zeit, Cloudflare all have a convenient way to proxy a relative API to a microservice/external URL. And they're all housed by a CDN.
from servor.
@lukejacksonn yes! something like that 😊
from servor.
@lukejacksonn that would be perfect!
from servor.
@lukejacksonn +1 for this
from servor.
Related Issues (20)
- setuid breaks local secure serving on linux HOT 5
- --reload causes browsers to enter quirks mode HOT 3
- Option for disable the injection of base tag HOT 4
- Media streaming issues with Chrome HOT 6
- Starting two instances of Servor without port cause them having the same port HOT 2
- `sudo servor --secure` throws `EACCES: permission denied` HOT 3
- Add flow support HOT 2
- Wait for write to finish HOT 3
- Support https for LAN IP HOT 1
- Trailing slash on SPA route HOT 2
- servor crashes on st terminal in Ubuntu HOT 5
- Please support etag and last-modified
- Vertical scroll position resets when servor triggers reloading in Firefox
- [Feature Request] Inject livereload to each html file
- [Feature Request] Allow multiple roots
- Listen on localhost only HOT 1
- crt and key file location for secure start HOT 2
- Support already encoded files (gz, br) HOT 1
- Exception handling in the `decodeURI` function is required.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from servor.