I have a fullstack application dockerized and deployed on a VPS with a custom domain, but there's an issue where requests I made on the frontend give me a Cors error like this.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://backend:8080/api/link/. (Reason: CORS request did not succeed). Status code: (null).
I normally use Create react app and it doesn't give me this error, but for this I'm using Vite and can't seem to find out what's causing it.
On my backend I've added the Springboot annotation to deal with the Cors error.
#CrossOrigin(origins = "*")
and also disabled Cors in my security config.
On the frontend side, I added this which points to my backend (Docker service)
"proxy": "http://backend:8080",
and this is my vite.config.js
export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
secure: false,
ws: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
port: 3000,
},
plugins: [react()],
});
I can make requests from Postman and it works as expected
You need to proxy the request
CORS requests will be blocked by the browser for security reasons To avoid this, the backend needs to inject allow origin header for you.
const proxy = require('http-proxy-middleware');
module.exports = function (app) {
app.use(proxy('/api', {
target: 'http://www.api.com',
logLevel: 'debug',
changeOrigin: true
}));
};
or you can use the google chrome extension Allow CORS: Access-Control-Allow-Origin
link: https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en
There are many suggestions online, i too have tried most of em.
Using #CrossOrigin("URL") over your controller class
Disabling cors via object of HttpSecurity, such as http.cors().disable();
Ultimately, i had to implement WebMvcConfigurer interface to resolve this issue.
#EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("URL");
}
}
Hope this helps
Related
I am learning react, I currently have a .net core API running in visual studio on localhost:7071.
The Local API is not running cors as there is no requirement for it to use Cors.
Creating a simple react client using the following will not return data due to a cors error?
I have tried a number of solutions online and none of them work, so how can I make this "simple" react client work without generating the following error
Access to XMLHttpRequest at 'http://localhost:7071/api/Users' 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.
function GetApiResults(){
const axios = require('axios').default;
axios.defaults.headers.common["Access-Control-Allow-Origin"] = "*";
axios({
method: 'get',
headers: { 'Content-Type': 'application/json' },
url: 'http://localhost:7071/api/Users',
}).then(function (response) {
console.log(response.data);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
}
export default GetResults;
You have a pretty straighforward description of the issue, browser expects the external resouces you are using (API in your case, external in terms it is not on same port) to provide CORS headers. If they are not set - browser will not execute the request. It will execute the request if you open the resource URL in browser tab, but if you are on localhost:3000 - any requests initiated by this page to anything that is not on localhost:3000 will require CORS to be set.
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0
Browser security prevents a web page from making requests to a different domain than the one that served the web page. This restriction is called the same-origin policy. The same-origin policy prevents a malicious site from reading sensitive data from another site.
So either enable CORS support in your backend, either use CRA feature called Proxy: https://create-react-app.dev/docs/proxying-api-requests-in-development/
I prefer the manual proxy configuration, at the very end of the article.
Important: this proxy is for DEVELOPMENT only!
Here is a step-by-step instruction, just tested:
Install npm install http-proxy-middleware --save
Add src/setupProxy.js with content:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
"/api",
createProxyMiddleware({
// I have a different port and Visual Studio might randomly change it
// Fix: edit running configuration
// https://stackoverflow.com/questions/70332897/how-to-change-default-port-no-of-my-net-core-6-api
// Notice: no /api at the end of URL, it will be added.
// more details at: https://www.npmjs.com/package/http-proxy-middleware
target: "https://localhost:7002",
changeOrigin: true,
// Im using .net core 6 starting api template
// which is running with a self-signed ssl cert with https enabled
secure: false
})
);
};
Modify your AXIOS configuration object to use new URL:
function GetApiResults() {
const axios = require("axios").default;
axios({
method: "get",
headers: { "Content-Type": "application/json" },
url: "/api/WeatherForecast"
})
/* ... */
}
Note: Im using default web api project, only changed [Route("api/[controller]")] (added api/) for Controller.
Restart the app and watch for logs from npm start output, proxy can log some errors there.
CORS is a browser feature. So, the browser you are using to access the React app must require you to use CORS. You need to setup CORS on your backend and allow connections from remote origin.
It will be good if you add CORS enabling code on Server Side. if your server-side app is in Express JS then add below middleware-
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
// res.header("Access-Control-Allow-Origin", "http://localhost:3000"); or add your react app url.
next();
});
I'm trying to config my Docusaurus web app to proxy the request to my api endpoint. For example, if I make a fetch request in my app fetch(/api/test), it will proxy the request from localhost:3000/api/test to my {{api_endpoint}}/api/test, but I'm still struggling to do it.
What I've done:
add a proxy field in package.json
create a setupProxy.js in the src folder
These 2 are based on the Proxying API Requests in Development
Another approach way is I created a custom webpack plugin and add it to the Docusaurus config
Does anyone have experience on this problem ? Thanks for reading, I really appreciate your help.
I went down the exact same path. Ultimately Docusaurus runs its Webpack dev server under the hood which is why the proxy field and setupProxy.js were not working as expected. I was able to get the outside API call by proxy and solved CORS errors by creating a Docusaurs plugin like you are attempting. Adding the "mergeStrategy" and "changeOrigin" were the keys to getting it all working.
// plugins/webpack/index.js
module.exports = function (context, options) {
return {
name: "cusotm-webpack-plugin",
configureWebpack(config, isServer, utils) {
return {
mergeStrategy: { "devServer.proxy": "replace" },
devServer: {
proxy: {
"/YOUR_COOL_ROUTE": {
target: "https://YOUR_COOL_API/",
secure: false,
changeOrigin: true,
logLevel: "debug",
},
},
},
};
},
};
};
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.
I am trying to 'connect' my small React JS app with my Deno API backend on my local environment with fetch().
const apiUrl = `http://localhost:8000`;
try{
fetch(apiUrl)
.then((res) => res.json())
.then((repos) => {
console.log(repos);
setAppState({ loading: false, repos: repos });
});
}catch(err){
console.log(err);
}
My app is serving on localhost:3000 and my deno api on localost:8000.
However, I am having problem with CORS:
Access to fetch at 'http://localhost:8000/' from origin 'http://localhost:3000' has been blocked by CORS policy: 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.
I tried some suggestions like:
add line '"proxy": "http://localhost:8000" to reactjs project packages.json'.
Or to add:
var options = {
method: 'get',
headers: {
"Access-Control-Request-Headers": "*",
"Access-Control-Request-Method": "*"
},
}
fetch(apiUrl, options)
Or to add:
fetch(apiUrl, {mode: 'no-cors'})
However, nothing works in my case. All the time getting the same error and some additional based on suggestions.
So,I need to disable CORS in my reactjs and deno api app to allow local dev communication between frontend and backend.
Solution in my case was pretty easy.
I had to import oakCors into my Deno API app.ts
import { oakCors } from "https://deno.land/x/cors/mod.ts";
after that, just add the excluded origin after app instantiation:
app.use(
oakCors({
origin: "http://localhost:3000"
}),
);
NOTE: I tried to set origin to origin: false and that did not work in my case.
For more options on Deno CORS here is a link: https://deno.land/x/cors
This works just fine:
app.use(oakCors({ origin: "*" }));
For me, I had to first pass oakCors configuration to the app and then the routes.
app.use(oakCors({
origin: 'http://localhost:4200',
optionsSuccessStatus: 200,
}));
app.use(router.routes());
placeapp.use(oakCors()) before your routes like this:
app.use(oakCors())
app.use(route.routes())
this is allow all CORS before to manage the routes
I'm running a react dev server on http://localhost:3000 and an express server on http://localhost:8080 and am using an Apollo Client to query the server. To enable session data to be passed from client to server I have added the credentials: "include" parameter when initializing the Apollo Client.
I've added the following line in my express server (before the routes are defined) to configure cors:
app.use(cors({ credentials: true, origin: "http://localhost:3000" }));
However, when executing queries, the following error is thrown:
Access to fetch at 'http://localhost:8080/graphql' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
Why is the header response showing up as *? Am I configuring CORs incorrectly or am I missing something else?
The problem I was running into here was that despite enabling CORS for express:
app.use(cors({ credentials: true, origin: "http://localhost:3000" }));
The GraphQL middleware was over-riding the setting. Make sure to pass the cors: false param as shown below if using an Apollo Server and associated middleware.
gqlServer.applyMiddleware({ app, path: "/graphql", cors: false });
This error is a CORS error generated by the browser. use npm install --save http-proxy-middleware in your front end and add setupProxy.js file in frontend/src/setupProxy.js
setupProxy.js
//run defferent ports for website and api server
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api/', { target: 'http://localhost:8080/' })); //make change as per your application (So you can access your data on http://localhost:8080/api/ )
};
Alternate solution
If you are using webpack dev server, here's another way to proxy requests without making changes on NodeJS. Adding this to package.json:
"proxy": "http://localhost:8080"
Should allow webpack to proxy requests made to http://localhost:3000 to http://localhost:8080.
But this would mean request will need to be made to http://localhost:3000 instead of http://localhost:8080.
Since you have credentials: true, you should include the credentials in your fetch call:
fetch(url, {
credentials: 'include'
})
or
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
This will send the request with the headers set to Access-Control-Allow-Credentials: true
without this, it will be rejected.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials