i'm using react-native
When I run the emulator virtually the api is well requested to the backend router.
However, when I actually test it on my Android device, the api request does not reach the backend.
My front port number is 8081 and my back end is 3065.
this is my code
for example my ip address: 49.174.243.53
(front.js)
const Kakao = ({navigation}) => {
const hello = async () => {
const {data} = await axios.post('http://43.164.243.53:3065/kakao/test', {
hi: 'hi2',
});
};
return (
<LoginButton style={{marginTop: 30}} onPress={hello}>
<Label>hello</Label>
</LoginButton>
);
};
export default Kakao;
(back/app.js)
const express = require('express');
const dotenv = require('dotenv');
const morgan = require('morgan');
const path = require('path');
const kakaoRouter = require('./routes/kakao');
const db = require('./models');
dotenv.config();
const app = express();
db.sequelize
.sync()
.then(() => {
console.log('db 연결 성공');
})
.catch(console.error);
passportConfig();
app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'uploads')));
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.get('/', (req, res) => {
res.send('hello express');
});
app.use('/kakao', kakaoRouter);
app.listen(3065, () => {
console.log('서버 실행 중!');
});
(back/router)
router.post('/test', async (req, res, next) => {
//whic is kakao/test
try {
console.log('req.body:::::::::', req.body);
return res.status(200).json({
posts: 'h!!!!!!!!!!!!!!!!!',
});
} catch (error) {
next(error); // status 500
}
});
In order to view remote documents from an HTTP URL, cleartext network traffic support is required. On Android 9.0 (API level 28) or higher, cleartext support is disabled by default and apps targeting Android 9.0 or higher will need to add the android:usesClearTextTraffic="true" flag in the AndroidManifest.xml file.
If you are only working with HTTPS files, this flag is not required
Related
I make several requests from a React Native app to an API. Every request works fine both on iOS and Android except the DELETE method that does not work on Android. The call is correctly made, it goes through the API and the objects are deleted. But instead of getting the response, the call falls under the catch statement with [TypeError: Network request failed]. This does not happen in iOS.
Some people with the same problem were missing 'Content-Type': 'application/json' on the request headers which is not my case.
This is happening both locally, in testing and production stages (using an ip instead of localhost will do nothing).
The request is also successfully performed in Postman.
What can it be?
React Native 0.63.5
export const deleteApi = async (api: string, body?: any) => {
const userResponse = await getUserCredentials();
const authState = await getAuthState();
let response = await fetch(api, {
method: 'DELETE',
headers: await getHeaders(userResponse, authState),
body: JSON.stringify(body)
});
if (response.status === UNAUTHENTICATED_CODE)
response = await interceptor(response, userResponse, {
api: api,
method: 'DELETE',
body: body
});
return response;
};
leaveClass = async (
uuid: string,
onSuccess: () => void,
onFailure: (error: string) => void,
) => {
this.setLoading(true);
try {
const api = LEAVE_CLASS_API_PREFIX + uuid + LEAVE_CLASS_API_SUFFIX;
const response = await deleteApi(api);
if (response.status === SUCCESS_STATUS_CODE) {
onSuccess();
}
else {
const jsonResponse = await response.json();
if (jsonResponse.detail) onFailure(jsonResponse.detail);
else onFailure(translations.SOMETHING_WENT_WRONG);
}
} catch (error) {
console.log('leaveClass error: ', error);
}
this.setLoading(false);
};
You can use a network plugin for Flipper (https://fbflipper.com/docs/setup/plugins/network/), copy your request from it as a curl, and try to perform it from your terminal or postman. If it has the same error, the problem is not in React Native.
I am trying to set up a simple websocket connection in my React Native app. It is returning the following error in Android: {"isTrusted": false, "message": "Expected HTTP 101 response but was '401 Unauthorized'"}. The websocket is opening fine in iOS, and using a websocket connection that does not require my user to be authenticated works (my user is authenticated for this server but it still say I'm not authorized).
Here is the relevant code in my app:
useEffect(() => {
const ws = new WebSocket(`wss://${DOMAIN}/api/stream/all`)
ws.onopen = () => {
console.log('websocket open') // --> iOS
}
ws.onerror = e => {
console.log('error', e) // --> Android
}
}, [])
Changing it to this works on Android:
useEffect(() => {
const ws = new WebSocket(`wss://echo.websocket.events/.ws`)
ws.onopen = () => {
console.log('websocket open') // --> Android & iOS
}
ws.onerror = e => {
console.log('error', e)
}
}, [])
Any idea why authentication is not working? Is there some Android config that needs to be changed so the authentication that already happened for this domain on https gets to the websocket connection somehow?
I ended up changing it to this (added session cookie to headers for Android):
if (Platform.OS === 'ios') {
const ws = new WebSocket(`wss://${DOMAIN}/api/stream/all`)
ws.onopen = () => {
console.log('websocket open') // --> it works!
}
} else {
const ws = new WebSocket(`wss://${DOMAIN}/api/stream/all`, '', { headers: {Cookie: sessionCookie } })
ws.onopen = () => {
console.log('websocket open') // --> it works!
}
}
I got the session cookie from the response after the user logged in and kept that in state to be used in the websocket connection: const sessionCookie = res.headers.get('set-cookie'). This solution may not work for everyone if login doesn't work the same way for you, but it may help someone.
I'm testing the custom tab on Microsoft Teams app.
It correctly works on Desktop and iPhone, but it doesn't work on the Android mobile app.
The Android mobile debug screenshot
I'd like to know Why it's canceled?
The Android mobile couldn't open the app's web page.
I've captured the packet on the webserver when the android clicked the custom tab.
I could see only the server key exchange process, there is no client key exchange.
Android mobile
The iPhone was working properly and there was the client key exchange process.
iPohne
Please advise me.
Refferred to the below source code:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const env = require('node-env-file');
const path = require('path');
var cookieParser = require('cookie-parser');
env(path.join(__dirname, '../.env'));
const config = require('./config/config');
const { logger } = require('./logger/logger');
const fs = require('fs');
const https = require('https');
const nocache = require('nocache');
const app = express();
const api = require('./api');
app.use(morgan('combined'));
app.enable('trust proxy');
app.use(bodyParser.json({ limit: '5mb' }));
app.use(bodyParser.urlencoded({ limit: '5mb', extended: true, parameterLimit: 50000 }));
app.use(cors());
app.use(nocache());
app.use(cookieParser())
app.use('/api', api);
// Login Authenticate
if (config.loginMode === 'local') {
require('./passport')
}
if (process.env.NODE_ENV === 'production') {
// Vue Router
app.use(require('connect-history-api-fallback')());
app.use(express.static(path.join(__dirname, '../../dist')));
}
// MongoDB Connection
require('./db')
const options = {
key: fs.readFileSync('./keys/evm.ecstel.co.kr.key', 'utf8'),
cert: fs.readFileSync('./keys/evm_ecstel_co_kr.crt', 'utf8')
}
// Server Running
const server = https.createServer(options, app).listen(process.env.PORT || config.port, function () {
logger.info(`Server started on https`)
logger.info(`Server started on port ${config.port} in ${config.host}`)
})
Note: Total Ionic newbie here.
I have the following:
Ionic 5 (Capacitor) app with Angular 11.
Express backend (localhost:3000)
I can fetch data from an API call and display in the browser, but not on the emulated Android device. I don't know how to check for console errors in Android Studio.
This image can explain the situation better.
I think this is due to CORS. I tried to follow the Ionic page on this but no resolution.
Here is my Express code:
const express = require("express");
const cors = require("cors");
const app = express();
const port = 3000;
const allowedOrigins = [
"capacitor://localhost",
"ionic://localhost",
"http://localhost",
"http://localhost:8080",
"http://localhost:8100",
"http://192.168.2.25:8100",
];
// For parsing JSON in request body
app.use(express.json());
// MySQL connection details - for POC sake.
// In PROD, these are typically saved in .env variables
// Ref: https://www.linkedin.com/pulse/storing-database-credentials-securely-siddhesh-jog
var mysql = require("mysql");
var connection = mysql.createConnection({
host: "____________________________.us-east-2.rds.amazonaws.com",
user: "admin",
password: "*****************",
database: "poc",
});
const corsOptions = {
origin: (origin, callback) => {
if (allowedOrigins.includes(origin) || !origin) {
callback(null, true);
} else {
console.log(origin);
callback(new Error("Origin not allowed by CORS"));
}
},
};
// Enable preflight requests for all routes
app.options("*", cors(corsOptions));
// Connect to MySQL
connection.connect(function (err) {
if (err) throw err;
console.log("Connected!");
});
// Dashboard - GET
app.get("/dashboard", cors(corsOptions), (req, res) => {
rows = [];
connection.query(
"select label_id, value from poc_fct",
function (err, result) {
if (err) throw err;
res.json(result);
}
);
});
app.listen(port, () => {
console.log(`CORS-enabled web server listening at http://localhost:${port}`);
});
Any help will be greatly appreciated.
What finally worked for me was changing the API endpoint from http://localhost:3000/data to http://192.168.2.25:3000/data, where 192.168.2.25 is the local IP address of the host where the Express server is running.
Few notes for anyone else who might have this issue in the future:
This isn't a CORS issue. I commented out app.use(cors)
This isn't a HTTP/HTTPS issue
Changing the emulator's proxy to 10.0.2.2:3000 did not work
I am building an application and using firebase for the backend. I used react-native-firebase to use firebase in my application. I have developed a login cloud function
exports.login = functions.https.onCall((data, context) => {
console.log("data", data);
console.log("context", context);
return "Login successful";
});
On running npm run serve in the functions folder I am getting these configurations in my console.
Console output after running npm run serve inside functions folder for firebase
Also I have added the following code to connect to the cloud function from my android emulator running the application.
import functions from "#react-native-firebase/functions"
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleLogin = () => {
// console.log(email, password);
functions()
.useFunctionsEmulator("URL")
.httpsCallable("login")({ email, password })
.then((response) => {
alert(response);
});
}
for URL I have tried "http://localhost:5001/" as it is the port on which the functions emulator is listening
Port on which cloud functions is listening. But on running the application I am getting this error
Error on clicking login button in app console. I tried searching for the error but nothing relevant comes up. Any help will be appreciated.
These are my cloud functions that I have defined
exports.helloWorld = functions.https.onRequest((request, response) => {
functions.logger.info("Hello logs!", { structuredData: true });
response.send("Hello from Firebase!");
});
exports.signup = functions.https.onRequest((request, response) => {
console.log("request", request);
response.send("SignUp successfull");
});
exports.login = functions.https.onCall((data, context) => {
console.log("data", data);
console.log("context", context);
return "SignIn successfull";
});
I was able to work it out finally
const handleLogin = async () => {
functions().useFunctionsEmulator("http://localhost:5001")
const response = await functions().httpsCallable("login")({ email, password });
console.log("response", response);
}
This is all the code required to successfully call cloud function locally inside an emulator from your running android emulator.