Webpack dev server Proxy is not working - ReactJS - reactjs

I want run my project on localhost:3000/upct/ROUTES
But I have my API in: http://desarrollo.com/api
I wanna use proxy option in Webpack but it is not working. I get error of CORS and others... My proxy config looks like:
CONFIG.devServer = {
//host: 'localhost',
port: 3000,
proxy: {
'/api/**': {
target: 'http://desarrollo.com/api',
secure: false,
changeOrigin: true
}
},
contentBase: PATH.join(__dirname, '/src'),
hot: true,
inline: true,
historyApiFallback: true/*,
headers: {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
}*/
};
I do my AJAX querys like:
$.ajax({
url: "http://desarrollo.com/api",
data: "",
type:"GET",
dataType: "JSON",
})
.done((respuesta) => {
console.log(respuesta);
}).fail(function(xhr, textStatus, errorThrown){
console.log("XHR: ", xhr/*.responseText*/, "Text Status: ", textStatus + '\n' + "Error Thrown: ", errorThrown);
})
I supposse proxy is for doing AJAX querys into my API without CORS errors. But it is not working. What is wrong here?
Thank you.

When using proxy, you have to send your requests to the localhost, so that proxy could redirect them to remote server without CORS. In your $.ajax() pass url: "/api".
After that when you run your app locally your requests will be sent to http://localhost:3000/api and when it runs on http://desarrollo.com it will send requests to http://desarrollo.com/api.

To add more to #GProst response, Below changes will work.
Find Protocol :
this.protocol = () => {
let returnValue = 'https://';
if (location.protocol !== 'https:') {
returnValue = 'http://';
}
return returnValue;
};
Find Hostname :
const hostName = window.location.hostname + (!window.location.port === false ? ':' + window.location.port : '');
Required URL :
const URL = this.protocol() + hostName;
Now Above URL can be used in Ajax.
$.ajax({
url: URL,
data: "",
type:"GET",
dataType: "JSON",
})
This will work in both webpack-dev-server as well as in application server e.g. Apache.

Related

Cookies are being sent but chrome doesn't set them

I saw many similar questions and played with many combinations but nothing works.
I specify that it's all on localhost.
regUser = () => {
var username = getE("username-input").value;
var email = getE("email-input").value;
var password = getE("password-input").value;
axios({
url: process.env.REACT_APP_API_URL + "register",
method: "post",
data: {
username, email, password
},
withCredentials: true
}).then(res => {
if(res.data.regSuccess) {
// Registration successful
this.setState({
regSuccess: true,
regTextHidden: false,
regText: "Registration Successful! An e-mail was sent to the specified e-mail address with confirmation information! You will be redirected to the Login page..."
}, ()=>{
setTimeout(
()=>{window.location.href=("/login")}, 5000
)
})
} else {
this.setState({
regSuccess: false,
regTextHidden: false,
regText: "An error occured. Please try again later!"
})
}
})
}
Backend code:
f.checkPassword(userData, function(result) {
if(!result.correct) {
// Wrong password
res.send({found: true, correct: false})
} else {
// Proceed with authentication
var token = f.genToken(userData.user);
res.header("OPTIONS", 'true')
res.cookie("access-token", token.token, {httpOnly: true, sameSite: "none", maxAge: "100000", secure: false});
res.send({found: true, correct: true})
}
})
No matter what cookie settings I use, they are being sent, the "Set-Cookie" header is present but no cookie is set.
I've played with every option for like 2 days but it just doesn't work. Any advice?
I was stuck on this for a while too. A couple things fixed it for me:
in the frontend in the axios call (which I see you've done), use:
withCredentials: true
Then in the backend in express, use npm package cors, with the following:
const app = express();
app.use(cors({ credentials: true, origin: 'http://localhost:3000' }));
Or use whatever your url origin is. Hope this works for you.

CORS: proxying localhost via webpack-dev-server to external API

I'm building simple react-powered contact page and it would be swell if I could test email sending from my local development machine. I'm using Zoho Email API, which I tested with curl and Insomnia - there everything is fine, I'm able to send emails.
Problems start when I try to do the same from React app via axios. The app itself is served locally via webpack-dev-server. Without proxying request through wds, the browser complains about CORS. But when I'm trying to proxy request via wds with the appropriate headers set I'm being greeted with 400 Bad Request and not much more to aid with the debugging.
The relevant wds setup:
const ReactRefreshWebpackPlugin = require('#pmmmwh/react-refresh-webpack-plugin')
exports.devServer = ({ host, port } = {}) => {
const plugin = new ReactRefreshWebpackPlugin()
return {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers':
'X-Requested-With, content-type, Authorization',
},
proxy: {
'/api/accounts/ZOHO_ID_NOT_SHOWN/messages': {
target: 'https://mail.zoho.eu',
secure: false,
},
},
https: true,
contentBase: path.join(__dirname, 'assets'),
stats: 'errors-only',
historyApiFallback: true,
overlay: true,
hot: true,
host,
port,
},
plugins: [plugin],
}
}
And function in which I'm using to axios to send the email:
const sendEmail = async () => {
const { name, email, message } = formState
try {
const response = await axios({
method: 'post',
url: EMAIL_SEND,
headers: { Authorization: EMAIL_AUTH },
data: {
toAddress: EMAIL_TO,
subject: `Message from ${name} # ${email}`,
content: message,
},
})
console.log(response) // debugging
} catch (e) {
console.log(e.response)
}
}
In the above function, EMAIL_SEND is imported from elsewhere and its value is /api/accounts/ZOHO_ID_NOT_SHOWN/messages - mirroring the wds proxy value.
With the above setup, when I try to send a test email from localhost I'm getting 400 Bad Request... and not much more. I'm sure that the issue is with how I'm proxying the request via wds but I kind of run out of ideas how I can fix it. Any suggestions will be greatly appreciated!

