Why can I not access this Rust simple server from the Internet? - web-services

I have the following server:
extern crate simple_server;
use crate::simple_server::*;
fn main() {
let host = "127.0.0.1";
let port = "7878";
let server = Server::new(|request, mut response| {
println!("Request received. {} {}", request.method(), request.uri());
println!("=============BODY=================");
let mut v: Vec<u8> = Vec::new();
for b in request.body().iter() {
v.push(*b);
}
let body_as_str = String::from_utf8(v);
match body_as_str {
Ok(strr) => println!("{}", strr),
Err(e) => println!("{}", e),
}
//ROUTING
match (request.method(), request.uri().path()) {
(&Method::GET, "/") => {
Ok(response.body("<h1>Hi!</h1><p>Hello hacker!</p>".as_bytes().to_vec())?)
}
(&Method::POST, "/") => {
Ok(response.body("<h1>Hi!</h1><p>Hello hacker!</p>".as_bytes().to_vec())?)
}
(_, _) => {
response.status(StatusCode::NOT_FOUND);
Ok(response.body("<h1>404</h1><p>Not found!<p>".as_bytes().to_vec())?)
}
}
});
println!("Listening on: {} port {}", host, port);
server.listen(host, port);
}
I'm not able to access the page going to http://my_server_ip:7878/ from the Internet.
I have my server's firewall setup to allow all on 7878 and also, other simple servers work just fine when configured to listen on that port, which makes me think this is a code problem with my specific Rust application. An example of a server which works fine is static-server on npm.
However, when I test this application on my build machine by going to "127.0.0.1:7878", it works fine.

By using "127.0.0.1" for the host variable you denied any connection that doesn't come from this address. Use "0.0.0.0", the unspecified address, for example.

Related

How to setup a Sockect.io server in aws EC2 and then connect remotely to the server?

Good morning.
I created a simple server for a chat using Socket.io. In the next screen, which would be the client interface, you can see some inputs
In localhost, in my computer works fine. Here are the logs messages from the server:
I uploaded the server to an EC2 instance with ubuntu. And it work fine, in the same way
Logs from the server in EC2
The main problem is when I tried to connect from my computer to the Socket.io server in EC2. I got this error from my client side file in my computer:
socket.io.js:3888 GET
https://mydomain:80/socket.io/?EIO=4&transport=polling&t=NQB59WG
Here is my server code:
const path = require("path");
const express = require("express");
const socketio = require("socket.io");
const app = express();
app.set('port', 3000);
//static files
app.use(express.static(path.join(__dirname, "public")));
//start the server
const server = app.listen(app.get('port'), () => {
console.log("server on port", app.get('port'));
});
const io = socketio(server);
//websockects
io.on('connection', (socket) => {
console.log("new connection " + socket.id);
socket.on('chat:message', (data) => {
console.log(data);
io.sockets.emit("chat:server", data);
});
socket.on('chat:typing', (data) => {
console.log(data);
socket.broadcast.emit("chat:typing", data);
});
});
Here is my client code:
const socket = io("https://domain:80");
//dom elements
let message = document.getElementById("message");
let username = document.getElementById("username");
let btn = document.getElementById("button");
let output = document.getElementById("output");
let actions = document.getElementById("actions");
btn.addEventListener('click', function() {
console.log({
username: username.value,
message: message.value
});
socket.emit("chat:message", {
username: username.value,
message: message.value
});
});
message.addEventListener('keypress', function() {
socket.emit("chat:typing", username.value);
});
socket.on("chat:server", function(data) {
console.log(data);
actions.innerHTML = "";
output.innerHTML += "<p><strong>" + data.username + "</strong>: " + data.message + " </p>";
});
socket.on("chat:typing", function(data) {
console.log(data);
actions.innerHTML = "<p><strong>" + data + "</strong> esta escribiendo </p>";
});
And here are the instance inboud rules for ports:
When i tried to connect from my computer to the EC2 instance, I tried with several ways to connect, like this:
const socket = io("https://url.org:80");
const socket = io("https://url.org");
const socket = io("https://ipaddres:80");
const socket = io("https://ipaddres");
const socket = io("ec2-xxxx.compute-1.amazonaws.com");
const socket = io("ec2-xxxx.compute-1.amazonaws.com:80");
Nothing works, Any help?
In my case the solution was to do two things:
I use my domaind without port
const socket = io("https://url.org");
The EC2 Instance work with nginx, I modified the header to add this property:
Access-Control-Allow-Origin: *
And it worked

