Cant send data to Firebase using AT commands - firebase

I'm using an Arduino with a GSM modem to try to send data to firebase.
However, when I try to, I get the following error:
SEND OK HTTP/1.1 400 Bad Request Server: nginx Date: Mon, 27 May 2019
22:34:09 GMT Content-Type: text/html Content-Length: 166 Connection:
close Strict-Transport-Security: max-age=31556926; includeSubDomains;
preload
400 Bad Request 400 Bad Request
nginx
CLOSED
The AT commands I issue are:
AT+QIOPEN="TCP", "drone-polution.firebaseio.com", 443
OK
CONNECT OK
AT+QISEND
>
POST /NewDB/.json
Accept: application/json
Content-Type: application/json
Content-Length: 9
{"a":"b"}
The last line is the actual payload.
Any help appreciated.

First, try this to program SAM chip to create an interface between Modem and your console PC (I found that there are good ready functions in MC20_Arduino_Interface.h which you can setup the modem.)
A simple program looks like this:
#include "MC20_Arduino_Interface.h"
// set serial port that connects to MC20
//#define serialMC20 Serial1
void setup()
{
//Begin serial comunication with Arduino and Arduino IDE (Serial Monitor)
SerialUSB.begin(115200);
while (!Serial);
//Being serial communication witj Arduino and MC20
serialMC20.begin(115200);
delay(1000);
SerialUSB.println("Setup Complete!");
}
void loop()
{
//Read MC20 output (if available) and print it in Arduino IDE Serial Monitor
if (serialMC20.available())
{
SerialUSB.write(serialMC20.read());
}
//Read Arduino IDE Serial Monitor inputs (if available) and send them to MC20
if (SerialUSB.available())
{
serialMC20.write(SerialUSB.read());
}
}
Also, I suggest you use Arduino's serial monitor for communication.
If the Modem starts successfully you will see SMS Ready and Call Ready in the serial monitor.
According to Quectel HTTP docs for a POST request:
3.2. Send POST Request to HTTP Server
AT+QIFGCNT=0
OK
AT+QICSGP=1,"CMNET" //Set APN
OK
AT+QIREGAPP //Optional
OK
AT+QIACT //Optional
OK
AT+QHTTPURL=58,30 //Set URL
CONNECT
<Input data>
//For example, input 58 bytes:
http://api.efxnow.com/DEMOWebServices2.8/Service.asmx/Echo
OK
//POST the data whose size is 18 bytes and the maximum latency time for inputting is 50s.
//It is recommended to set the latency time as long as enough to download all the data in the latency time.
AT+QHTTPPOST=18,50,10
CONNECT
//This means module enters into data mode and is ready to receive data from UART.
//For example, input 18 bytes: Message=helloworld.
OK
//This means all data has been received, and DCD is set to high.
AT+QHTTPREAD=30 //Read the response of HTTP server.
CONNECT
<Output data> //Output the response data of HTTP server to UART.
//For example, UART outputs:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="https://api.efxnow.com/webservices2.3">Message='helloworld' ASCII:104 101 108 108
111 119 111 114 108 100 </string>
OK
AT+QIDEACT //Deactivate PDP context.
DEACT OK
For example for httpbin.org/post it would become something like this:
16:45:56.416 -> AT+QIFGCNT=0
16:45:56.416 -> OK
16:46:02.918 -> AT+QICSGP=1,"mtnirancell"
16:46:02.918 -> OK
16:46:07.850 -> AT+QIREGAPP
16:46:07.850 -> OK
16:46:12.275 -> AT+QIACT
16:46:12.275 -> OK
16:46:27.467 -> AT+QHTTPURL=23,60
16:46:27.467 -> CONNECT
16:46:27.467 -> <http://httpbin.org/post>
16:46:36.965 -> OK
16:46:36.965 ->
16:46:48.786 -> AT+QHTTPPOST=18,50,10
16:46:48.786 -> CONNECT
16:46:48.786 -> <message=helloworld>
16:47:02.094 -> OK
16:47:02.094 ->
16:47:06.569 -> AT+QHTTPREAD=30
16:47:06.569 -> CONNECT
16:47:06.569 -> {
16:47:06.569 -> "args": {},
16:47:06.569 -> "data": "",
16:47:06.569 -> "files": {},
16:47:06.569 -> "form": {
16:47:06.569 -> "message": "helloworld"
16:47:06.569 -> },
16:47:06.569 -> "headers": {
16:47:06.569 -> "Accept": "*/*",
16:47:06.569 -> "Content-Length": "18",
16:47:06.569 -> "Content-Type": "application/x-www-form-urlencoded",
16:47:06.602 -> "Host": "httpbin.org",
16:47:06.602 -> "User-Agent": "QUECTEL_MODULE"
16:47:06.602 -> },
16:47:06.602 -> "json": null,
16:47:06.602 -> "origin": "*******, ********",
16:47:06.602 -> "url": "https://httpbin.org/post"
16:47:06.602 -> }
16:47:06.602 -> OK

