HTTPS data retrieval error - http

I have an ESP12 with NodeMCU firmware installed (modules: http, tls, etc.).
Whenever I try to use http.get with an https link, I receive the following error:
> http.get("https://pastebin.com/raw/cAB83eF1", nil, function(code, data)
>> if (code < 0) then
>> print("HTTP request failed")
>> else
>> print(code, data)
>> end
>> end)
> HTTP client: Disconnected with error: -114
HTTP client: Connection timeout
HTTP client: Connection timeout
where as when I tried the same pastebin.com link without https, I am able to receive data and the HTTP status code.
> http.get("http://pastebin.com/raw/cAB83eF1", nil, function(code, data)
>> if (code < 0) then
>> print("HTTP request failed")
>> else
>> print(code, data)
>> end
>> end)
> 200 test
Quoting from the docs of http.get:
Each request method takes a callback which is invoked when the
response has been received from the server. The first argument is the
status code, which is either a regular HTTP status code, or -1 to
denote a DNS, connection or out-of-memory failure, or a timeout
(currently at 10 seconds).
Since the docs say valid codes are -1 and HTTP codes, how can I find out what is -114?
Edit1: After building the firmware with debug option ON. I get the following error:
> http.get("https://pastebin.com/raw/cAB83eF1", nil, function(code, data)
>> if (code < 0) then
>> print("HTTP request failed")
>> else
>> print(code, data)
>> end
>> end)
> client handshake start.
please start sntp first !
please start sntp first !
client handshake failed!
Reason:[-0x7200]
HTTP client: Disconnected with error: -114
HTTP client: Connection timeout
HTTP client: Connection timeout
=rtctime.get()
1501394767 272709
>
As per the log statement Reason:[-0x7200] 0x72 hex is -114 decimal which gets printed later Disconnected with error: -114.
Also sntp.sync() has already been performed as seen from the output of rtctime.get(). Even if the SNTP has been synced why is the message please start sntp first ! printed?
Also later in the log, after the -114 message, it displays Connection timeout message. How can I change the timeout for https connections? any pointers to C/header files?
Note: I do have the git repo and docker image installed on my Linux machine for building the firmware.
PS: I need https because I'll be making my ESP12 communicate with a RESP API hosted on the cloud.

This is a short and unsatisfactory answer: you hit https://github.com/nodemcu/nodemcu-firmware/issues/1707.

Related

GCP deployment with nginx - uwsgi - flask fails

I have a very simple flask app that is deployed on GKE and exposed via google external load balancer. And getting random 502 responses from the backend-service (added a custom headers on backend-service and nginx to make sure the source and I can see the backend-service's header but not nginx's)
The setup is;
LB -> backend-service -> neg -> pod (nginx -> uwsgi) where pod is the application built using flask and deployed via uwsgi and nginx.
The scenario is to handle image uploads in simple-secured way. Sender sends me a token with upload request.
My flask app
receive request and check the sent token via another service using "requests".
If token valid, proceed to handle the image and return 200
If token is not valid, stop and send back a 401 response.
First, I got suspicious about the 200 and 401's. And reverted all responses to 200. Following some of the expected responses, server starts to respond 502 and keep sending it. "Some of the messages at the very beginning succeeded".
nginx error logs contains below lines
2023/02/08 18:22:29 [error] 10#10: *145 readv() failed (104: Connection reset by peer) while reading upstream, client: 35.191.17.139, server: _, request: "POST /api/v1/imageUpload/image HTTP/1.1", upstream: "uwsgi://127.0.0.1:21270", host: "example-host.com"
my uwsgi.ini file is as below;
[uwsgi]
socket = 127.0.0.1:21270
master
processes = 8
threads = 1
buffer-size = 32768
stats = 127.0.0.1:21290
log-maxsize = 104857600
logdate
log-reopen
log-x-forwarded-for
uid = image_processor
gid = image_processor
need-app
chdir = /server/
wsgi-file = image_processor_application.py
callable = app
py-auto-reload = 1
pidfile = /tmp/uwsgi-imgproc-py.pid
my nginx.conf is as below
location ~ ^/api/ {
client_max_body_size 15M;
include uwsgi_params;
uwsgi_pass 127.0.0.1:21270;
}
Lastly, my app has a healthcheck method with simple JSON response. It does no extra stuff and simply returns. This never fails as explained above.
Edit : my nginx access logs in the pod shows the response as 401 while the client receives 502.
for those who gonna face with the same issue, the problem was post data reading (or not reading).
nginx was expecting to get post data read by the proxied, in our case uwsgi, app. But according to my logic I was not reading it in some cases and returning back the response.
Setting uwsgi post-buffering solved the issue.
post-buffering = %(16 * 1024 * 1024)
Which led me to this solution;
https://stackoverflow.com/a/26765936/631965
Nginx uwsgi (104: Connection reset by peer) while reading response header from upstream

