Dart servers refusing connection in local network - dart

I have Dart running on Mac Mavericks and Ubuntu Linux. I am just getting started;and, none of the examples will function through my local network. When I install a server on Ubuntu and try to access with the mac- nothing happens. When I try to access from Ubunutu, I get a "java.net Connection Refused error" Same goes for Curl on either machine, (connection refused). All of the samples run fine as client/server from localhost. Neither, Client apps or Browsers are able to connect. All other servers/clients working normally in the home network. Firewall is ok, and I double checked port numbers. There are no conflicting servers on the desired ports. I tried about 5 different scripts from the Dart site and others, each with a CORS function, but nothing connects, including the sample below, SimpleServer
-Github
Sample Code
/* A simple web server that responds to **ALL** GET requests by returning
* the contents of data.json file, and responds to ALL **POST** requests
* by overwriting the contents of the data.json file
*
* Browse to it using http://localhost:8080
*
* Provides CORS headers, so can be accessed from any other page
*/
import 'dart:io';
final HOST = "127.0.0.1"; // eg: localhost
final PORT = 8080;
final DATA_FILE = "data.json";
void main() {
HttpServer.bind(HOST, PORT).then((server) {
server.listen((HttpRequest request) {
switch (request.method) {
case "GET":
handleGet(request);
break;
case "POST":
handlePost(request);
break;
case "OPTIONS":
handleOptions(request);
break;
default: defaultHandler(request);
}
},
onError: printError);
print("Listening for GET and POST on http://$HOST:$PORT");
},
onError: printError);
}
/**
* Handle GET requests by reading the contents of data.json
* and returning it to the client
*/
void handleGet(HttpRequest req) {
HttpResponse res = req.response;
print("${req.method}: ${req.uri.path}");
addCorsHeaders(res);
var file = new File(DATA_FILE);
if (file.existsSync()) {
res.headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
file.readAsBytes().asStream().pipe(res); // automatically close output stream
}
else {
var err = "Could not find file: $DATA_FILE";
res.write(err);
res.close();
}
}
/**
* Handle POST requests by overwriting the contents of data.json
* Return the same set of data back to the client.
*/
void handlePost(HttpRequest req) {
HttpResponse res = req.response;
print("${req.method}: ${req.uri.path}");
addCorsHeaders(res);
req.listen((List<int> buffer) {
var file = new File(DATA_FILE);
var ioSink = file.openWrite(); // save the data to the file
ioSink.add(buffer);
ioSink.close();
// return the same results back to the client
res.add(buffer);
res.close();
},
onError: printError);
}
/**
* Add Cross-site headers to enable accessing this server from pages
* not served by this server
*
* See: http://www.html5rocks.com/en/tutorials/cors/
* and http://enable-cors.org/server.html
*/
void addCorsHeaders(HttpResponse res) {
res.headers.add("Access-Control-Allow-Origin", "*");
res.headers.add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.headers.add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
}
void handleOptions(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
print("${req.method}: ${req.uri.path}");
res.statusCode = HttpStatus.NO_CONTENT;
res.close();
}
void defaultHandler(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
res.statusCode = HttpStatus.NOT_FOUND;
res.write("Not found: ${req.method}, ${req.uri.path}");
res.close();
}
void printError(error) => print(error);
data.json
{
"language":"DART",
"targets":["dartium","javascript","Android?"],
"website":{
"homepage":"www.dartlang.org",
"api":"api.dartlang.org"
}
}

I think this is because the Dart server is configured to listen to only the clients on the localhost. You need to make it to listen to any IPv4/v6 client in order to receive any response from the server over the network.
Change the line final HOST = "127.0.0.1"; to final HOST = InternetAddress.ANY_IP_V4;
or final HOST = InternetAddress.ANY_IP_V6;
It should make it work.

Related

Ionic 5 - API request working on browser, not on emulated IOS

