Webpack dev server proxy router option doesn't work - webpack-dev-server

I'm setting up an application using the Vue CLI. I've come to configuring the proxy of the webpack-dev-server to proxy requests to a certain endpoint. Which endpoint to proxy to differs based on certain request parameters.
According to the http-proxy documentation, I should be able to do this using the router option (instead of the target property, but the target property is required by webpack-dev-server). Here's a minimal version of my proxy configuration:
{
devServer: {
port: 8080,
host: 'localhost',
proxy: {
'/api': {
target: 'http://localhost:8000',
router: function (req) {
console.log('Proxy router', req.hostname);
return 'http://localhost:7000';
},
},
},
}
}
What I'd expect to happen here is that any requests made to http://localhost:8080/api would be proxied to http://localhost:7000. What actually happens is that it tries to proxy the requests to the endpoint configured in the target option.
To illustrate this, this is the console output:
Proxy router localhost
Proxy error: Could not proxy request /api/test from localhost:8080 to http://localhost:8000/.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
It executes the router function (as seen by the console log output above), but it seems to just ignore the result and proxy to the target endpoint anyway. According to the http-proxy docs, the target option isn't required when using the router option, so I would have removed it if I could, but webpack-dev-server itself requires the target option to be set and be a valid URI.
How can I get the proxy to use the router function in webpack-dev-server?

This appears to be a problem with the underlying http-proxy-middleware. Although that configuration does successfully proxy the request to /api to http://localhost:7000, if the proxied request fails the original target is logged:
const target = (this.proxyOptions.target as any).host || this.proxyOptions.target;
const errorMessage =
'[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)';
Source
If you turn up the log level, you can see that it is using the desired target:
'/api': {
target: 'http://localhost:8000',
router: function () {
return 'http://localhost:7000';
},
logLevel: 'debug',
},
[HPM] Router new target: http://localhost:8000 -> "http://localhost:7000"
[HPM] GET /api => http://localhost:7000
[HPM] Error occurred while trying to proxy request /api from localhost:8080 to http://localhost:8000 (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)
It looks like this was fixed in v1.1.2.

Related

My react app and express server are on different ports

Problem/error:
I am running my react app on port 3000 and express on 3001.
error: Access to fetch at 'http://localhost:3001/api' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
//react code
//this function gets called when a button get pressed
...
post = () => {
const client_data = {info: this.state.input};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json
},
body: JSON.stringify(client_data)
}
fetch("http://localhost:3001/api", options);
}
...
Server is pretty simple
var express = require('express');
var app = express();
app.post('api', (request, response)=>{console.log(request})
(when I add "app.listen(3000)" react stops working)
You have to proxy your requests from react to express. The best way is to let it do your WebPack devServer, having this configuration:
(I assume, your express server is on 3000 and your React app on 3001)
devServer: {
...
...
proxy: {
'/api': {
target: 'http://127.0.0.1:3000/',
},
},
This says, that whichever request to path /api will be redirected to port 3001. Then you fetch to
fetch("/api", options);
Client automatically requests localhost:3001 (port on which the application is running), but the proxy redirects to 3000.
Brief explanation:
When developing react app, react creates a live developing enviroment that runs on -p 3000. However, if I spin up a node backend on -p 3000, the ports collide and the live enviroment crashes.
Solution:
Spin the node backend on a different port (4000)
and make a proxy in the live app
SERVER:
app.listen(4000, () => console.log("server is up on -p 4000")
CLIENT:
In the react app package.json file insert this key/value:
{
...
"proxy": "http://localhost:4000",
...
}

ECONNREFUSED - Proxying API requests from React

I am developing a MERN stack app. I am using the http-proxy-middleware package for proxying API requests. At the client side, inside "src" folder, I have a file called setupProxy.js. And the code inside is as follows:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
"/api/products",
createProxyMiddleware({
target: "http://localhost:8000",
})
);
};
As you can see, I am making a request to "/api/products".
But I am receiving error in the console. The error says:
[HPM] Error occurred while trying to proxy request /api/products from
localhost:3000 to http://localhost:8000 (ECONNREFUSED)
(https://nodejs.org/api/errors.html#errors_common_system_errors)
Also, the request is being made to "http://localhost:3000/api/products".
How can I solve this issue?

React app with Rocket backend giving ECONNREFUSED when using proxy

I'm trying to make a web app using rocket for the backend and react for the frontend. However, when I try to make a proxy I keep getting rayk#pop-os:~/repos/homrs/frontend$ curl http://localhost:3000/api Proxy error: Could not proxy request /api from localhost:3000 to http://localhost:8000 (ECONNREFUSED).
The things I've currently tried are adding "proxy": "http://localhost:8000" to my package.json in the application and I've always tried configuring the proxy manually as suggested here https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually.
Here is the backend code I'm using to test:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().mount("/api", routes![index]).launch();
}
Here is the setupProxy.js I attempted to use
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8000',
changeOrigin: true,
})
);
};
I also have attempted to use http://localhost:8000 and http://localhost:8000/. I have also tried changing the rocket port from 8000 to 3001 and that also did not work.
Edit: Here is a link to the github repo: https://github.com/GimpFlamingo/homrs
The people here: https://github.com/plouc/mozaik/issues/118 were having a similar issue.
I was able to reproduce your issue and found adding address = "127.0.0.1" to Rocket.toml and then setting "proxy" to "http://127.0.0.1:8080" fixed it for me!