nginx - connection timed out while reading upstream

I have a flask server with and endpoint that processes some uploaded .csv files and returns a .zip (in a JSON reponse, as a base64 string)
This process can take up to 90 seconds
I've been setting it up for production using gunicorn and nginx and I'm testing the endpoint with smaller .csv s. They get processed fine and in a couple seconds I get the "got blob" log. But nginx doesn't return it to the client and finally it times out. I set up a longer fail-timeout of 10 minutes and the client WILL wait 10 minutes, then time out
the proxy read timeout offered as solution here is set to 3600s
Also the proxy connect timeout is set to 75s according to this
also the timeout for the gunicorn workers according to this
The error log says: "upstream timed out connection timed out while reading upstream"
I also see examples of nginx receiving an OPTIONS request and immediately after the POST request (some CORS weirdness from the client) where nginx passes the OPTIONS request but fails to pass the POST request to gunicorn despite nginx having received it
Question:
What am I doing wrong here?
Many thanks
http {
upstream flask {
server 127.0.0.1:5050 fail_timeout=600;
}
# error log
# 2022/08/18 14:49:11 [error] 1028#1028: *39 upstream timed out (110: Connection timed out) while reading upstream, ...
# ...
server {
# ...
location /api/ {
proxy_pass http://flask/;
proxy_read_timeout 3600;
proxy_connect_timeout 75s;
# ...
}
# ...
}
}
# wsgi.py
from main import app
if __name__ == '__main__':
app.run()
# flask endpoint
#app.route("/process-csv", methods=['POST'])
def process_csv():
def wrapped_run_func():
return blob, export_filename
# ...
try:
blob, export_filename = wrapped_run_func()
b64_file = base64.b64encode(blob.getvalue()).decode()
ret = jsonify(file=b64_file, filename=export_filename)
# return Response(response=ret, status=200, mimetype="application/json")
print("got blob")
return ret
except Exception as e:
app.logger.exception(f"0: Error processing file: {export_filename}")
return Response("Internal server error", status=500)
ps. getting this error from stackoverflow
"Your post appears to contain code that is not properly formatted as code. Please indent all code by 4 spaces using the code toolbar button or the CTRL+K keyboard shortcut. For more editing help, click the [?] toolbar icon."
for having perfectly well formatted code with language syntax, I'm sorry that I had to post it ugly
Sadly I got no response
See last lines for the "solution" finally implemented
CAUSE OF ERROR: I believe the problem is that I'm hosting the Nginx server on wsl1
I tried updating to wsl2 and see if that fixed it but I need to enable some kind of "nested virtualization", as the wsl1 is running already on a VM.
Through conf changes I got it to the point where no error is logged, gunicorn return the file then it just stays in the ether. Nginx never gets/sends the response
"SOLUTION":
I ended up changing the code for the client, the server and the nginx.conf file:
the server saves the resulting file and only returns the file name
the client inserts the filename into an href that then displays a link
on click a request is sent to nginx which in turn just sends the file from a static folder, leaving gunicorn alone
I guess this is the optimal way to do it anyway, though it still bugs me I couldn't (for sure) find the reason of the error

How to debug a HANDSHAKE_FAILURE when requesting an HTTPS server with ocaml-cohttp Client.post method ? (And why am I getting this error ?)

