I'm trying to move my proxy config out of my package.json and move it into a setupProxy.js, as per the docs, however I'm failing at the first hurdle.
My react app (created with CRA) is running on http://localhost:3000/. My API is running on https://localhost:7146.
With the package.json approach, everything works as expected - calls to the server succeed.
"proxy": "https://localhost:7146",
First request executed is
GET
http://localhost:3000/
Status 200 OK
However when I remove this line from package.json, create a setupProxy.js file and try and configure it, I cant get it working.
// setupProxy.js
const { createProxyMiddleware } = require("http-proxy-middleware");
const setupProxy = (app) => {
app.use("/",
createProxyMiddleware({
target: "https://localhost:7146",
changeOrigin: true,
}),
);
};
module.exports = setupProxy;
The first request executed is
GET
http://localhost:3000/
Status 500 Internal Server Error
Error occurred while trying to proxy: localhost:3000/
Can anyone help me understand how to configure the proxy via setupProxy.js? I'm finding the docs pretty limited in this area. I've tried different middleware paths (/, *, /api) but I get the same error. I've tried not specifying a middleware path in app.use and instead specifying it only as a createProxyMiddleware parameter and still get the same error.
Note, I understand that this example is super basic and there is no need to use setupProxy over the package.json approach, however I plan to do some more complicated configuration as soon as I get the basics nailed down.
Related
I've been tasked with transitioning a development CRA build to work in production. Currently we use an api proxy in development with a setupProxy.js file as such:
const BACKEND_URL = process.env.BACKEND_URL
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function setupProxy(app) {
app.use(
'/api',
createProxyMiddleware({
target: BACKEND_URL,
changeOrigin: true,
})
)
}
This works as expected in development but this feature isn't meant for production, so I've changed all the API endpoints to make proper use of the backend url (basically going from axios.get(/api/endpoint) to something like axios.get(`${process.env.BACKEND_URL}/api/endpoint`)
From what I can tell now, the calls are pointed at the right place now (before it was erroring out the whole app), but I immediately get a 401/unauthorized error for every call and even my websockets as soon as I log into the app, no data being returned.
Is there a critical part of the transition to prod - and specifically the replacement of the api proxy - that I am missing? It seems like there some sort of token missing that is causing all my calls to fail but there was no such token as part of the setupProxy file? Any direction or help would be appreciated
Simple setup:
React App created with create-react-app
ASP.NET Core web API - a couple of controllers (currently no security until I make it work)
Both the API and Application are deployed to Azure.
When I run the app locally with configured proxy (I contact the deployed API on Azure) it works correctly makes the calls.
If I try the API directly from my machine it works too (PostMan for example)
When I open the deployed React APP - The application loads correctly but the call to the API doesn't get proxy(ed). What I mean it's not returning 404, 403 - it returns status 200, but makes the call to the app itself instead of proxy the request to the API.
I've tried both using "proxy" configuration in package.json as well as using "http-proxy-middleware". Both cases work with locally running app, but not deployed. Here is the configuration of the proxy:
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://XXXXXX.azurewebsites.net',
changeOrigin: true,
})
);
};
I suppose it's something related to the configuration of the node server used when I deploy to azure, but I don't have a clue what.
I've used the following tutorial for deployment: https://websitebeaver.com/deploy-create-react-app-to-azure-app-services
But as seen from content there is no proxy part in it.
After long troubleshooting I realize the issue was due to wrong understanding of the proxy configuration.
So I was not realizing the proxy configuration is respected only in debug mode and totally ignored into prod build. And of course while debugging the issue I was not realizing the Azure Deployment pipe was doing production build. So the resolution was to detect the production/dev on application layer and inject correct URL.
Here I hit another issue - process.env.NODE_ENV, which I was using to distinguish between development and production was undefined into my index.tsx - it was available in App.tsx and all its children, but not in index.tsx where my dependency container was initialized.
What resolved my issue is package called dotenv. Then I've just imported it into index.tsx and the process.env was available.
import * as dotenv from 'dotenv';
I am implementing http proxy middleware in to my react app. I want to proxing qa or dev backend services urls from my local .
Example of my dev login url below
https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login
my setupProxy.js
module.exports = function (app) {
app.use('/auth/login' ,createProxyMiddleware({
target: 'https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login',
changeOrigin: true,
})
);
};
I started my app and click the login button and the request got failed with 404 not found error . Not sure why my target is not replacing with my actual http://localhost:9009/auth/login uri to https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login.
Also am not getting proxy created message in my console when we do npm start as well. I am using webpack dev server not react-scripts . If any changes required on webpack side or am i missing anything badly please let me know. I tried small poc it got worked but that is simple without herokuapp things.
It took me some time to understand how the http-proxy-middleware works.
Look at the following diagram from the http-proxy-middleware Docs
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
For simple configurations, any request that your front-end does calling an API get observed by a matching pattern on the path section of the above diagram and overwritten with your target configuration, to be exposed in the header of the request as a different URL. This also help you in the development phase locally to avoid the CORS blocking mechanism of the browsers.
Example:
Let's imagine we need to call from our front-end exposed at http://localhost:3000 to an endpoint located at https://localhost:7005/api/WeatherForecast
This type of calls will be blocked in all browsers by CORS.
So, with the following config, you will be able to bypass the cors problem.
const { createProxyMiddleware } = require('http-proxy-middleware');
const context = [
"/api",
];
module.exports = function (app) {
const webApiProxy = createProxyMiddleware(context[0], {
target: 'https://localhost:7005',
secure: false,
changeOrigin: true,
headers: {
Connection: 'Keep-Alive'
},
logLevel: 'debug'
});
app.use(webApiProxy);
};
With this, any request made from http://localhost:3000 will be intercepted by the proxy-middleware and if it finds a /api in some part of the path will be changed to https://localhost:7005/api and also concatenate the rest of your original path following the /api.
So finally, your front-end will be asking things from http://localhost:3000 but all the request will arrive to https://localhost:7005 as if they were request by https://localhost:7005 and this will fix the Cors problem coz your requesting and responding from the same origin.
I Guess your can fix your problem by writting your config this way:
module.exports = function (app) {
app.use('/auth/login' ,createProxyMiddleware({
target: 'https://dev.sju.uk/auth/login',
changeOrigin: true,
headers: {
Connection: 'Keep-Alive'
},
})
);
};
Bare in mind, this libray not only can help you with the CORS problem but also to perform hundred of things for any request/response like change arguments from the body, add things to the body, add headers, perform operations before the request aka logging what's requested, perform operations on the response aka logging again what has returned, etc, etc.
Hope this will help to resolve your issue!
I am building a web application from the ASP.Net Core React template, whose "ClientApp" React portion appears to be a 'create-react-app' project. When I deploy the app to IIS, it gets hosted in a subfolder from the root, i.e. http://myserver.com/SubApp. Because of this, I have changed the "homepage" value in package.json to http://myserver.com/SubApp.
What I am now experiencing is that when I am making fetch calls in my javascript code locally, if I use fetch('/myendpoint'), the the url requested locally is https://localhost:44315/myendpoint (which works), but when deployed, this url becomes http://myserver.com/myendpoint, which does not work.
Conversely, when I make the endpont fetch('myendpoint') (no leading slash), the server requests the correct URL http://myserver.com/SubApp/myendpoint but localhost fetches the incorrect URL, https://localhost:44315/SubApp/myendpoint.
I understand that the leading slash makes the request from the root, but the root appears to be different in localhost vs. on the server.
For local debugging purposes, I tried setting a proxy in package.json to https://localhost:44315 so that hopefully fetch('myendpoint') (no leading slash) would work in my local environment, but when I try this, chrome prompts me to sign in repeatedly without ever successfully making the request.
I feel like I am almost there, but I must be missing something. How can I configure my package.json (or other project configuration) to make the fetch commands succeed on both localhost and my server, without doing something hacky like checking the URL in the javascript code before every fetch?
What you need is Proxying API Requests in Development.
It easily allows you to call any endpoint in development and forward it to your backend or other location without CORS issues or your problem of mismatched endpoints.
You will have to use the manual configuration option, since the default proxy setup only helps with host/port forwarding.
Install http-proxy-middleware as a dev dependency:
$ npm -i http-proxy-middleware --save-dev
Following the guide linked above, you can use this configuration:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/SubApp/*',
createProxyMiddleware({
target: 'localhost://44315', // or anything else, point to your dev backend
pathRewrite: {
'^/SubApp': '/', // remove base path
},
})
);
};
You can then fetch with the /SubApp part in the request which will be removed in developement. You can use other configurations to achieve this, this is one example.
I had this same experience as well and found that setting the homepage value in the package.json is a dead end. What you want to do is make use of the PUBLIC_URL environment variable to set a full absolute url in your .env . There may be a way to use relative urls, but there were some edge cases that just made it cleaner to use an absolute URL.
When you set this environment variable you want to make use of it in the following places:
Your Routes (if you use react router)
The path should be prefixed by process.env.PUBLIC_URL
Your internal links should also be prefixed by the env var.
I have a node.js Server listening on 3300. It is tested okay with postman.
I have a react app created using create-react-app listening on 3000 and package.json having the statement "proxy":"http://localhost:3300". This is also tested okay.
I have another react app on the same machine, which is using webpack and listening on 8080. The package.json also has the same proxy statement "proxy":"http://localhost:3300" . In this case, when I am calling the api /api/users, my console log says
api-auth.js:5 POST http://localhost:8080/auth/signin/ 404 (Not Found)
if I directly call the api as
fetch('http://localhost:3300/api/users')
it fails with CORS error.
just to be more clear, this failing react app is actually downloaded from http://mdbootstrap.com in which I add a login form to test if it works.
Can you please help me resolve this issue?
As per my understanding just by adding the proxy line in the package.json does the trick but somehow it does not work when webpack is used.... is there something I should do in webpack as well?
Unless I'm mistaken, { proxy } from package.json is not read by webpack, webpack-dev-middleware or webpack-dev-server. It would explain the 404 response you are receiving.
You should try configuring { devServer.proxy }. If you would prefer, you can even import package.json to get the server URL.
Here's a simple example with with a web server proxying requests to an API server listening on localhost:3000.
You don't need proxy for this, you can install npm package "cors".
https://www.npmjs.com/package/cors
And use it at you node.js server. Here is how i use it at my express.js server.
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());