Webpack react app proxying to express server. Returning the json response from the express server rather than react components

I have a react web app that uses express as the back end.
I have it set up so that it proxies the request urls on the react server port (9000), to the express server (3000). Problem is, when I type in the path /examplepath, it returns the json that the express app returns, rather than returning the component that renders from getting that response from the backend. I am getting the express response and looking at it rather than react getting the express response and looking at it and then rendering and showing me that render.
When I click this button, it renders the correct page because it uses this code
componentDidMount() {
axios.post('/', qs.stringify(this.state))
.then(res => {
if (res.data === "session") {
this.setState({session: true})
}
})
}
It will render the page correctly using react
But if I visit the route directly it renders the json response from the express backend.
Like this
When I want it to render like the correcly rendered one using react
devServer: {
port: 9000,
open: true,
proxy: {
'/': 'http://localhost:3000'
}
}
THIS ^ is my webpack.config.js
Try adding historyApiFallback: true to your webpack.config.js file (not sure if the proxy will mess with it -- if so, use express cors middleware on the backend instead):
devServer: {
host: 'localhost',
port: 9000,
quiet: true,
historyApiFallback: true,
},
Also, a more common port setup is: React app on 3000 and API/server on 5000.
In addition, make sure you clearly separate your front and back end routes. Try keeping your back end routes to /api/someurl, and adding that to your proxy (and AJAX requests):
proxy: {
'/api/*': 'http://localhost:3000/api/'
}
Then, all front-end requests will be:
axios.get('/api/someurl').then().catch()
which will resolve to http://localhost:3000/api/someurl. This way, there's no chance of blending the front and back end routes.
Personally, I'd recommend cors over a proxy, because the proxy has been known to cause random connection issues.

java.io.IOException: Failed to retrieve API configs with status: 404 when called from webserver

So I have an appengine webapp which includes cloud endpoints deployed locally on port 8888.
The error message in the title occurs on startup of our webpack-dev-server which runs on port 3000 and proxies all requests starting with /_ah/api/* to http://localhost:8888. The exact console error is as follows:
The odd thing is, when I open this url in another tab and switch the port to 8888 the request comes through, and the webpack-dev-server can also proxy the requests to the backend from then on.
Most other issues I read on this suggested setting the appengine config in gradle to the following:
httpPort = 8888
httpAddress = "0.0.0.0";
However I already did that so that does not seem to be the issue.
My relevant webpack config is as follows:
module.exports = webpackMerge(commonConfig, {
...
output: {
...
publicPath: 'http://localhost:3000/'
},
devServer: {
port: 3000,
open: true,
proxy: {
'/_ah/api/*': 'http://localhost:8888/'
}
}
});
Some backends don't work properly without changeOrigin: true. You can use it like this:
proxy: {
'/_ah/api/*': {
target: 'http://localhost:8888/',
changeOrigin: true,
secure: false
}
}
If that doesn't work, does the proxy path (/_ah/api/) need to be included in the request? You could try if ignoring the path works:
proxy: {
'/_ah/api/*': {
target: 'http://localhost:8888/',
ignorePath: true
}
}
And if that doesn't work, I would try out removing the last part of the proxy path: /_ah/api/* to /_ah/api. This should do the same, but the first one is deprecated.

Resources