esp8266 websocket server and sodcket.io client in angular 7

I am using esp8266 to run my websocket server and angular 7 to run socket.io to run websocket client. When I run the angular application. The logs in Arduino shows Disconnected!. I am not sure what is causing this.
following is the angular side code for client.
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs/Rx';
import { environment } from 'src/environments/environment';
#Injectable()
export class SocketServiceService {
private socket;
constructor() { }
connect(): Rx.Subject<MessageEvent> {
this.socket = io('ws://192.168.43.155:81');
console.log("created server")
let observable = new Observable(observer => {
this.socket.on('message', (data) => {
console.log("Received message from Websocket Server")
observer.next(data);
})
return () => {
this.socket.disconnect();
}
});
let observer = {
next: (data: Object) => {
this.socket.emit('message', JSON.stringify(data));
console.log("msg emited"+ data);
},
};
return Rx.Subject.create(observer, observable);
}
}
this is esp8266 code
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(81);
#define USE_SERIAL Serial1
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
break;
case WStype_BIN:
USE_SERIAL.printf("[%u] get binary length: %u\n", num, length);
hexdump(payload, length);
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
webSocket.begin();
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}
please Suggest what might be going wrong, Any pointers will be helpful.
It's a lot to ask for someone to actually try to debug this (to do so, I'd have to create an Angular project using your Angular code, and also set up an ESP8266 sketch using your Arduino code), so I'm not going to try, but here's a couple of suggestions:
Try setting up a WebSocket server in Node, using the example code in the socket.io-client documentation. If that works, then you've narrowed the problem down to the ESP8266 code. If it fails in the same way, then you have a problem in your Angular client.
If the problem is in your Angular code, I'd suggest using the rsjx WebSocketSubject class. It gives you a fully configured WebSocket client, works really well, and would eliminate your low-level websocket client code.
Here's an example of connecting to the WebSocket, subscribing to inbound messages, and sending an outbound message:
connect() {
this.webSocket = webSocket(environment.chatUrl);
this.subscription = this.webSocket.subscribe(msg => {
console.log('got message: ' + msg);
},
err => {
this.setDisconnected();
console.log('err!', err);
},
() => {
console.log('websocket closed'));
this.setDisconnected();
}
);
this.webSocket.next({
name: this.name
});
}
and here's sending a message:
sendMessage(msg: string) {
if (this.connected) {
this.webSocket.next(msg);
}
}
and here's disconnecting:
private disconnect() {
if (this.subscription) {
this.webSocket.complete();
this.subscription.unsubscribe();
this.subscription = undefined;
this.setDisconnected();
}
}

automatically register GCE instances in google cloud DNS?

