How to properly configure Browsersync to proxy backend - node.js

I'm struggling with proper configuration of Browsercync (and maybe some middleware?).
My configuration is like:
local.example.com it's mine local address configured via /etc/hosts.
devel.example.com it's our company devel environment (backend).
staging.example.com it's our company staging environment (backend).
As I'm UI developer I want to use my local code, but work with one of backend environments.
I'm using gulp to build my project etc. It's also has task to run browser-sync and watch file changes. But of course there is now problem with cookies domains that are coming from backend. CSRF token cookie domain is set by browser to currently used backend.
I have tried:
To use middleware http-proxy-middleware with configuration:
server: {
baseDir: './build',
middleware: [
proxyMiddleware('/api', {
target: 'http://devel.example.com',
changeOrigin: true,
})
]
]
But problem I have is that it's doing non-transparent redirects, which are visible in browser console. I thought that it will work like this, that proxy will mask those requests to browser will think that all requests and responses are coming from local.example.com. But it seems that it doesn't work like this (or maybe I configured it badly).
Also big problem with this solution is that it somehow changes my POST HTTP requests to GET (WTF?!).
To use build in browser-sync proxy option. In many tutorials I saw using proxy option with server option, but it seems not work anymore. So I have tried to use it with serveStatic like this:
serveStatic: ['./build'],
proxy: {
target: 'devel.example.com',
cookies: {
stripDomain: false
}
}
But this doesn't work at all...
I would really appriciate for any help in this topic.
Thanks

Related

node Vue.js different code scenario if run in dev mode

I have Vue.JS front app with nodeJS backend based on expressJS. ExpressJS also used as web server for statically built Vue.JS app
Front app communicates with express backend via rest and websocket. It uses url host from window.location instance and easily communicates with backend
In production mode, when built application in static expressJS server area, everything work perfect
In dev mode, Vue use it's own web server, and backend urls based on window.location are incorrect because no expresJS on same host and port.
So my question is it possible change some code blocks if running in dev mode ?
Like something this :
if( devmode)
{
const url = "http://somebackendhost/rest"
}
else {
const url = location.host ....
}
}
I will assume you are developing your Vue app using Vue CLI
Changing app behavior depending on environment
In Vue CLI you can use Environment Variables
if(process.env.NODE_ENV === "development")
{
}
This works thanks to Webpack's Define plugin and big advantage is that process.env.NODE_ENV is replaced at build time by the real value. So in production build Webpack will see just if("production" === "development") {} and happily removes the code in optimization phase because it knows this can never be true
Better solution
But I would not use this approach for your problem. Using different API server (not same as the server used for serving Vue SPA) can easily lead to CORS problems
Exactly for this use case, Vue CLI (and Webpack Dev server used under the hood) supports proxying
vue.config.js
module.exports = {
devServer: {
proxy: {
'^/api': {
target: 'http://localhost:58300/',
ws: true, // websockets
changeOrigin: true,
}
}
},
},
This config makes Vue Dev server to proxy any request to /api to other server running at http://localhost:58300/ (your node/express app) and change the origin (so browser thinks response came from the dev server)
All of this can be done without Vue CLI but you will need to set it up by yourself in Webpack config...
The problem
You can't access this information from your browser.
But there are three solutions:
Solution #1
On compilation time create a variable in code which defines devmode (const devmode = true;)
Solution #2
Because your bundler can minify your variable names or changing the scope for security reasons, may be the situation where you can't access it.
So second solution is to define devmode in your localStorage.
Solution #3
Third solution is almost the best.
If you are developing, you are probably accessing your web app via localhost.
location.hostname will return the name of host, so you can make something like:
const devmode = location.hotname == 'localhost';
Best solution
Do not do this. Develop a fully working web app using local REST API and define the URL of REST API in some variable, so when you are preparing your production app, you or compiler just changes the URL adress variable in code of your REST API.
Why is this the best solution?
Because it do not impacts your end-user's performance and they will be loading less code, which is the best practise.
Post Scriptum
Don't forget to remove all devmode codepaths when compiling production version!

npm start - developing React app - any way to set 'base href' or forward traffic to my back-end?

I am modifying existing React application which uses the relative URLs e.g.: /server/fetchRouteInfo.
The react app runs in context of a hostname e.g.: local.website.com, so it all works nicely as URLs get resolved to: local.website.com/server/...
I've found the npm start convenient to use to develop this React application. The problem is because of npm, my front-end app gets hosted under: localhost:3000, so the relative URLs no longer resolve to correct back-end and external resources.
What's the best way to connect my front-end app to desired back-end?
I've tried to use HTML <base href="local.website.com"> but it breaks the npm internal calls e.g. to static.js.
I know that I could modify the relative URLs to full absolute, but that's not the way I want to go.
Perhaps there is a way to forward / proxy-pass any traffic that goes to npm to my endpoint? In other words if there is request like: localhost:3000/server/... it would get internally proxied to: local.website.com/server/....
What's the common way to solve my problem, namely how to connect front-end to external back-end given the front-end uses relative URLs.
You can set the proxy in package.json. Just add one more parameter proxy with the desired value.
For more information, please refer to Proxying in Development
On React page there is proxy section: https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually
Looking up the component Github: https://github.com/chimurai/http-proxy-middleware
There is a way to provide custom filter.
Instructions:
Install component: npm install --save-dev http-proxy-middleware
Create file: src/setupProxy.js with this config
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
var filter = function(pathname) {
if (pathname.match('^/static')) {
return false;
}
return !pathname.match('^/$');
};
app.use(
proxy(filter,{
target: 'https://local.backend',
changeOrigin: true
})
);
};
npm start
This will redirect all traffic, except the: / (this is where my React app is served) and starting with /static (some NPM JavaScript).
I am not sure if it's the easiest way or not. I would've been easier if there is dedicated namespace e.g.: /api that you could use.
There was a caveat though. If you first need to login to your back-end which sets session cookies, those cookies won't persist if you use: localhost:3000 path (the localhost is not valid domain for cookies to be set).
My workaround was to add the entry in: /etc/hosts and create bogus domain.
127.0.0.1 local.host then use: local.host:3000 endpoint.
Another issue you might encounter if the session cookie is: Secure, that means that it won't be set for unencrypted protocols. Simply start the npm with https support: HTTPS=true npm start and contact using: https://local.host:3000 endpoint.

