grab full url from ESP8266WebServer - webserver

This question must be a duplicate, but I cannot find the answer.
Using the ESP8266WebServer library, there is an uri() method to grab the uri. So in the example: http://example.com/index, it will grab /index, but I would also like to get the example.com. IS there a method for that?

The http(s)://host:port part is not sent to server. The client uses the hostname to resolve the IP address and then the client makes a connection to the IP address on the specified port.
But HTTP 1.1 has a mandatory Host header in requests to a HTTP server.
The ESP8266 Arduino ESP8266WebServer library makes the current request's headers accessible on the ESP8266WebServer instance. To get the Host header there is a hostHeader() method.
Example:
void handleRoot() {
Serial.print("The Host: header value: ");
Serial.println(server.hostHeader());
server.send(200, "text/plain", "hello from esp8266!\r\n");
}
Documentation for the ESP8266WebServer is here.

Related

REST client gives error, while HTTP looks fine

My interface (an MKR Wifi 1010 Arduino) runs a very simple REST API, but when testing it with Mulesoft's Advanced Rest Client, I get this error:
The requested URL can't be reached
The service might be temporarily down or it may have moved permanently to a new web address.
The response status "0" is not allowed. See HTTP spec for more details: https://tools.ietf.org/html/rfc2616#section-6.1.1
When I check it with telnet though, it looks fine:
[bf#localhost ~]$ telnet 192.168.178.185 80
Trying 192.168.178.185...
Connected to 192.168.178.185.
Escape character is '^]'.
GET /api/gps HTTP/1.1
Host: 192.168.178.185
HTTP/1.1 200 OK
Connection: close
Content-Length: 9
Content-Type: application/json
"Success"
Connection closed by foreign host.
My question now is, is the rest client broken, or am I missing something in my reply? Of course I want any REST client to be able to process my interface correctly.

Strange issue with Vertx Http request

I configured an HTTPS website on AWS, which allows visiting from a white list of IPs.
My local machine runs with a VPN connection, which is in the white list.
I could visit the website from web browser or by the java.net.http package with the below code:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://mywebsite/route"))
.GET() // GET is default
.build();
HttpResponse<Void> response = client.send(request,
HttpResponse.BodyHandlers.discarding());
But if I replaced the code with a Vertx implementation from io.vertx.ext.web.client package, I got a 403 forbidden response from the same website.
WebClientOptions options = new WebClientOptions().setTryUseCompression(true).setTrustAll(true);
HttpRequest<Buffer> request = WebClient.create(vertx, options)
.getAbs("https://mywebsite/route")
.ssl(true).putHeaders(headers);
request.send(asyncResult -> {
if (asyncResult.succeeded()) {
HttpResponse response = asyncResult.result();
}
});
Does anyone have an idea why the Vertx implementation is rejected?
Finally got the root cause. I started a local server that accepts the testing request and forwards it to the server on AWS. The testing client sent the request to localhost and thus "Host=localhost:8080/..." is in the request header. In the Vert.X implementation, a new header entry "Host=localhost:443/..." is wrongly put into the request headers. I haven't debug the Vert.X implementation so I have no idea why it behaviors as this. But then the AWS firewall rejected the request with a rule that a request could not come from localhost.

STM32 - ESP8266 -GET Request

I'm using STM32 with ESp8266 using latest AT Command Firmware V2
Also i'm including https://github.com/nimaltd/ESP8266
Which helps parse at commands
I can connect to my router access point and my local tcp server but when sending GET requests i receive nothing on my local
const char* host = "192.168.1.9";
while(!Wifi_TcpIp_StartTcpConnection(0,host,3437,10)){
char buffer[] = "Unable to connect to TCP Backend\r\n";
HAL_UART_Transmit(&huart1,buffer,sizeof(buffer),HAL_MAX_DELAY);
};
uint8_t req ="GET /opaaa HTTP/1.1\r\n"; Wifi_TcpIp_SendDataTcp(0,sizeof(req),&req); //success but i receive nothing
Assuming the TCP communication works properly (you can connect to the server, send and receive data) and that the host you connect to serves HTTP on that port, the issue I can see with your request is that you're missing an additional CRLF at the end, like so:
char *req = "GET /opaaa HTTP/1.1\r\n\r\n";
Wifi_TcpIp_SendDataTcp(0, strlen(req), (uint8_t*)req);
This signifies the end of HTTP headers that you're sending. In your original case, the server may still be waiting for more headers and therefore holding with sending the response back to you.
I also suggest to clean up the sending code, one way of which I've pasted above - you were assigning a string to a single byte uint8_t variable.

Frisby.js Error: tunneling socket could not be established

I am trying to test an REST API on my local machine using frisby.js . It throws the following error.
Error: tunneling socket could not be established.
The machine address is something like 'https://machine_name:8443'
It seems that you are behind a proxy. Then, to make your frisby test working, you need to apply proxy configuration as follows:
var frisby = require('frisby');
frisby.globalSetup({
request: {
proxy: 'http://xx.xx.xx.xx:yyyy' // Provide proxy info (host, port) here
}
});
frisby.create('Your spec description here')
.get('https://machine_name:8443')
.expectStatus(200)
.toss();
Note also that you are using HTTPS protocol. Then you may find useful my answer in this post in case you have problems with SSL certificates

Differentiate between TcpClient and WebSocket?

I am developing an application in which i am using socket for the communication between server application and client application(web and desktop both). My server application continuously listening the request of the client application and accept the request whenever comes.
Server code :
TcpListener listener = new TcpListener(IPAddress.Parse(ipAddStr), portNum);
listener.Start();
while (listen)
{
TcpClient handler = listener.AcceptTcpClient();
// doing some stuff
// for every client handler i am creating a new thread and start listening for the next request
}
and for web client i am using WebSocket, as for establishing the connection with WebSocket client we have to follow some handshaking process. and for that I am using the following code (which is working fine) :
static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private static string AcceptKey(ref string key)
{
string longKey = key + guid;
SHA1 sha1 = SHA1CryptoServiceProvider.Create();
byte[] hashBytes = sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(longKey));
return Convert.ToBase64String(hashBytes);
}
generating and sending response for handshaking with websocket client:
// generate accept key fromm client header request
var key = headerRequest.Replace("ey:", "`")
.Split('`')[1]
.Replace("\r", "").Split('\n')[0]
.Trim();
var responseKey = AcceptKey(ref key);
//create the response for the webclient
var newLine = "\r\n";
var response = "HTTP/1.1 101 Switching Protocols" + newLine
+ "Upgrade: websocket" + newLine
+ "Connection: Upgrade" + newLine
+ "Sec-WebSocket-Accept: " + responseKey + newLine + newLine;
//send respose to the webclient
Byte[] sendBytes = Encoding.ASCII.GetBytes(response);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
I have also TcpClient socket used for desktop application, so the problem is how to identify that the request is from WebSocket or from TcpClient ?
The easiest way would be to have a websocket listener and the vanilla TCP listener listen to different port numbers. You should do that anyway, because it is customary for websocket applications to run on the standard http port 80 (or standard https port 443 when you use websockets with TLS), while a custom protocol based on TCP should run on one of the ports from the "registered" range between 1024 to 49151. You are well-advised to follow this, because a well-secured client environment which allows web access but not much else might not allow the user to connect to other ports than 80 and 443, while any non-http traffic on these ports might trigger an intrusion detection system.
When you still want to handle both protocols on the same port for some reason, it will be a bit difficult. Websocket is a protocol based on TCP which looks like a vanilla HTTP GET request at first, until you receive the headers Connection: Upgrade and Upgrade: websocket.
That means connection requests for either protocol need to be accepted by the same listener at first. Only after the client sent enough data to identify its connection attempt as either your custom protocol or websocket (or something completely different which accidentally connected to your port - you will encounter that a lot when you deploy your application facing the internet) and then delegate the communication with the client to the appropriate handler class.
A TcpClient is a Socket wrapper.
WebSocket is a protocol that can run over a TcpClient. WebSocket protocol defines the handshake and how to frame data.
The best way of differentiate simple TCP connections and WebSocket connections is to have them listening in different ports, since you are going to use different protocols. It would be bad if you have them in the same port, it will become a mess.