How to send request to an API on remote server via webpack devlopment server using axios

I want to fetch some data from my remote server supporting REST API.
I am using axios and web-dev-server. My frontend is sending request and I have used both firefox and chrome to open my frontend.
However every time I tries to make request I encounter cors error.
Also I don't want to make any changes on my server.
The firefox and chrome are sending this header.
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language :en-US,en;q=0.5
Connection:keep-alive
Host:my.ip.to.host:port
Origin:http://localhost:3000
Referer:http://localhost:3000/login
User-Agent:Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/67.0
I have tried to run my simple request code on an online platform without web-dev-server and there it runs perfectly fine.
Here is my code
//********** my request*********
return axios
.get('http://my.ip.to.host:port/api/User/login', {
headers: {
Accept: '/'
}
})
.then(function(response) {
console.log(response);
return 'user';
})
.catch(function(error) {
console.log(error);
return 'err';
});
//*****************************
//*****webpack.config.js********
var HtmlWebpackPlugin = require('html-webpack-plugin');
require('babel-polyfill');
module.exports = {
mode: 'development',
entry: [ 'babel-polyfill', './src' ],
resolve: {
extensions: [ '.js', '.jsx' ]
},
module: {
rules: [
{
test: /.jsx?$/,
loader: 'babel-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
devServer: {
historyApiFallback: true,
port: 3000
},
externals: {
// global app config object
config: JSON.stringify({
apiUrl: 'http://localhost:4000',
checkLogin: 'http://my.ip.to.host:port/api/User/login'
})
}
};
Here is the error I am getting.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://my.ip.to.host:port/api/User/login. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).`enter code here`
You need to set withCredentials as true in axios config. Cors Setting
let HttpInterceptor = axios.create({
headers: {
Accept: "*/*"
}
});
HttpInterceptor.interceptors.request.use(
function(config) {
config.withCredentials = true; // To enable CORS
return config;
},
function(error) {
return promise.reject(error);
}
);
//********** Your request*********
return HttpInterceptor
.get('http://my.ip.to.host:port/api/User/login')
.then(function(response) {
console.log(response);
return 'user';
})
.catch(function(error) {
console.log(error);
return 'err';
});
Here Google has explained the cors(Cross-origin requests) very nicely.
I have worked around this by hosting a proxy server(on the same local server where I am hosting my client) and redirecting all my single page app request via that.
First of all, I created a proxy setting in devsever key of webpack config file, like this.
devServer: {
proxy: {
//abc is REST API request endpoint on my backend
'/abc': {
//target is where your proxy server is hosted
target: 'http://localhost:5000',
secure: 'false'
},
//xyz is REST API request endpoint on my backend
'/xyz': {
//target is where your proxy server is hosted
target: 'http://localhost:5000',
secure: 'false'
}
},......// rest of the setting
}
Then,
For a particular invocation of a action via my client I make request to my backend like this.
axios
.get('/startAppkey', { withCredentials: true })// withCredential enables passing of cookies and session id. If you dont want to creat session you can avoid this.
.then((response) => {
// do stuff with response
})
.catch(function() {
//do stuff
});
Our client is all set.
Now time for proxy server.
First install http-proxy-middleware,Like this.
sudo npm i --save http-proxy-middleware
//it is also avilable on yarn
then,
To setup proxy server here is few lines of code.
import * as express from 'express'; // using express to support my middleware
import * as proxy from 'http-proxy-middleware';
const app = express();
// the path /abc and /xyz should be same as you have declared in in webpack config file
app.use('/abc', proxy({ target: 'http://your/backend/api/endpoint'}));
app.use('/xyz', proxy({ target: 'http://your/backend/api/endpoint'}));
//that's it you are done here.

After preflight (cors) request server change origin to * and chrome not display request (but i look response body). How to solve a problem?

After preflight (cors) request server change origin to * and chrome not display request (but i look response body).
Request headers
Chrome's error:
Access to fetch at 'http://localhost:6529/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'.
I use express, cors, graphql, apollo on backend and react on frontend.
Cors configuration (backend):
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
maxAge: 86400,
optionsSuccessStatus: 200,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'].join(','),
}));
Headers configuration (frontend)
const credentials = "include";
let client: ApolloClient<NormalizedCacheObject> | null = null;
export function createClient(cookie: any, ctx: any, store: any): ApolloClient<NormalizedCacheObject> {
storage.setItem("ctx", ctx);
client = new ApolloClient({
cache,
link: ApolloLink.from([
onError(({graphQLErrors, networkError}) => {
if (graphQLErrors) {
if (!SERVER) {
const redirectUrl = getRedirect(graphQLErrors);
if (redirectUrl) {
location.assign(redirectUrl);
}
}
graphQLErrors.map(({message, locations, path}) => {
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
);
});
}
if (networkError) {
console.log(`[Network error]: ${networkError}`);
}
}),
new ReduxLink(store),
new BatchHttpLink({
credentials,
uri: GRAPHQL,
headers: cookie,
fetchOptions: {
withCredentials: true,
credentials,
},
}),
],
),
ssrMode: SERVER,
connectToDevTools: true,
});
return client;
}
How to solve a problem?
I just went through the problem myself and it was a nightmare. The reason it is not working is that the CORS header must have a . in it. http://localhost:3000 doesn't meet that qualification.
I solved this issue by going into my host's file (on a Mac: /etc/hosts) and redirecting a dummy domain such as api.myapp.local to 127.0.0.1 (localhost). Then I redirected my frontend to app.myapp.local. So now when the CORS request is made it is from http://app.myapp.local:3000 to http://api.myapp.local:3001 and it meets that requirement. You can call the domain whatever you would like.