I have this Ionic 5/Capacitor app, which I'm making an API call to a local server from, that server running on docker at localhost:3000. When I test from the browser, the request is made fine. From Postman it requests fine, too. In my XCode logs the emulator, I see this
[error] - ERROR {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"http://localhost:3000/pins","ok":false,"name":"HttpErrorResponse","message":"Http failure response for http://localhost:3000/pins: 0 Unknown Error","error":{"isTrusted":true}}
The really interesting part, is that I'm running Fiddler to monitor the request as it's made. Fiddler gets a 200 as well, I can even see the response data. So, Fiddler sees the proper network call, but then my Ionic app gets that error. That makes me feel like it's an Ionic/Emulator/IOS problem, but I don't have enough familiarity with Ionic to know right off the bat what it is.
Here's the code responsible for making the request:
ngOnInit() {
const request = this.http.get('http://localhost:3000/pins');
this.refresh$.subscribe(
(lastPos: { latitude?: any; longitude?: number }) => {
request.subscribe(data => {
if (data) {
this.addMarkersToMap(data, lastPos);
}
});
}
);
}
And the HTTPClient imported in the constructor is from Angular:
import { HttpClient } from '#angular/common/http';
I ended up having to use this package, doing a check on if I'm on mobile or not.
https://ionicframework.com/docs/native/http/
Try with this :
const request = this.http.get('http://localhost:3000/pins', { observe: 'response', withCredentials: true });
Solution 2 : capacitor.config.json
"server": {
"hostname": "localhost", (maybe try precising the port number too)
}
Solution 3 : On your Express server (from https://ionicframework.com/docs/troubleshooting/cors)
const express = require('express');
const cors = require('cors');
const app = express();
const allowedOrigins = [
'capacitor://localhost',
'ionic://localhost',
'http://localhost',
'http://localhost:8080',
'http://localhost:8100'
];
// Reflect the origin if it's in the allowed list or not defined (cURL, Postman, etc.)
const corsOptions = {
origin: (origin, callback) => {
if (allowedOrigins.includes(origin) || !origin) {
callback(null, true);
} else {
callback(new Error('Origin not allowed by CORS'));
}
}
}
// Enable preflight requests for all routes
app.options('*', cors(corsOptions));
app.get('/', cors(corsOptions), (req, res, next) => {
res.json({ message: 'This route is CORS-enabled for an allowed origin.' });
})
app.listen(3000, () => {
console.log('CORS-enabled web server listening on port 3000');
});

How To Consume Stream HTTP Response In Java?

I'm having trouble trying to consume the Response of an HTTP Endpoint which Streams real-time events continously. It's actually one of Docker's endpoints: https://docs.docker.com/engine/api/v1.40/#operation/SystemEvents
I am using Apache HTTP Client 4.5.5 and it just halts indefinitely when I try to consume the content InputStream:
HttpEntity entity = resp.getEntity();
EntityUtils.consume(entity);//it just hangs here.
//Even if I don't call this method, Apache calls it automatically
//after running all my ResponseHandlers
Apparently, it can be done by using JDK's raw URL: Stream a HTTP response in Java
But I cannot do that since local Docker communicates over a Unix Socket which I only managed to configure in Apache's HTTP Client with a 3rd party library for Unix Sockets in Java.
If there is a smarter HTTP Client library which I could switch to, that would also be an option.
Any ideas would be greatly appreciated. Thank you!
I managed to solve this issue by generating an infinite java.util.stream.Stream of JsonObject from the response InputStream (I know the json reading part is not the most elegant solution but there is no better way with that API and also, Docker doesn't send any separator between the jsons).
final InputStream content = response.getEntity().getContent();
final Stream<JsonObject> stream = Stream.generate(
() -> {
JsonObject read = null;
try {
final byte[] tmp = new byte[4096];
while (content.read(tmp) != -1) {
try {
final JsonReader reader = Json.createReader(
new ByteArrayInputStream(tmp)
);
read = reader.readObject();
break;
} catch (final Exception exception) {
//Couldn't parse byte[] to Json,
//try to read more bytes.
}
}
} catch (final IOException ex) {
throw new IllegalStateException(
"IOException when reading streamed JsonObjects!"
);
}
return read;
}
).onClose(
() -> {
try {
((CloseableHttpResponse) response).close();
} catch (final IOException ex) {
//There is a bug in Apache HTTPClient, when closing
//an infinite InputStream: IOException is thrown
//because the client still tries to read the remainder
// of the closed Stream. We should ignore this case.
}
}
);
return stream;

Volley android "javax.net.ssl.SSLHandshakeException: Handshake failed"

Hi I'm rebuilding a API call using volley library
this is my test code to send XML data and receive xml response (I just need to successfully receive response in string format)
String url ="https://prdesb1.singpost.com/ma/FilterOverseasPostalInfo";
final String payload = "<OverseasPostalInfoDetailsRequest xmlns=\"http://singpost.com/paw/ns\"><Country>AFAFG</Country><Weight>100</Weight><DeliveryServiceName></DeliveryServiceName><ItemType></ItemType><PriceRange>999</PriceRange><DeliveryTimeRange>999</DeliveryTimeRange></OverseasPostalInfoDetailsRequest>\n";
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Do something with the response
Log.v("tesResponse","testResponseS");
Log.v("response",response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Handle error
Log.v("tesResponse","testResponseF");
Log.v("error",error.toString());
}
}
){
#Override
public String getBodyContentType() {
return "application/xml; charset=" +
getParamsEncoding();
}
#Override
public byte[] getBody() throws AuthFailureError {
String postData = payload;
try {
return postData == null ? null :
postData.getBytes(getParamsEncoding());
} catch (UnsupportedEncodingException uee) {
// TODO consider if some other action should be taken
return null;
}
}
};
// stringRequest.setRetryPolicy(new DefaultRetryPolicy(5*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
stringRequest.setRetryPolicy(new DefaultRetryPolicy(0, 0, 0));
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
I have test the String url and the payload on POSTMAN and give successful result. But don't know why my android app give this error
08-22 19:44:24.335 16319-16518/com.example.victory1908.test1 D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 08-22 19:44:24.355 16319:16319 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64eac0, tid 16319
[ 08-22 19:44:24.399 16319:16518 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64edc0, tid 16518
08-22 19:44:24.410 16319-16518/com.example.victory1908.test1 I/OpenGLRenderer: Initialized EGL, version 1.4
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/tesResponse: testResponseF
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/error: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed
Just notice problem only with API 23+ (android 6.0 and above) API 22 is working fine!
I have tried set the retry policy but does not work. Anyone know what wrong with the code. Thanks in advance

Dart: Processing an uploaded file on the server from client request

I am trying to process images uploaded from client on the server but am receiving the following errors. Am I processing the httpRequest wrong?
Unhandled exception:
Uncaught Error: HttpException: Connection closed while receiving data, uri = /api/upload
/// Client Code (dart file) (Works # sending request)
sendData(dynamic data) {
final req = new HttpRequest();
FormData fd = new FormData();
fd.append('uploadContent', data);
fd.appendBlob('uploadContent', data);
req.open("POST", "http://127.0.0.1:8080/api/upload", async: true);
req.send(fd);
req.onReadyStateChange.listen((Event e) {
if (req.readyState == HttpRequest.DONE &&
(req.status == 200 || req.status == 0)) {
window.alert("upload complete");
}
});
}
InputElement uploadInput = document.querySelector('#sideBar-profile-picture');
uploadInput.onChange.listen((Event event){
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
File file = files[0];
FileReader reader = new FileReader();
reader.onLoad.listen((e) {
print('results: ${reader.result}');
sendData(reader.result);
});
reader.readAsArrayBuffer(file);
}
});
I have a small server listening for the request (/api/upload) and calling handleUploadRequest with the httpRequest being passed in as the param.
Server code (This is where I am stuck)
Future<Null> handleUploadRequest(final HttpRequest httpRequest) async {
httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d)).then((builder) {
var data = builder.takeBytes();
print('bytes builder: ${data}');
});
}
I am trying to read the data so that I can store it on a cdn but never get a chance to since the connection always gets closed while receiving the data.
Any help on being able to complete this is appreciated. Been at this for the past couple days:/
It is hard to tell when/if you close the httpRequest. If you are doing it right after handleUploadRequest returns, it will indeed close the connection as you are not waiting for httpRequest.fold() to complete. Adding await as shown below and making sure to call httpRequest.close() after this function complete asynchronously should work
Future<Null> handleUploadRequest(final HttpRequest httpRequest) async {
await httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d)).then((builder) {
var data = builder.takeBytes();
print('bytes builder: ${data}');
});
}
(FYI) I have a similar code that works when testing with curl and uploading a file