How do I have my GCE instances register with an internal GCP DNS zone? Is there a built in way to do this?
Edit: looks like I can do this https://cloud.google.com/sdk/gcloud/reference/dns/record-sets/transaction/add
For a full guide on this, check out Google Cloud Platform in Action.
You can use the Cloud DNS API to register the instance, which is pretty straight forward. I think the part that isn't well documented would be how to get the right IP address and such in a start-up script.
The following code snippet has some helpers in Node.js that pull down instance names, zones, and IP addresses which you can then use to register with Cloud DNS.
const request = require('request');
const metadataUrl = 'http://metadata.google.internal/computeMetadata/v1/';
const metadataHeader = {'Metadata-Flavor': 'Google'};
const getMetadata = (path) => {
const options = {
url: metadataUrl + path,
headers: metadataHeader
};
return new Promise((resolve, reject) => {
request(options, (err, resp, body) => {
resolve(body) ? err === null : reject(err);
});
});
};
const getInstanceName = () => {
return getMetadata('instance/name');
};
const getInstanceZone = () => {
return getMetadata('instance/zone').then((data) => {
const parts = data.split('/');
return parts[parts.length-1];
})
};
const getInstanceIp = () => {
const path = 'instance/network-interfaces/0/access-configs/0/external-ip';
return getMetadata(path);
};
const getInstanceDetails = () => {
const promises = [getInstanceName(), getInstanceZone(), getInstanceIp()];
return Promise.all(promises).then((data) => {
return {
name: data[0],
zone: data[1],
ip: data[2]
};
});
};
So then in Cloud DNS, you could register using these helpers by doing something like the following (note this was written using an early version of the DNS library -- you can install it by running npm install #google-cloud/dns#0.6.1).
const dns = require('#google-cloud/dns')({
projectId: 'your-project-id'
});
const zone = dns.zone('mydomain-dot-com');
getInstanceDetails().then((details) => {
return zone.record('a', {
name: [details.name, details.zone].join('-') + '.mydomain.com.',
data: details.ip,
ttl: 86400
});
}).then((record) =>{
return zone.createChange({add: record});
}).then((data) => {
const change = data[0];
console.log('Change created at', change.metadata.startTime,
'as Change ID', change.metadata.id);
console.log('Change status is currently', change.metadata.status);
});
It sounds like you want an internal DNS registration, in which case this happens automatically. See https://cloud.google.com/compute/docs/internal-dns.
For example, if you create an instance named "instance-1", it will be automatically resolvable from any instance in the same network and project as either instance-1 or the FQDN: [HOST_NAME].c.[PROJECT_ID].internal.
Note: automatic external DNS registration is now in alpha: https://issuetracker.google.com/issues/35904549

Using custom URL for httptest.NewServer in Go

I am running UT on some rest calls by creating a http test server in the Go language. My code is as follows.
type student struct{
FirstName string
LastName string
}
func testGetStudentName() {
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response = new(student)
response.FirstName = "Some"
response.LastName = "Name"
b, err := json.Marshal(response)
if err == nil {
fmt.Fprintln(w, string(b[:]))
}
}))
defer ts.Close()
student1 := base.getStudent("123")
log.Print("testServerUrl",testServer.URL) //prints out http://127.0.0.1:49931 ( port changes every time this is run)
ts.URL = "http://127.0.0.1:8099" //this assignment does not quite change the URL of the created test server.
}
In the file being tested,
var baseURL = "http://originalUrl.com"
var mockUrl = "http://127.0.0.1:49855"
func Init(mockServer bool){
if mockServer {
baseURL = mockUrl
}
}
func getStudent(id String){
url := baseUrl + "/student/" + id
req, err := http.NewRequest("GET", url, nil)
}
This init is called from my test.
This creates a new test server and runs the calls on a random port. Is it possible for me to run this server on a port I specify?
Most applications use the port assigned in NewServer or NewUnstartedServer because this port will not conflict with a port in use on the machine. Instead of assigning a port, they set the base URL for the service to the test server's URL.
If you do want to set the listening port, do the following:
// create a listener with the desired port.
l, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
ts := httptest.NewUnstartedServer(handler)
// NewUnstartedServer creates a listener. Close that listener and replace
// with the one we created.
ts.Listener.Close()
ts.Listener = l
// Start the server.
ts.Start()
// Stop the server on return from the function.
defer ts.Close()
// Add your test code here.

How to get IPhone's Public IP Address in swift3

For my project, i need to get the IPhone's Public IP address, there are so many examples available, which show public IP address by using external / third party URL. I just want to know how to extract IPhone's IP Address without help of using another URL.
I have following code but it gives local IP.
func getWiFiAddress() -> String? {
var address : String?
// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return nil }
guard let firstAddr = ifaddr else { return nil }
// For each interface ...
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
// Check for IPv4 or IPv6 interface:
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
// Check interface name:
let name = String(cString: interface.ifa_name)
if name == "en0" {
// Convert interface address to a human readable string:
var addr = interface.ifa_addr.pointee
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostname)
}
}
}
freeifaddrs(ifaddr)
return address
}