I wrote the following OCaml code in order to make POST requests to an https server.
open Lwt
open Cohttp
open Cohttp_lwt_unix
try
let headers = Header.init ()
|> fun h -> Header.add h "content-type" "application/json" in
let body = Client.post
~headers
~body:(body_of_credentials nickname secret)
(uri_of_project project)
>>= fun (response, body) ->
let code = response |> Response.status |> Code.code_of_status in
Printf.printf "Response code: %d\n" code;
Printf.printf "Headers: %s\n" (response |> Response.headers |> Header.to_string);
body |> Cohttp_lwt.Body.to_string >|= fun body ->
Printf.printf "Body of length: %d\n" (String.length body);
body
in
let body = Lwt_main.run body in
print_endline ("Received body\n" ^ body)
with
| Tls_lwt.Tls_alert e ->
print_endline (Tls.Packet.alert_type_to_string e);
exit 1
But when executing it with CONDUIT_TLS=native CONDUIT_DEBUG=true COHTTP_DEBUG=true I get the following response :
Selected TLS library: Native
Resolver system: https://my_server/auth/tokens/ ((name https) (port 443) (tls true)) -> (TCP ((V4 xx.xxx.xx.xxx) 443))
HANDSHAKE_FAILURE
I've read all the google results (documentation, ocaml/cohttp/ocaml-tls lists and stack overflow questions) I could find about it, but nothing helps, so I would like to start from scratch here.
How can I get more details about this failure ?
In case it helps, I'm using the following opam configuration:
"lwt" {>= "4.1.0"}
"cohttp" {>= "1.1.1"}
"cohttp-lwt"
"cohttp-lwt-unix" {>= "1.1.1"}
"tls" {>= "0.9.2"}
EDIT:
As suggested by #ivg, I tried with CONDUIT_TLS=openssl but then I get the following error:
Selected TLS library: OpenSSL
Resolver system: https://my_server/auth/tokens/ ((name https) (port 443) (tls true)) -> (TCP ((V4 xx.xxx.xx.xxx) 443))
...: internal error, uncaught exception:
SSL: Method error
EDIT²:
As suggested in the following discussion: github.com/savonet/ocaml-ssl/issues/40 I added an opam pin to ssl-0.5.5: opam pin add ssl 0.5.5 in order to fix this error. Now I am able to post requests to my https server, but not with the pure ocaml implementation of tls.
You're getting this alert because the handshaking process (authentication) had failed. This alert means, that the peer is not authenticated (either the server or the client) and thus a secure connection could not be established.
To debug the issue, I would suggest first to ensure that everything works fine with conventional tools, e.g., openssl, wget, or curl.
If you're sure that your configuration is fine and this is a problem on the ocaml-tls part I would suggest to use the low-level interface of the ocaml-tls library. Apparently, conduit doesn't expose or use any of the tracing capabilities of ocaml-tls, so there is no other choice.
The alert type is projected from two more rich fatal and error types that bear much more information about the nature of the problem, cf. the following code that creates an alert and consider possible input values that lead to the HANDSHAKE_FAILURE alert.
To access the particular error or alert I would suggest you to use the Tracing capabilities of ocaml-tls. There are examples in the source repository that already enable tracing and should provide sufficient information. I hope those examples will fit into your use case.

ESP HTTP connection issue : on connection callback function not getting called

I am using custom build for NodeMCU with following modules: cjson, file, gpio, http, net, node, ow, tmr, websocket, wifi.
conn = nil
conn=net.createConnection(net.TCP) -- 30 seconds timeout time of serv
conn:on("connection", function(conn, payload)
print("Server DB Connected, sending event") -- This line is not getting print on esplorer.
conn:send ( <some-data>)
end)
conn:connect(80,"mysite.com")
conn:close()
For debugging i tried using following code :
net.dns.resolve("www.google.com", function(sk, ip)
if (ip == nil) then
print("DNS fail!")
else
print("Resolved: " .. ip)
end
end)
But above is giving output " DNS fail! "
Site is working perfectly fine along with server.
A normal GET request to the same site using putty is returning correct data.
Please help me resolving the issue.

Connection failed in asterisk CLI

I am using php version 5.3.10 and asterisk version 1.8.22.0.
I am registering one customer of a2billing in softphone and dialing one number.
In asterisk i am getting below result:
<SIP/myip-0000004c>AGI Tx >> 200 result=1
<SIP/myip-0000004c>AGI Rx << Connection failed
<SIP/myip-0000004c>AGI Tx >> 510 Invalid or unknown command
[Dec 30 07:59:16] ERROR[28331]: utils.c:1343 ast_carefulwrite: write() returned error: Broken pipe
[Dec 30 07:59:16] ERROR[28331]: utils.c:1343 ast_carefulwrite: write() returned error: Broken pipe
-- <SIP/myip-0000004c>AGI Script a2billing.php completed, returning 0
Does anybody have any idea what is the issue?
I am getting correct credential in AGI when it is trying to connect and using those credential i can connect in mysql but from CLI> i am getting connection failed error.
Thanks in advance.
You need to install php5-adodb and libphp-adodb.

Resources