I am using a package called 'concurrently' to run my client and server at the same time on localhost. Client runs on port 3000 while server runs on port 5000. I have set proxy in the package.json of server in the following manner:
"proxy": "https://localhost:5000"
But when I make a request from client in the following manner:
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const res = await axios.post('/api/users', body, config);
It says: POST http://localhost:3000/api/users 404 (Not Found). I don't understand why but despite setting proxy, axios keeps making request to port 3000 instead of port 5000. What is the issue?
I just want to say that the solution of adding cors is not a solution. You need to include the proxy "proxy" : "https://localhost:5000" in the package.json, you may need to restart or something or other-- but if you choose to use cors instead, you are allowing anyone to access your API. That means your database is wide open for people to poke around with. Passwords, emails, users, etc. It's all compromised.
I got it working correctly. What I did was:
1) change axios.post('/api/users', body, config); to axios.post('http://localhost:5000/api/users', body, config);
2) Then in the 'users' express route on the server side, add CORS functionality by installing 'cors' npm package, and then adding the following lines:
const router = express.Router();
...
// add these lines
var cors = require('cors');
router.use(cors());
...
router.post('/', async (req, res) => {
...
});
as far as I understood your question, what you need is to refer Axios developer documents. for time being.
check this
import axios, { AxiosInstance } from 'axios';
import * as tunnel from 'tunnel';
const agent = tunnel.httpsOverHttp({
proxy: {
host: 'proxy.mycorp.com',
port: 8000,
},
});
const axiosClient: AxiosInstance = axios.create({
baseURL: 'https://some.api.com',
httpsAgent: agent,
});
In my case I didn't check well, it appeared that the call was actually forwarded to the api server at the proxy address.
Check that the server is running and whether it is receiving your calls or not.
when I send request to a server with proxy my code works successful. I hope this answer useful to you or another peoples.
const axios = require("axios");
const cheerio = require('cheerio');
async function sendRequestWithProxy() {
let proxyServer = {
"host" : "YOUR_PROXY_HOST",
"port" : "YOUR_PROXY_PORT",
"username" : "YOUR_PROXY_USERNAME",
"password" : "YOUR_PROXY_PASSWORD"
};
var ProductUrl = "http://YOUR_REQUEST_URL";
await axios.get(ProductUrl, {
proxy: {
host: proxyServer.host,
port: proxyServer.port,
auth: {username: proxyServer.username, password: proxyServer.password}
},
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36', }
}).then((response) => {
const $ = cheerio.load(response.data);
let productInfo = $("#HTML_ID_ATTRIBUTE").text();
///YOUR CODE
}).catch(function (error) {
if (error.response) {
//ERROR AREA
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
}
});
}
Related
I was using the following code within my Flutter app and it was working with no problems, but today after I upgraded my Flutter, it doesn't work and gives me XMLHttpRequest error.
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
final url = Uri.parse('http://$host:8000/api/$urlSegment');
try {
final http.Response response = await http.post(
url,
headers: {"Content-Type": "application/json"},
body: json.encode(
{
'email': email,
'password': password,
},
),
);
Does anything have been changed in new Flutter version? Should I change the following line of code that specifies my host address?
final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
EDIT: I tried to add cors to my NodeJS backend server and this is my app.ts file as following:
import express, { Request, Response, NextFunction } from "express";
import cors from "cors";
import dotenv from "dotenv";
dotenv.config();
import config from "config";
import responseTime from "response-time";
import connect from "./utils/connect";
import logger from "./utils/logger";
import routes from "./routes";
import deserializeUser from "./middleware/deserializeUser";
import { restResponseTimeHistogram, startMetricsServer } from "./utils/metrics";
import swaggerDocs from "./utils/swagger";
const allowedOrigins = ['http://localhost:8000' , 'https://10.0.2.2:8000', 'http://127.0.0.1:8000'];
const options: cors.CorsOptions = {
origin: allowedOrigins
};
const port = config.get<number>("port");
const app = express();
app.use(express.json());
app.use(cors(options));
app.use(deserializeUser);
app.use(
responseTime((req: Request, res: Response, time: number) => {
if (req?.route?.path) {
restResponseTimeHistogram.observe(
{
method: req.method,
route: req.route.path,
status_code: res.statusCode,
},
time * 1000
);
}
})
);
app.listen(port, async () => {
logger.info(`App is running at http://localhost:${port}`);
await connect();
routes(app);
startMetricsServer();
swaggerDocs(app, port);
});
But still doesn't work and I get the same error!
You've set the allowed origins to :8000, but that's the backend server's address. Instead, you need to set it to the Flutter debug server's address (and eventually to the web server where you host the production app, if that's not exactly the same as the backend server). (You can remove all the addresses ending in 8000.)
The problem is that the debug server picks a random port for each run. You can tell it to use a fixed port and then that becomes the port you need to include in your allowed origins.
Add --web-hostname=localhost --web-port=9999 as command line parameters to where you run your main.dart, then add localhost:9999 as an allowed origin.
(As a get-out-of-jail, also try * as an allowed origin.)
Finally, you should probably explicitly set the CORS allowed methods to the list of methods your server's API expects; probably OPTIONS, GET and POST.
I have this react-app that is connected to a node/express server. The node/express server all it has is app.get(api)
I connected it to 4 different apis, it gets the data and sends simply returns it to the front-end/client.
When I was building it and running it locally, it worked no problem. I would get the json objects and my front-end cleans the data and displays it. As soon as I deployed my server to heroku, it stopped working. I'm using axios to make the requests and I changed it from http://localhost/3000 to the url that heroku gave me. Now instead of getting my json data I get this error:
If it helps, when I run the url directly in my browser it works, I do see the data like I'm supposed to. Why is that? Thank you so much to whoever helps me!
As requested, this is a part of my express server, the other two routes are basically the same thing but of course to different APIs.
const express = require("express");
const axios = require("axios");
const app = express();
const cors = require("cors");
require("dotenv").config();
// This enables our app (server 3000) to make requests
// can also do "*" to allow anyone to make them but not recommended
// for security reasons
app.use(
cors({
origin: "*",
}),
);
app.get("/walmart/:item", (req, res) => {
let url = `https://www.walmart.com/search/api/preso?prg=desktop&page=1&query=${req.params.item}`;
var config = {
method: "get",
url: url,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0",
Accept: "application/json",
"Accept-Language": "en-US,en;q=0.5",
"content-type": "application/json",
wm_client_ip: "",
Connection: "keep-alive",
Cookie: process.env.WALMART_COOKIE,
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
},
};
axios(config)
.then((response) => {
res.send(response.data.items);
})
.catch((err) => {
res.send(err);
});
});
app.get("/wholefoods/:item", (req, res) => {
let url = `https://www.wholefoodsmarket.com/api/search?text=${req.params.item}&store=10152&limit=60&offset=0`;
axios
.get(url)
.then((response) => {
res.send(response.data.results);
})
.catch((err) => {
res.send(err);
});
});
and this is the data I should be receiving when I call those routes from my react app (and the one I get when I use my browser at the moment)
I have an application connecting to a Nestjs server to establish a WS connection (server is on a different URL, so it is a CORS request).
The WebsocketGateway is defined as such.
#WebSocketGateway(port, {
handlePreflightRequest: (req, res) => {
const headers = {
'Access-Control-Allow-Headers': 'Authorization',
'Access-Control-Allow-Origin': 'the page origin',
'Access-Control-Allow-Credentials': true,
};
res.writeHead(200, headers);
res.end();
}
})
Works like a charm on Chrome v87 and down and on Firefox. Since upgrading my browser to Chrome 88, the front-end socket-io connection goes on a connect-reconnect loop, as:
The preflight request passes and gets a 200 response, with the headers set above;
The actual connection fails with CORS error as the only message in the browser console
Just incase someone else needs this, in your decorator there is a cors property
#WebSocketGateway({ cors: true })
This is how i fixed
import { IoAdapter } from '#nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
export class SocketAdapter extends IoAdapter {
createIOServer(
port: number,
options?: ServerOptions & {
namespace?: string;
server?: any;
},
) {
const server = super.createIOServer(port, { ...options, cors: true });
return server;
}
}
main.ts
const app = await NestFactory.create(AppModule, { cors: true });
app.useWebSocketAdapter(new SocketAdapter(app));
I have been trying to do an api call (nodejs with express running on localhost) from a react app running in the browser over a local dev server (web-pack dev server). Everything was working well until I tried to call the api. They are both running on separate ports.
I have tried adding the cors headers (Recommended by MDN) to both the post call (from the app in browser) and to the response from the Nodejs API but neither of these solved the issue.
Code for the api call (in browser):
const headers = {
'Content-Type': 'application/json',
'access-token': '',
'Access-Control-Allow-Origin': '*',
}
export default async () => {
try {
const body = JSON.stringify({
test: true,
})
const response = await fetch('http://localhost:1337/internal/provider/check_email_exist', {
method: 'POST',
headers,
body,
})
console.log(response)
} catch (e) {
return e
}
}
API Middleware (in nodejs):
// Verify All Requests
app.use(VerifyToken)
// Compress
app.use(compression())
// Helmet middlware
app.use(helmet())
// Body Parser
app.use(bodyParser.urlencoded({
extended: false,
}))
app.use(bodyParser.json())
The expected result is to just give a 200 status code and respond with the data.
The actual output is:
OPTIONS http://localhost:1337/internal/provider/check_email_exist 404 (Not Found)
Access to fetch at 'http://localhost:1337/internal/provider/check_email_exist' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Since you're using webpack-dev-server you can use the proxy option DevServerProxy.
Your configuration will look like this:
// webpack.config.js
devServer: {
proxy: {
'/internal': 'http://localhost:1337'
}
}
Since I can't see your express routes on your question I'm speculating about the proxy route if your API lives on /internal endpoint then you should modify your React code like this:
const response = await fetch('/internal/provider/check_email_exist', {
method: 'POST',
headers,
body,
})
As you can see I ommited the https://localhost:1337 because the proxy option from webpack-dev-server will handle this and it will redirect to http://localhost:1337. Hope this will help you. Cheers, sigfried.
EDIT
As the comment on your question pointed out you should set the headers on your express server, not the client, for this task you can use the cors-middleware package.
Maybe this can help if you face with preflight errors.
My full config:
const cors = require('cors');
const express = require('express');
const { createProxyMiddleware: proxy } = require('http-proxy-middleware');
...
const logLevel = 'info';
const ip = require('ip').address();
const proxyOptions = {
xfwd: true,
target,
changeOrigin: true,
logLevel,
cookieDomainRewrite: {
'*': 'localhost',
},
headers: {
'X-Forwarded-For': ip,
'X-Node': 'true',
},
};
const backNginxApp = express();
backNginxApp.use(
cors({
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
origin: 'http://localhost:3000',
optionsSuccessStatus: 200,
credentials: true,
})
);
backNginxApp.use('/api', proxy(proxyOptions));
API: const target = 'https://someapi.com'
Local development running at: http://localhost:3000
I am trying to fetch some data from the development server using React.
I am running the client on localhost:3001 and the backend on port 3000.
The fetch request :
const users = fetch('/api/users');
users.then((err,res) => {
console.log(res);
})
When I run my development server and webpack-dev-server I get the following output:
GET http://localhost:3001/api/users 404 (Not Found)
I tried specifying the proxy in the package.json so it would proxy the request to the API server, however nothing has changed.
Here is my package.json file:
.. and the webpack.config :
Please tell me, if you need to see anything else from my project. I apologies, if I'm missing something and not being thorough, I'm still quite new to using these technologies.
You can modify your fetch request API url to give the complete hostname since
fetch('http://localhost:3000/api/users')
also make sure that you have CORS enabled on your backend
In case your want to redirect through webpack, your can try devServer.proxy as
devServer: {
inline: true,
contentBase: './dist',
port: 3001,
proxy: { "/api/**": { target: 'http://localhost:3000', secure: false } }
}
I know I'm a little late to the game here, but I'll leave it here for future reference.
To make the devServer proxy work as expected, you need to specify the HTTP Accepts header to be something else than "text/html". Do this with the init-object that fetch accepts as the second argument. A simple example:
fetch("/api/profile",{
headers:{
"accepts":"application/json"
}
})
.then(res => {
console.log(res);
return res.json();
})
.then(json => console.log(json) )
.catch( a => { console.log(a) });
The reason for this is that the WebPack Dev Server normally uses a context/namespace to differentiate between what to serve and what to forward. The create-react-app scripts do not extract a namespace from the proxy path in the package.json file. Instead the scripts has the opinionated default behaviour that any request using something else than HTTP GET will get forwarded. Also, anything using HTTP GET, but NOT text/html as the Accepts header will get forwarded.
The reasoning is because most React Apps are SPA (Single Page Applications) which use AJAX/Fetch to communicate with some API. API's normally use JSON or XML, but not text/html.
In the package.json
"proxy": {
"/api/users": {
"target": "http://localhost:3000"
}
},
I had the same problem using axios and was only able to get it working by using the complete hostname and enabling Cors.
const response = await axios.get('http://localhost/users/');
Install cors
npm i cors
Use cors
const express = require("express");
const request = require("request");
const cors = require("cors");
const app = express();
app.use(cors());
app.use("/", (req, res) => {
//...
});
app.listen(80, () => {
console.log("CORS-enabled web server listening on port 80");
});
Ref
The solution by user jellyfish-tom in https://github.com/webpack/webpack-dev-server/issues/793#issuecomment-316650146 worked for me.
devServer: {
proxy: {
"*": "http://[::1]:8081"
// "secure": false,
// "changeOrigin": true
}
},
Webpack Dev Server uses devServer.proxy config in your Webpack config to control proxying requests.