http-proxy-middleware adds a '/' before query parameters - express

I want to consume an API using a proxy written in express. I use http-proxy-middleware for this. Here is the setup I have:
app.use(
createProxyMiddleware('/api', {
target: 'http://example.com/api/v2',
changeOrigin: true,
pathRewrite: {
'/api': '',
}
})
);
Then I make a request from postman or browser: GET http://localhost:8080/api/list?first=50
All I get from the API server is 404. I saw in the browser that the URL changes to http://localhost:8080/api/v2/list/?first=50 and I don't understand why.
All I want is to add an auth header which I managed to do using onProxyReq, but now I just want everything that comes after /api to be forwarded as is to http://example.com/api/v2.

I just got it to work. Turns out I had some things wrong. The first wrong thing target: 'http://example.com/api/v2' should be target: 'http://example.com'. Then, pathRewrite will rewrite anything it matches and redirect to the new path, so it ended up calling localhost:8080/api/list?first=50 and then localhost:8080/api/v2/list/?first=50. So with these 2 mistakes combined, in the end the API call would be example.com/api/v2/v2/list/?first=50 and that's clearly wrong. I replaced the target and I am now using /api/v2 as context for the proxy.
I would still like to call my proxy using localhost:8080/api/whatever and have it turned into example.com/api/v2/whatever, but it's just a nice to have.

Related

How do I serve an express + vue app on same domain in Heroku

I have a backend api in express and a front end in vue.js with typescript.
In my development environment, the front end talks to the backend via a proxy server defined in the vue.config.js file...
module.exports = {
devServer: {
proxy: {
"^/api": {
target: 'http://localhost:3002',
changeOrigin: true,
pathRewrite: {"^/api": "/"}
},
}
}
}
So, my front end expects to be served on [address] and it is expecting the express application to be at [address]/api on the SAME address/url.
I was able to achieve this on Digital Ocean App Platform by setting up 2 'components', a backend served from '/api' and a front end component with the Vue.js stuff in it served from '/' on the same domain.
How can I achieve this in Heroku?
I have seen a lot of people (e.g. https://www.youtube.com/watch?v=W-b9KGwVECs) suggest using a build step that builds the front end, copies the static assets back up into a 'public' folder and then uses express to serve the static assets as well as the rest api using this...
app.use(express.static(__dirname + '/public/'));
But is this really the best way to do it? Seems to me like now Express is responsible for the front end and the backend when they should be seperate concerns. Also, what about scaling the back vs the front?, does this work for CDNs?
This seems like such a common use case for something like Heroku, maybe I am just missing something obvious.

NextJS API route conflict

I have been transitioning to NextJS from CRA. I'm re-implementing authentication using SSR, and I would like to use NextJS built-in API routes to set HTTPOnly cookies.
There is a weird problem where my backend base URL is https://somesite.com/api and my frontend's - https://somesite.com/. This means that NextJS built-in API routes will be in conflict with my own backend.
I have been researching online and couldn't find any way on changing routing in NextJS, and I don't want to change base URL of my backend, since there are other services depending on it.
Has anyone had the same issue? How can I resolve this issue?
Try next.js rewrite
Rewrites allow you to map an incoming request path to a different destination path. Docs
Check Live Example here: https://stackblitz.com/edit/nextjs-rewrite
If Path is /api it'll point to JSON placeholder APIs.(ex. /api/todos)
module.exports = {
async rewrites() {
return [
{
source: '/api/:slug*',
destination: 'https://jsonplaceholder.typicode.com/:slug*'
}
];
}
};

Heroku adding 'undefined' to BASE_URL environment variable

attempting to deploy a vuejs, express app to heroku. The app displays, but cannot access the api, because heroku seems to add 'undefined' in the middle of the base_url. Everything works locally as expected.
Here is my heroku config var:
BASE_URL: https://goore-todos.herokuapp.com/
Here is the Vuejs component api request:
fetchTodo () {
let uri = process.env.BASE_URL + '/api/all';
axios.get(uri).then((response) => {
this.todos = response.data;
});
},
As mentioned, this works locally.
the console shows the following error:
VM71:1 GET https://goore-todos.herokuapp.com/undefined/api/all 404 (Not Found)
and the view is empty.
requests to https://goore-todos.herokuapp.com/api/ via Postman work as expected.
In this case it looks like process.env.BASE_URL is undefined. As it is undefined, the url you're trying to access is considered to be relative. That means it uses your current domain and appends the path to it.
If your frontend and backend are running on the same domain there is no reason to try to pass the API url as a variable as you can just use relative URLs.
If you want to access the URL via an environment variable it is a bit trickier with a frontend app. The Vue app is running on the user's browser, not on your server so you can't directly access it.
I had this problem and had to go through and hard code all of my URLs with the heroku URL. I tried resetting the config variables in Heroku which had an extra slash at the end, but in the end hard-coding each API call was the only thing that fixed it.

vue cli3 enable CORS

I have had this problem for nearly 2 days, any help would be a life saver.
I have my vue app running on 8080 dev mode and I am trying to integrate blockstack login and that app tries to read http://localhost/manifest.json, so I placed it in static directory, but it is throwing me cors error, do we have solution for that vue cli configurations like vue.config.js?
The "correct answer" doesn't actually help in this instance.
Blockstack needs to be able to hit the manifest.json file (in this case localhost:8080/manifest.json). When the server doesn't support CORS Blockstack will throw an error.
What the OP is asking is how to make "vue-cli-service serve" allow COR requests to happen. To do this, we need to modify Webpack's dev server to allow the CORS request.
Add vue.config.js (if it doesn't already exist)
module.exports = {
configureWebpack: {
devServer: {
headers: { "Access-Control-Allow-Origin": "*" }
}
}
};
I had the same problem like you are having. I applied what the documentation of vue-js says to put some code in vue.config.js like this
module.exports = {
devServer: {
proxy: 'http://localhost:4000'
}
}
but that would'nt help. See this documentation https://cli.vuejs.org/config/#devserver .
I have separate backend which is in laravel,What i did after having wasting too much time in allowing cors in vue-js, i applied cors on my backend index.php file and that worked like a charm.
The problem is you don't really know where is it coming from but look at both front end and backend side and then try to find solution on both sides.

How to do routing/navigation in Elm without the # (hash) in the URL?

Using the UrlParser.parseHash function i was able to successfully parse the following url:
http://localhost:8000/MyRepl.elm/#home/something-else
The behavior is as expected, when i copy paste this in the browser and hit enter - the app loads with the appropriate view.
But now i want to remove the # and for this i used UrlParser.parsePath function. I kept the rest of the code exactly as before - but for some reason this doesn't work.
When i copy paste this and hit enter:
http://localhost:8000/MyRepl.elm/home/something-else - notice no #.
The browser creates a direct request to the elm -reactor localhost server.
There is no routing happening. The elm reactor server returns a 404 - as if there is no file named /MyRepl.elm/home/something-else
But routing without # should be possible because the http://package.elm-lang.org/packages - Docs site is written in elm and there is no # in the url as you can see.
Questions:
Anyone has experienced the same problem? Any ideas how to fix this?
Or can you point me to a repo where navigation without # works as expected?
You need a backend that servers your index page for every request. After serving the index page the routing will happen as usual in Elm.
For example in express it would look something like:
router.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
router.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
Elm reactor doesn't support this.
If you are using webpack you can do the same with the historyApiFallback attribute How to tell webpack dev server to serve index.html for any route