I am persistently getting following error on connecting to test server using RippleAPI for Javascript:
[ConnectionError(Error: connect() timed out after 2000 ms. If your internet connection is working, the rippled server may be blocked or inaccessible.)]
However, if I try to get balance from curl, it works:
curl 'https://testnet.data.api.ripple.com/v2/accounts/rwAVpkGNU9Shn63EpFq7ju1tr89SsSBwHz/balances?currency=XRP'
Code snippet below:
'use strict';
const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI({
server: 'wss://s.altnet.rippletest.net:51233' // Public rippled server
});
api.connect().then(() => {
/* begin custom code ------------------------------------ */
const myAddress = 'rwAVpkGNU9Shn63EpFq7ju1tr89SsSBwHz';
console.log('getting account info for', myAddress);
return api.getAccountInfo(myAddress);
}).then(info => {
console.log(info);
console.log('getAccountInfo done');
/* end custom code -------------------------------------- */
}).then(() => {
return api.disconnect();
}).then(() => {
console.log('done and disconnected.');
}).catch(console.error);
timeout param doesn't seem to work even if I suggest;
use:
api.connection._config.connectionTimeout = 3e4;
Related
I have an app with divided code (client / server). On the client side, I'd like socket io to attempt multiple URLs (one at a time) until it connects successfully.
Here's my code:
const BAD_HOST = "http://localhost:8081";
const LOCAL_HOST = "http://localhost:8080";
const SOCKET_CONFIG = {
upgrade: false,
transports: ["websocket"],
auth: { ... }, // Trimmed for brevity
extraHeaders: { ... }, // Trimmed for brevity
};
let socket = io(BAD_HOST, SOCKET_CONFIG); // This connects fine when I use LOCAL_HOST
socket.on("connect_error", (err) => {
console.log(err);
socket = io(LOCAL_HOST, SOCKET_CONFIG); // DOES NOT WORK
});
socket.on("connect", () => { ... } // Trimmed for brevity
In short, when I try to reassign the value for socket to a new io connection, it seems to retain the old, failed connection. My browser continues to throw 'connect_error' messages from the bad url:
WebSocket connection to 'ws://localhost:8081/socket.io/?EIO=4&transport=websocket' failed:
I checked but couldn't find any official documentation on this question.
I think an approach is already discussed here:
https://stackoverflow.com/a/22722710/656708
Essentially you have an array of URLs, which in your case would be:
const socketServerURLs = ["http://localhost:8081","http://localhost:8080"];
and then iterate over them, trying to initiate a socket connection, like this:
// something along these lines
socketServerURLs.forEach((url) => {
// ...
socket.connect(url, socketConfiguration, (client) => {});
// ...
}
Then again, I don't know what a BAD_HOST entails. Assuming that you mean that a connection to that host failed, how would you know that without actually trying to connect to it?
I am trying to log my GPS coordinates in a React-Native expo application.
The background task runs successfully and consoles log the coordinates.
Now I want to send them to my server.
For example a post request to /api/mylocation?lon=123&lat=345
I tried a regular fetch method but I get a timeout error.
regular meaning fetch(url,{ method:'POST' etc}) (I know how to perform a basic fetch)
How can I solve this? I suspect it has to do with async and all that.
const LOCATION_TRACKING = 'location-tracking';
const startLocationTracking = async () => {
console.log('startLocationTracking');
await Location.startLocationUpdatesAsync(LOCATION_TRACKING, {
accuracy: Location.Accuracy.Highest,
timeInterval: 10000,
distanceInterval: 0,
});
const hasStarted = await Location.hasStartedLocationUpdatesAsync(
LOCATION_TRACKING
);
console.log('tracking started?', hasStarted);
};
TaskManager.defineTask(LOCATION_TRACKING, async ({ data, error }) => {
console.log('running task:', data, error);
// send_driver_location()
if (error) {
console.log('LOCATION_TRACKING task ERROR:', error);
return;
}
if (data) {
const { locations } = data;
let lat = locations[0].coords.latitude;
let long = locations[0].coords.longitude;
console.log(
`${new Date(Date.now()).toLocaleString()}: ${lat},${long}`
);
// add a fetch method here?
// fetch(url, {...}
}
});
Obviously, this will be helpful when I want to fetch tokens from my server for authentication purposes also.
I have script to move data from one platform to another. The source db allows only 100 records to be fetched in a single request. So I created a routine to fetch by batches of 100 which works fine I guess.
Now I try to process each records of 100 and do the necessary transformations (which involves axios call to get certain data) and create a record in firebase firestore.
Now when I run this migration in firebase express node, I get socket hang up ECONNRESET.
I know this is caused by wrong handling of promises.
Here is what my code looks like:
import { scrollByBatches } from "../helpers/migrations/apiScroll";
import { createServiceLocation } from "../helpers/locations";
const mapServiceLocationData = async (serviceLocation: any, env: string) => {
try {
const migratedServiceLocation: any = {
isMigrated: true,
id: serviceLocation._id,
};
if (serviceLocation.list?.length) {
await Promise.all(serviceLocation.ids.map(async (id: string) => {
const { data } = await dbEndPoint.priceMultiplier({ id }); // error says socket hangup on this call
let multiplierUnit;
let serviceType;
if (data.response._id) {
multiplierUnit = data.response;
const result = await dbEndPoint.serviceType({ id: multiplierUnit.service_custom_service_type }); // error says socket hangup on this call
if (result.data.response._id) {
serviceType = result.data.response.type_text;
migratedServiceLocation.logs = [...multiplierUnit.history_list_text, ...migratedServiceLocation.logs];
}
}
}));
}
await createServiceLocation(migratedServiceLocation); // create record in destination db
} catch (error) {
console.log("Error serviceLocation: ", serviceLocation._id, JSON.stringify(error));
}
return null; // is this even necessary?
};
export const up = async () => {
try {
// get 100 docs from source db => process it.. => fetch next 100 => so on...
await scrollByBatches(dbEndPoint.serviceLocation, async (serviceLocations: any) => {
await Promise.all(
serviceLocations.map(async (serviceLocation: any) => {
await mapServiceLocationData(serviceLocation);
})
);
}, 100);
} catch (error) {
console.log("Error", JSON.stringify(error));
}
return null; // is this even necessary?
};
The error I get in firebase functions console is:
For clarity on how the fetch by batches looks like:
const iterateInBatches = async (endPoint: any, limit: number, cursor: number, callback: any, resolve: any, reject: any) => {
try {
const result = await endPoint({ limit, cursor });
const { results, remaining }: any = result.data.response;
if (remaining >= 0) {
await callback(results);
}
if ((remaining)) {
setTimeout(() => {
iterateInBatches(endPoint, limit, (cursor + limit), callback, resolve, reject);
}, 1000); // wait a second
} else {
resolve();
}
} catch (err) {
reject(err);
}
};
export const scrollByBatches = async (endPoint: any, callback: any, limit: number, cursor: number = 0) => {
return new Promise((resolve, reject) => {
iterateInBatches(endPoint, limit, cursor, callback, resolve, reject);
});
};
What am I doing wrong? I have added comments in the code sections for readability.
Thanks.
There are two cases when socket hang up gets thrown:
When you are a client
When you, as a client, send a request to a remote server, and receive no timely response. Your socket is ended which throws this error. You should catch this error and decide how to handle it: whether to retry the request, queue it for later, etc.
When you are a server/proxy
When you, as a server, perhaps a proxy server, receive a request from a client, then start acting upon it (or relay the request to the upstream server), and before you have prepared the response, the client decides to cancel/abort the request.
I would suggest a number of possibilities for you to try and test that might help you solve your issue of ECONNRESET :
If you have access to the source database, you could try looking
there for some logs or metrics. Perhaps you are overloading the
service.
Quick and dirty solution for development: Use longjohn, you get long
stack traces that will contain the async operations. Clean and
correct solution: Technically, in node, whenever you emit an 'error'
event and no one listens to it, it will throw the error. To make it
not throw, put a listener on it and handle it yourself. That way you
can log the error with more information.
You can also set NODE_DEBUG=net or use strace. They both provide you
what the node is doing internally.
You could restart your server and run the connection again, maybe
your server crashed or refused the connection most likely blocked by
the User Agent.
You could also try running this code locally, instead of in cloud
functions to see if there is a different result. It's possible that
the RSG/google network is interfering somehow.
You can also have a look at this GitHub issue and stackoverflow
thread to see the common fixes for the ECONNRESET issue and see if
those help resolve the issue.
I do web development with an Android (not rooted) phone and look for a method to show the browser (Chrome or Firefox) console messages.
Neither Android Chrome nor Firefox has web inspector/console and I don't found Firefox (working) add-on.
Update: I can't connect my phone to a computer (ADB, Chrome remote tool... are unavailable).
Anybody can hint me a viable solution?
Try https://github.com/liriliri/eruda, very good approximation of Dev Tools.
All you need to do is add this snippet on top of the page:
<script src="//cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
Edit
A practical solution can be found at https://stackoverflow.com/a/60106504/1025638
Original (self) answer
I don't found a "just work" solution to solve my problem so I made a short tool to send the logs and errors from the browser to a backend server.
It uses a Proxy around window.console object and implements the function window.onerror to post the messages to the server.
I structured the code to use it as an expressjs middleware for reusability.
It isn't perfect and it may not be compatible with
all browsers, but it really helps if there isn't dev tools in a browser.
Anyone can test it through repl.it.
// Use this module as middleware with expressjs compatible server:
//
// In the server:
// consoleWrapperMiddleware(basePath, app)
// basePath: URL path to send browser messages
// app: expressjs application reference
// return: nothing
//
// In the html page:
// <script src="basePath" />
// basePath: URL path to send browser messages
function consoleWrapper(oldConsole, oldOnerror, serverUrl) {
function _post(log) {
const req = new XMLHttpRequest()
req.open('POST', serverUrl, true)
req.setRequestHeader('Content-Type', 'application/json')
req.send(JSON.stringify(log))
}
const console = new Proxy(oldConsole, {
get: (target, propKey, receiver) => {
const origMethod = target[propKey]
return function (...args) {
if (origMethod === undefined) {
const message = 'unknown console method: '+propKey
_post({ level: 'wrap', message: [message]})
return message
}
else {
let result = origMethod.apply(this, args)
_post({ level: origMethod.name, message: args })
return result
}
}
}
})
const onerror = function(msg, url, line, col) {
if (typeof oldOnerror === 'function')
oldOnerror(arguments)
const content = [ msg, url+':'+line+':'+col ]
_post({ level: 'js-err', message: content })
}
return [ console, onerror ]
}
function consoleWrapperMiddleware(basePath, app) {
app.get(basePath, (req, res) => {
res.status(200).send('[ window.console, window.onerror ] = '+consoleWrapper.toString()+'(window.console, window.onerror, location.protocol.concat("//").concat(location.host).concat("'+basePath+'"))')
console.log('Console wrapper sent')
})
app.post(basePath, (req, res) => {
let body = []
req.on('data', (chunk) => {
body.push(chunk)
}).on('end', () => {
body = Buffer.concat(body).toString()
const logMsg = JSON.parse(body)
console.log('['+logMsg.level+']', ...logMsg.message)
res.writeHead(200)
res.end()
})
})
console.log('Log server listening from',basePath)
}
module.exports = consoleWrapperMiddleware
In my frontend I'm using the sails.io.js wrapper. I'm trying to connect to my backend and listen for notifications. This works fine when I'm using blast to send out to all connected sockets, but broadcasting does nothing.
However, joining a room seems to work as the callback from the join function gets executed without any errors.
The frontend part:
import * as socketIoClient from 'socket.io-client'
import * as sailsIo from 'sails.io.js'
const io = sailsIo(socketIoClient)
io.sails.url = 'localhost:1337'
io.sails.environment = process.env.NODE_ENV || 'development'
io.sails.useCORSRouteToGetCookie = false
io.socket.get('/notification/join', (data, jwRes) => {
console.log('Server responded with status code ' + jwRes.statusCode + ' and data: ', data);
})
io.socket.on('notification', data => {
console.log('Server says: ', data);
})
My Sails Controller:
export const join = async (req, res) => {
if (!req.isSocket) {
return res.badRequest();
}
// Join a user specific notification room
sails.sockets.join(req, 'notification', error => {
if (!error) console.log('Everything went fine')
return res.send('Connected') // this works so far
})
// Send events each second
setInterval(() => {
sails.sockets.broadcast('notification', { data: 'Real notification' }) // This never works
sails.sockets.blast('notification', {data: 'BLAST'}) // This works perfectly
}, 1000)
}
Any suggestion on what goes wrong? Like I said, the callback of joining the room gets executed without an error, also the blast call works fine and the frontend is able to receive the message.