Dart mailer returning success or error to client

I'm learning dart and have created a simple contact form - based on the forms tutorial on the dart site, using mailer to send a mail.
So far so good - the client post the message, the server picks up the post data, creates an envelope and sends the mail... but I want to display a comforting message to the person filling out the form, or warn them if it were not sent.
The problem is that the http response is sent before the future that sends the email is completed -
Chris Storm talks about using completers to solve this problem, I think - here: testing error conditions with dart and again in a chapter in Dart for Hipsters, but i am finding it hard to work out how to apply it here.
Here is the complete server code - the comments in the sendMail function show the problem.
import 'dart:io';
import 'dart:convert';
import 'package:mailer/mailer.dart';
final HOST = '127.0.0.1'; // eg: localhost
final PORT = 4040; // a port, must match the client program
void main() {
HttpServer.bind(HOST, PORT).then(gotMessage, onError: printError);
}
void gotMessage(_server) {
_server.listen((HttpRequest request) {
switch (request.method) {
case 'POST':
handlePost(request);
break;
case 'OPTIONS':
handleOptions(request);
break;
default: defaultHandler(request);
}
},
onError: printError); // .listen failed
print('Listening for GET and POST on http://$HOST:$PORT');
}
/**
* Handle POST requests
*
*/
void handlePost(HttpRequest req) {
HttpResponse res = req.response;
print('${req.method}: ${req.uri.path}');
addCorsHeaders(res);
req.listen((List<int> buffer) {
// Create a new string from the characters in the buffer and convert this into a map
Map postData = JSON.decode(new String.fromCharCodes(buffer));
res.write(sendMail(postData));
res.close();
},
onError: printError);
}
/**
* Add Cross-site headers to enable accessing this server from pages
* not served by this server
*
* See: http://www.html5rocks.com/en/tutorials/cors/
* and http://enable-cors.org/server.html
*/
void addCorsHeaders(HttpResponse res) {
res.headers.add('Access-Control-Allow-Origin', '*, ');
res.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.headers.add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}
void handleOptions(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
print('${req.method}: ${req.uri.path}');
res.statusCode = HttpStatus.NO_CONTENT;
res.close();
}
void defaultHandler(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
res.statusCode = HttpStatus.NOT_FOUND;
res.write('Not found: ${req.method}, ${req.uri.path}');
res.close();
}
void printError(error) => print(error);
sendMail(postData) {
String sentMsg = 'I am waiting for a result to report'; //initialised value
var options = new GmailSmtpOptions()
..username = 'my.mailt#gmail.com' //shove real values in here to test
..password = 'my_password';
var transport = new SmtpTransport(options);
// Create the envelope to send.
var envelope = new Envelope()
..fromName = postData['name']
..from = postData['fromEmail']
..recipients = ['the_recipient#somedomain.com']
..subject = 'Message from contact form'
..text = postData['contactMessage'];
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' ) //this will not be returned...
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e'); // nor will this
return sentMsg; // Sadly the initial value will be returned as the future (transport.send) will not have completed
}
If I get it right, you want to send a response based on the result on transport.send(). If so you can just return it, like
return transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
Or using Completer
var c = new Completer();
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.then(c.complete)
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
return c.future;
And since you are returning a Future, you have to change how you send your response to client, from
res.write(sendMail(postData));
res.close();
to
sendMail(postData)
.then((result) {
res.write(result);
res.close();
});
Your code doesn't look bad :)
As far as I can see there isn't missing much (haven't tried to execute it though).
request.response.write('Hello, world');
request.response.close();
either in handlePost() (where you have req available or
return the result that you want to return to the client from handlePost() to gotMessage() and add above lines there.
Also take a look at An Introduction to the dart:io Library - Writing web servers

Resources