Cross-Origin Request Blocked, header Access-Control-Allow-Origin missing

I was writing a blog application which has front end in react + typescript and backend in go iris. I'm doing a get request to fetch blog content. Backend runs at localhost:5000 and node at localhost:3000.But it fails with the error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/getposts. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
I have already configured CORS in the backend
Cors := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000"},
AllowCredentials: true,
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"},
AllowedHeaders: []string{"Cache-Control", "X-File-Name", "X-Requested-With", "X-File-Name", "Content-Type", "Authorization", "Set-Cookie", "Cookie"},
Debug: true,
})
authConfig := basicauth.Config{
Users: map[string]string{USER_NAME: PASSWORD},
Realm: "Authorization Required", // defaults to "Authorization Required"
Expires: time.Duration(30) * time.Minute,
}
authentication := basicauth.New(authConfig)
app := iris.New()
app.Use(Cors)
app.Get("/getposts", authentication, GetPostsHandler)
This is how I send request
fetch("http://localhost:5000/getposts", {
method: "get",
credentials: "include",
mode: "cors",
headers: [
["Content-Type", "application/json"],
["Authorization", "Basic " + btoa("Sreyas:password")]
]
})
.then(response => {
if (response.ok) {
response.json().then(rawdata => {
this.setState({ blogdata: rawdata });
});
} else {
console.log("No posts");
this.setState({ blogdata: null });
}
})
.catch(error => {
console.log("Server Error");
this.setState({ blogdata: null });
});
I searched and tried for hours to fix this problem but no luck.
Thanks to Slotheroo for his suggestion to use nginx and that was the only possible way i could over come this problem.I used nginx to proxy the requests and route both front end and back end to 8000 port. I will leave a sample of my nginx server configuration and changes made to code here so that it helps anyone in future :)
(Please note that using loop back ip like "localhost" can affect performance on loading and sending request therefore use exact ip of the machine to overcome such performance issue)
nginx.conf
server {
listen 8000;
server_name localhost;
location / {
proxy_pass http://localhost:3000;
}
location /getposts {
proxy_pass http://localhost:5000/getposts;
}
}
Added localhost:8000 to Allowed Orgins in backend
AllowedOrigins: []string{"http://localhost:8000"},
request is now send to 8000 port
fetch('http://localhost:8000/getposts',{
method: 'get',
credentials: "include",
mode: "cors",
headers: [
["Content-Type", "application/json"],
["Authorization","Basic "+btoa('Sreyas:password')],
]
}).then((response) => {
if(response.ok){
response.json().then(rawdata =>{
this.setState({blogdata:rawdata})
})
}else{
console.log("No posts")
this.setState({blogdata:null})
}
}).catch(error => {
console.log("Server Error")
this.setState({blogdata:null})
})
}

Resources