Related

How enable gzip compression middleware in go-chi

How can I enable gzip compression using the gzip middleware of the go-chi framework?
Try using the example shown here:
https://github.com/go-chi/chi/issues/204
but when I check with curl, I get this:
$ curl -H "Accept-Encoding: gzip" -I http://127.0.0.1:3333
HTTP/1.1 405 Method Not Allowed
Date: Sat, 31 Aug 2019 19:06:39 GMT
I tried the code "hello world":
package main
import (
"net/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
//r.Use(middleware.DefaultCompress) //using this produces the same result
r.Use(middleware.Compress(5, "gzip"))
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
func Hello(w http.ResponseWriter, r *http.Request){
w.Header().Set("Content-Type", "text/html") //according to the documentation this must be here to enable gzip
w.Write([]byte("hello world\n"))
}
but when I try to verify with curl, the result is the same
$ curl -H "Accept-Encoding: gzip" -I http://127.0.0.1:3333
HTTP/1.1 405 Method Not Allowed
Date: Sat, 31 Aug 2019 19:06:39 GMT
what's going on?
The other answers are outdated now. I had to solve this myself, so here what I found out.
Your error is here:
r.Use(middleware.Compress(5, "gzip"))
The second argument ("types") refers to the content types that the compression will be applied to. For example: "text/html", "application/json", etc
Just add a list of the content-types you want to compress, or remove the argument altogether:
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Compress(5))
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
This will compress all the content-types defined in the default list from middleware.Compress:
var defaultCompressibleContentTypes = []string{
"text/html",
"text/css",
"text/plain",
"text/javascript",
"application/javascript",
"application/x-javascript",
"application/json",
"application/atom+xml",
"application/rss+xml",
"image/svg+xml",
}
Good luck!
r.Use(middleware.DefaultCompress) has now been marked as DEPRECATED.
To enable compression you need to create a compressor, and use its handler.
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
compressor := middleware.NewCompressor(flate.DefaultCompression)
r.Use(compressor.Handler())
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
The flate package must be imported as compress/flate.
Use the commented middleware.DefaultCompress and a normal GET request.
package main
import (
"net/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.DefaultCompress)
r.Get("/", Hello)
http.ListenAndServe(":3333", r)
}
func Hello(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.Write([]byte("hello world\n"))
}
Try with curl:
$ curl -v http://localhost:3333 --compressed
* Rebuilt URL to: http://localhost:3333/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3333 (#0)
> GET / HTTP/1.1
> Host: localhost:3333
> User-Agent: curl/7.58.0
> Accept: */*
> Accept-Encoding: deflate, gzip
>
< HTTP/1.1 200 OK
< Content-Encoding: gzip
< Content-Type: text/html
< Date: Sat, 31 Aug 2019 23:37:52 GMT
< Content-Length: 36
<
hello world
* Connection #0 to host localhost left intact
Or HTTPie:
$ http :3333
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 36
Content-Type: text/html
Date: Sat, 31 Aug 2019 23:38:31 GMT
hello world

HTTP POST in Arduino MKGSM to Eventhub

I'm using the Arduino library MKGSM in order to make an HTTP POST to my Azure Eventhub. I am confident with the parameters provided as I have tried them by hand with curl and the HTTP POST did work, so the problem is for sure in my Android syntax. Here is my approach:
#include <MKRGSM.h>
#include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[] = SECRET_PINNUMBER;
// APN data
const char GPRS_APN[] = SECRET_GPRS_APN;
const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN;
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;
// initialize the library instance
GSMSSLClient client;
GPRS gprs;
GSM gsmAccess;
// URL, path and port (for example: arduino.cc)
char server[] = "<namespace>.servicebus.windows.net";
char path[] = "/<myeventhubname>/messages";
int port = 443; // port 443 is the default for HTTPS
void setup() {
// initialize serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Starting Arduino web client.");
// connection state
boolean connected = false;
// After starting the modem with GSM.begin()
// attach the shield to the GPRS network with the APN, login and password
while (!connected) {
if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &&
(gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
connected = true;
} else {
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, port)) {
Serial.println("connected");
// Make a HTTP request:
client.print("POST ");
client.print(server);
client.print(path);
client.println(" HTTP/1.1");
client.println("Authorization: SharedAccessSignature sr=https%3A%2F%2F<namespace>.servicebus.windows.net%2F<myeventhubname>&sig=<mysig>&se=<myse>&skn=RootManageSharedAccessKey");
client.println();
client.println("{\"HELLO\"}");
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.available() && !client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
for (;;)
;
}
}
Basically, the original example was a GET that obtained the ascii symbol of Arduino and I am guessing if it is possible to use the same code to make an http post (in my case, to an Eventhub).
Update:
After changing GSM gsmAccess to GSM gsmAccess(true) I start getting an output which is unreadable. I attach it bellow:
AT
OK
AT+IPR=921600
OK
AT
OK
AT+UPSV=3
OK
AT+CPIN?
ERROR
AT+CPIN?
ERROR
AT+CPIN?
ERROR
AT+CPIN?
+CPIN: READY
OK
AT+CMGF=1
OK
AT+UDCONF=1,1
OK
AT+CTZU=1
OK
AT+UDTMFD=1,2
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
+UMWI: 0,1
+UMWI: 0,2
+UMWI: 0,3
+UMWI: 0,4
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,1
OK
AT+UCALLSTAT=1
OK
AT+CGATT=1
OK
AT+UPSD=0,1,""
OK
AT+UPSD=0,6,3
OK
AT+UPSD=0,2,""
OK
AT+UPSD=0,3,""
OK
AT+UPSD=0,7,"0.0.0.0"
OK
AT+UPSDA=0,3
OK
AT+UPSND=0,8
+UPSND: 0,8,1
OK
AT+USOCR=6
+USOCR: 0
OK
AT+USOCO=0,"<server>.servicebus.windows.net",443
OK
connected
AT+USOWR=0,5,"504F535420"
+USOWR: 0,5
OK
AT+USOWR=0,60,"2F6D796576656E746875622F6D657373616765733F74696D656F75743D3630266170692D76657273696F6E3D323031342D303120485454502F312E31"
+USOWR: 0,60
OK
AT+USOWR=0,193,"417574686F72697A6174696F6E3A205368617265644163636573735369676E61747572652073723D687474707325334125324625324665666F7230312E736572766963656275732E77696E646F77732E6E65742532466D796576656E74687562267369673D683977624C78673467306E50764E6E347977696F462532426C623244446E6556306863353833757A496B7462302533442673653D3135373633313930323826736B6E3D526F6F744D616E6167655368617265644163636573734B6579"
+USOWR: 0,193
OK
AT+USOWR=0,59,"436F6E74656E742D547970653A206170706C69636174696F6E2F61746F6D2B786D6C3B747970653D656E7472793B636861727365743D7574662D38"
+USOWR: 0,59
OK
AT+USOWR=0,2,"0D0A"
+USOWR: 0,2
OK
AT+USOWR=0,35,"486F73743A2065666F7230312E736572766963656275732E77696E646F77732E6E6574"
+USOWR: 0,35
OK
AT+USOWR=0,2,"0D0A"
+USOWR: 0,2
OK
AT+USOWR=0,2,"0D0A"
+USOWR: 0,2
OK
AT+USOWR=0,2,"0D0A"
+USOWR: 0,2
OK
AT+USOWR=0,22,"7B2276616C7565223A2048656C6C6F20576F726C647D"
+USOWR: 0,22
OK
AT+USOWR=0,2,"0D0A"
+USOWR: 0,2
OK
disconnecting.
AT+USOCL=0
OK
Disclaimer - this is a suggestion only. I do not have the equipment or accounts to test/verify this.
Have you tried adding "https://" between POST and server ?
there might also be some parameters required before "HTTP/1.1"
namely
?timeout=60&api-version=2014-01
also,
client.println("Authorization: SharedAccessSignature sr=https%3A%2F%2F<namespace>.servicebus.windows.net%2F<myeventhubname>&sig=<mysig>&se=<myse>&skn=RootManageSharedAccessKey");
might not be right. try removing the https%3A%2F%2F in front of < namespace >
finally, you may also need to send :
Content-Type: application/atom+xml;type=entry;charset=utf-8
Host: your-namespace.servicebus.windows.net
in all:
// Make a HTTP request:
client.print("POST ");
client.print("https://");
client.print(server);
client.print(path);
client.print("?timeout=60&api-version=2014-01");
client.println(" HTTP/1.1");
client.println("Authorization: SharedAccessSignature sr=<namespace>.servicebus.windows.net/<myeventhubname>&sig=<mysig>&se=<myse>&skn=RootManageSharedAccessKey");
client.println("Content-Type: application/atom+xml;type=entry;charset=utf-8");
client.println("Host: <namespace>.servicebus.windows.net");
client.println();
client.println("{\"HELLO\"}");
} else {
.......
Cheers
So with the addition of the output by qwerty, I do not have much more to add yet.
The modem is not (it appears) sending out everything that is outlined in the code snippet I provided
If you scroll down the output until you reach
AT+USOCO=0,"<server>.servicebus.windows.net",443
the POST sequence starts next.
AT+USOWR=0,5,"504F535420"
sends "POST"
the next output from the modem skips the "https://" and server (ie it's as if the following two lines are missing from the code)
client.print("https://");
client.print(server);
but instead skips to sending out the path, timeout and HTTP/1.1. The rest of the output is also missing CR/LF from several lines.
It behaves as if the code in fact was
// Make a HTTP request:
client.print("POST ");
client.print(path);
client.print("?timeout=60&api-version=2014-01");
client.print(" HTTP/1.1");
client.print("Authorization: SharedAccessSignature sr=<namespace>.servicebus.windows.net/<myeventhubname>&sig=<mysig>&se=<myse>&skn=RootManageSharedAccessKey");
client.println("Content-Type: application/atom+xml;type=entry;charset=utf-8");
client.println("Host: <namespace>.servicebus.windows.net");
client.println();
client.println();
client.println("{\"value\": Hello World}");
I'm not sure what is causing this behaviour, but introducing delays might help
(Additionally, if server and path are constant strings, not likely to change for you application, you can concatenate the first 6 client.print() statements)
Giving you:
// Make a HTTP request:
client.print("POST https://<myserver>/<mypath>/?timeout=60&api-version=2014-01 HTTP/1.1");
client.println();
delay(5);
client.print("Authorization: SharedAccessSignature sr=<namespace>.servicebus.windows.net/<myeventhubname>&sig=<mysig>&se=<myse>&skn=RootManageSharedAccessKey");
client.println();
delay(5);
client.print("Content-Type: application/atom+xml;type=entry;charset=utf-8");
client.println();
delay(5);
client.print("Host: <namespace>.servicebus.windows.net");
client.println();
delay(5);
client.println();
delay(5);
client.print("{\"value\": Hello World}");
client.println();
}

libcurl write callback is not called for post http message

Intro
I'm sending POST request to server which responses with chunked messages.
So I'm trying to make writecallback being called on each received chunked http message.
Code
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace std;
size_t write_callback(char *d, size_t n, size_t l, void *userp)
{
cerr << ""--- Called once" << endl;
return n*l;
}
string xml_msg()
{
return "<<some request data>>";
}
curl_slist* get_header(size_t content_length)
{
auto list = curl_slist_append(nullptr, "<<protocol version>>");
list = curl_slist_append(list, "Content-Type: text/xml");
list = curl_slist_append(list, "Content-Length: " + content_length);
return list;
}
void main()
{
auto xml = xml_msg();
curl_global_init(CURL_GLOBAL_ALL);
auto curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "<<server url>>");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0)");
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_easy_setopt(curl, CURLOPT_USERPWD, "<<user credentials>>");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, get_header(xml.size()));
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, xml.data());
curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
}
Verbose log
* STATE: INIT => CONNECT handle 0x15c4de0; line 1422 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x15c4de0; line 1458 (connection #0)
* Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x15c4de0; line 1539 (connection #0)
* Connected to <<host>> (xxx.xxx.xxx.xxx) port 80 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x15c4de0; line 1591 (connection #0)
* Marked for [keep alive]: HTTP default
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x15c4de0; line 1605 (connection #0)
* STATE: PROTOCONNECT => DO handle 0x15c4de0; line 1626 (connection #0)
* Server auth using Basic with user '<<credentials>>'
> POST <<URL>>
Host: <<host>>
Authorization: Basic <<base64 credentials>>
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0)
Accept: */*
Content-Type: text/xml
Content-Length: 204
* upload completely sent off: 204 out of 204 bytes
* STATE: DO => DO_DONE handle 0x15c4de0; line 1688 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x15c4de0; line 1813 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x15c4de0; line 1823 (connection #0)
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Tue, 08 May 2018 12:29:49 GMT
* Server is not blacklisted
< Server: <<server>>
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Content-Language: en-US
< Cache-Control: no-cache, no-store
< Pragma: no-cache
< Content-Type: application/xml;charset=UTF-8
< Set-Cookie: <<cookie>>
< Transfer-Encoding: chunked
<
--- Called once
* STATE: PERFORM => DONE handle 0x15c4de0; line 1992 (connection #0)
* multi_done
* Connection #0 to <<server>> left intact
Problem
Writecallback has been called when connection had been closed by server due to timeout with FIN tcp packet instead of moment when chunked http response has been received.
It is about 30 secs interval between this events.
Question
What am I doing wrong?
Update 1
Server returns a tcp segment with PUSH flag and http message with chunked transfer encoding containing XML. Message ends with CLRF. Meanwhile Win API socket does not allow to read it and select() returns 0, which means that there is nothing to read/write on this socket.
After 30 secs delay before closing connection due to heartbeat timeout (that is internal implementation of the server), server sends finalizing http message with chunked transfer encoding, which contains 0 and CLRF. After that message select() displays new socket state and libcurl calls write callback with returning chunked message content.
That is what I see after debuging libcurl. I need to find out the way to get chunked http message returned by libcurl once it is received, not after getting final http message.
Ok, I was able to find out that the problem is with Win Api sockets. On linux builds libcurl calls writecallback right after receiving chuncked message. I'm not sure how to fix that issue with Win builds, but at least I found rootcause of problem.

Asterisk ARI / phpari - Bridge recording: "Recording not found"

I'm using phpari with Asterisk 13 and trying to record a bridge (mixing type).
In my code:
$this->phpariObject->bridges()->bridge_start_recording($bridgeID, "debug", "wav");
It returns:
array(4) {
["name"]=>
string(5) "debug"
["format"]=>
string(3) "wav"
["state"]=>
string(6) "queued"
["target_uri"]=>
string(15) "bridge:5:1:503"
}
When and I stop and save with
$this->phpariObject->recordings()->recordings_live_stop_n_store("debug");
It returns FALSE.
I debug with
curl -v -u xxxx:xxxx -X POST "http://localhost:8088/ari/recordings/live/debug/stop"
Result:
* About to connect() to localhost port 8088 (#0)
* Trying ::1... Connection refused
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8088 (#0)
* Server auth using Basic with user 'xxxxx'
> POST /ari/recordings/live/debug/stop HTTP/1.1
> Authorization: Basic xxxxxxx
> User-Agent: curl/7.19.7 (xxxxx) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: localhost:8088
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Server: Asterisk/13.2.0
< Date: Thu, 19 Feb 2015 11:58:18 GMT
< Cache-Control: no-cache, no-store
< Content-type: application/json
< Content-Length: 38
<
{
"message": "Recording not found"
* Connection #0 to host localhost left intact
* Closing connection #0
}
Asterisk CLI verbose 5 trace: http://pastebin.com/QZXnpXVA
So, I've solved the problem.
It was a simple write permission problem.
Asterisk user couldn't write on /var/spool/asterisk/recording because it was owned by root.
Changing the ownership to the asterisk user solved it.
I detected this problem by looking at the Asterisk CLI trace again:
-- x=0, open writing: /var/spool/asterisk/recording/debug format: sln, (nil)
This (nil) indicates that the file could not be written, so I checked the folder and saw where the problem was.

How do I silence Network.Browser.browse's logs to stdout?

I'm using Network.Browser 4000.0.9 to retrieve a web page:
import Network.Browser
import Network.HTTP
main =
do
(uri, response) <- browse $ do
setAllowRedirects True
setDebugLog Nothing
request $ getRequest "http://www.google.com/robots.txt"
putStrLn "done"
Despite setDebugLog Nothing this spews all of this logging:
Sending:
GET /robots.txt HTTP/1.1
Host: www.google.com
User-Agent: ...
Content-Length: 0
Creating new connection to www.google.com
Received:
HTTP/1.1 200 OK
Content-Type: text/plain
...
How do I turn this logging off?
Use setOutHandler and setErrHandler as described in the documentation page you linked.

Resources