Proxy running node-react application

I just created a react-node-SQL app and I want it to run on Google Cloud (not firebase)
My React app runs on different port and my node app runs on different port.
I followed this article and added this line in my react-app package.json but I didn't worked out i.e href in button was still going to localhost:8081 but It didn't worked
I had my node running on port 8080, In package.json of my react app i added "proxy": "http://localhost:8080/" and in button when I did href="/api/status" it was going to localhost:8081 on which the react app was running
Now, Is it possible to run both node and react under the same project? or we need to create separate project for them.
[Update:] I am using webpack, In my webpack config file, I added this
devServer: {
proxy: {
'/': 'http://localhost:8080'
}
},
The problem with this, that even in my react app, on Startup (running on 8081) when it opens the webpage localhost:8081/ it throws an error saying cannot get the page
but if I do something like this
devServer: {
proxy: {
'/api': 'http://localhost:8080'
}
},
it opens the page homepage normally. Now my api and callback uRL after authentication aren't configured with have prefix as api.
Basically, when you do an ajax request from react app, like axios or fetch it will use the proxy: <..> for the backend url. But, href doesn't work with proxies. In that case you need to manually configure proxy using the setupProxy.js documented in the manual proxy page.
Check out this issue:
Same error here, it still routes to localhost:3000/api/auth/google, my
CRA version is 2.1.3 It seems http-proxy-middleware is the only
working way. I have to Configuring the Proxy Manually
From the react doc:
If the proxy option is not flexible enough for you, you can get direct
access to the Express app instance and hook up your own proxy
middleware.
You can use this feature in conjunction with the proxy property in
package.json, but it is recommended you consolidate all of your logic
into src/setupProxy.js.

When to use proxy and when to use CORS in a react project?

I am a beginner at react development, I am confused about when I should use proxy or cors to make the front end talk to the back end.. Or do i need to use both? like proxy for development and cors for production?
CORS is completely related to back end when you want make your back end server accessible for any request use CORS.
example:
const app=require('express');
const cors=require('cors');
app.use(cors())// server will respond to any domain
Most of the time you are going to use a proxy when you want to be able to connect to an api that the webpack dev server isn't hosting but will be hosted by your server when published. An example will probably clear this up better than anything.
When developing you have the following scenario
API Server - running at localhost:4567 Webpack Dev Server - running at localhost:8080
Your App.js will make a request to the API server like so
$.ajax({
url: '/api/getOwnedGames',
...
});
Without a proxy this will actually make a request to localhost:8080/api/getOwnedGames (since you are browsing from the webpack dev server). If you however setup the proxy like so...
proxy: {
'/api/*': {
target: 'http://localhost:4567'
}
}
the api request will get rewritten to be http://localhost:4567/api/getOwnedGames.
if you aren't hosting your own api you probably don't need the proxy.

How to use CAS authentication with angular2 webpack starter typescript?

I am using the following:
https://github.com/gdi2290/angular-starter
I start the application with npm start that uses webpack dev server. My issue is I want to add CAS authentication, but have no idea where what goes. This is the library I am trying to use:
https://github.com/TencentWSRD/connect-cas2
All the examples appear to use express, though I am not sure if I can use this with the webpack-dev-server as is with the starter I am using? If so, how do I use it? Or do I need a different CAS library that is compatible with the npm start?
Webpack is more of a build tool with minimal server capability. It can serve static content making it perfect for updating content on the fly and put together simple websites with basic routing and client side side logic.
If you want anything even a little more complex you will need a server side technology. So the connect-cas2 will require you to use node.js and express. The documentation shows you exactly how to set it up.
I don't know anything about connect-cas2 but I know passport for authentication, but they wouldn't be terribly different. I would follow the quick start and if you have any issues then edit your question with the code that you are having issues with or have trouble understanding.
I have been digging around and you might be able to proxy the authentication if you already have a CAS server setup somewhere. I would try the following:
// the proxy option is part of the devServer in your webpack.config.js
devServer: {
contentBase: 'public',
// setup a proxy
proxy: {
// just replace the /cas/validate endpoint to the endpoint in your
// website that will trigger the api call
'/cas/validate': 'https://url-to-your-cas-server.com'
}
},

Resources