HTTPS Post Request with ESP8266 - post

I'm trying to send an HTTPS POST request with a ESP8266. I can make the request just fine with python and cURL just when I try it with the ESP it doesn't work. A segment of my code is below
const char *host = "api.pushbullet.com";
const int httpsPort = 443;
const char fingerprint[] PROGMEM = "4C 70 C5 AE F3 30 E8 29 D1 9C 18 C6 2F 08 D0 6A A9 AA 19 0F";
Link = "/post";
httpsClient.print(String("POST ") + Link + " HTTP/1.1\r\n" +
"Host: " + host + "/v2/pushes" + "\r\n" +
"Access-Token: *************"+ "\r\n" +
"Content-Type: application/json"+ "\r\n" +
"Content-Length: 20"+ "\r\n" +
"body: Hello World" + "\r\n\r\n");
Serial.println("request sent");
The request I'm trying to make is below. This works just fine in python
import requests
headers = {
'Access-Token': '***********',
'Content-Type': 'application/json',
}
data = '{"body":"Hello World","title":"Hi","type":"note"}'
response = requests.post('https://api.pushbullet.com/v2/pushes', headers=headers, data=data)
And in cURL:
curl --header 'Access-Token: **********' --header 'Content-Type: application/json' --data-binary '{"body":"Hello World","title":"Hi","type":"note"}' --request POST https://api.pushbullet.com/v2/pushes
When I make the request with the Arduino code it returns "Error 411 (Length Required)!!".
This is probably due to some stupid mistake I've made but if anyone could help me fix my Arduino code I'd be very grateful. Thanks

There are a few mistakes in your code.
your http POST format are incorrect in a)host name, b)uri, and c)header/body separation;
your http body is not a valid json object.
Here is an example on sending the http (without using String):
const char *host = "api.pushbullet.com";
const char *uri = "/post/v2/pushes/";
const char *body ="{\"body\": \"Hello World\"}"; // a valid jsonObject
char postStr[40];
sprintf(postStr, "POST %s HTTP/1.1", uri); // put together the string for HTTP POST
httpsClient.println(postStr);
httpsClient.print("Host: "); httpsClient.println(host);
httpsClient.println("Access-Token: *************");
httpsClient.println("Content-Type: application/json");
httpsClient.print("Content-Length: "); httpsClient.println(strlen(body));
httpsClient.println(); // extra `\r\n` to separate the http header and http body
httpsClient.println(body);

General advice: when you use cURL always use --verbose to see the full HTTP exchange.
In your case it should be
httpsClient.print(String("POST ") + "/v2/pushes" + Link + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Access-Token: *************"+ "\r\n" +
"Content-Type: application/json"+ "\r\n" +
"Content-Length: 20"+ "\r\n" +
"body: Hello World" + "\r\n\r\n");
Note how
the path is "/v2/pushes/" plus identifier ("Link" in your case?)
Host is just "api.pushbullet.com"
Side notes:
make sure you send correct values for Content-Length
consider using HTTPClient if you are not confident with low-level HTTP programming

Related

Trying to connect to host

I'm trying to connect to Google Firebase Firestore using an esp8266 device. I want to do a post request but can't get a connection to the host:
const char *host = "firestore.googleapis.com";
int r=0; //retry counter
while((!httpsClient.connect(host, httpsPort)) && (r < 30)){
delay(50);
Serial.print(".");
r++;
}
httpsClient.print(String("POST ") + "/v1beta1/projects/myproject/databases/(default)/documents/loggings" + " HTTP/1.1\r\n" +
"Host: " + "firestore.googleapis.com" + "\r\n" +
"Content-Type: application/json"+ "\r\n" +
"Content-Length: 240" + "\r\n\r\n" +
postData+ "\r\n" +
"Connection: close\r\n\r\n");
The connect() function doesn't work because the host can't be found (404). How do I need to use the connect function to get a proper connection to the firestore host?
Call httpsClient.setInsecure() before connect(). Key validation is then skipped. It's not secure but maybe that's ok for your use case. httpsPort should be 443. For me connecting to fcm.googleapis.com works if done like this:
WiFiClientSecure client;
client.setInsecure(); // INSECURE!
client.connect("fcm.googleapis.com", 443);

Jersey: http error 400

I need to write a Jersey Client in Spring.
Using CURL, this works:
curl --header "Authorization: Basic aaaaaaabbbbb" --header "Content-Type: application/json" --request POST "http://163.162.8.112:9000/path" --data #TestWrapperJob.json
--> return a STRING
-- TestWrapper.json
{ "name": "job2aad",
"description": "Descrizione test job1",
"tests": [ {
"TestPath": "EsempiRiccardo\\TestWrapper",
"TestDuration": "2"
} ],
"topology": null
}
Now I'm trying to translate in JAVA, but i get HTTP ERROR 400
Client client = Client.create();
String temp = "{ \"name\": \"job2aad\", "
+ " \"description\": \"Descrizione test job1\", "
+ " \"tests\": [ { "
+ " \"TestPath\": \"EsempiRiccardo\\TestWrapper\", "
+ " \"TestDuration\": \"2\" "
+ " } ], "
+ " \"topology\": null "
+ "}";
WebResource webResource = client.resource("http://163.162.8.112:9000/path");
ClientResponse response = webResource.header("Authorization", "Basic aaaaaaabbbbb")
.type("application/json")
.post(ClientResponse.class, temp);
What's wrong?
Riccardo
Ok, sorry to all...
I found the answer
+ " \"TestPath\": \"EsempiRiccardo\\TestWrapper\", "
should be
+ " \"TestPath\": \"EsempiRiccardo\\\\TestWrapper\", "

How to avoid Restart Bluetooth Printer after print?

I have developed windows mobile 6.1 application which search nearby Bluetooth devices and send files.Also I did print functionality to print document on Bluetooth printer.
First time print functionality is working perfectly fine but when I print the document again, then I need to restart the printer and then after it will print.
Is there any solution to avoid restart printer??
Below is my print code from reference of https://32feet.codeplex.com/discussions/355451
private void btPrint_Click(object sender, EventArgs e)
{
// Activate BT
BluetoothRadio.PrimaryRadio.Mode = RadioMode.Connectable;
System.Threading.Thread.Sleep(1000);
// Connect
BluetoothAddress btAddress;
btAddress = BluetoothAddress.Parse("0022583165F7");
BluetoothClient btClient = new BluetoothClient();
try
{
btClient.Connect(new BluetoothEndPoint(btAddress, BluetoothService.SerialPort));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
// Send data
string CPCLStr1 =
"! 0 200 200 210 1" + Environment.NewLine +
"ML 25" + Environment.NewLine +
"TEXT 7 0 10 20" + Environment.NewLine +
"Just" + Environment.NewLine +
"Testing" + Environment.NewLine +
"ENDML" + Environment.NewLine +
"FORM" + Environment.NewLine +
"PRINT" + Environment.NewLine;
// Convert CPCL String to byte array
byte[] CPCLbytes1 = ASCIIEncoding.ASCII.GetBytes(CPCLStr1);
NetworkStream ns = btClient.GetStream();
ns.Write(CPCLbytes1, 0, CPCLbytes1.Length);
btClient.Close();
}
Although you close the client stream, the printer seems to wait some time before it resets it's session.
Try to send a <EOF> or <EOT> byte at the end.
Acording to CPCL reference guide there is no simple reset command as with ESC/p for example ({esc}#).
Doing a device reset after every print seems an overkill.
EDIT: SDK sample for sendFile:
Byte[] cpclLabel = Encoding.Default.GetBytes("! 0 200 200 406 1\r\n" + "ON-FEED IGNORE\r\n"
+ "BOX 20 20 380 380 8\r\n"
+ "T 0 6 137 177 TEST\r\n"
+ "PRINT\r\n");
The above runs fine on my RW420 without the need to reset between prints.

HTTP 302 - Not found parameter GSessionID - Google Calendar

I need help .
I want to create events on google calendar with a desktop application , when the parameters sent
url = 'https://www.google.com/calendar/feeds/emaill%40gmail.com/private/full';
and then add xml where this event to create
createXML := '<?xml version=''1.0'' encoding=''UTF-8''?>'#13#10 +
'<entry xmlns=''http://www.w3.org/2005/Atom'''#13#10 +
'xmlns:gd=''http://schemas.google.com/g/2005''>'#13#10 +
'<category scheme=''http://schemas.google.com/g/2005#kind'''#13#10 +
'term=''http://schemas.google.com/g/2005#event''></category>'#13#10 +
'<title type=''text''>' + title + '</title>'#13#10 +
'<content type=''text''>' + content + '</content>'#13#10 +
'<gd:transparency'#13#10 +
'value=''http://schemas.google.com/g/2005#event.opaque''>'#13#10 +
'</gd:transparency>'#13#10 +
'<gd:eventStatus'#13#10 +
'value=''http://schemas.google.com/g/2005#event.confirmed''>'#13#10 +
'</gd:eventStatus>'#13#10 +
'<gd:where valueString=''' + location + '''></gd:where>'#13#10 +
'<gd:when startTime=''' + EventStartTime + ''''#13#10 +
'endTime=''' + EventEndTime + '''></gd:when>'#13#10 +
'</entry>';
When I do the POST process the next header appears
HTTP/1.0 302 Moved Temporarily
Expires: Wed, 30 April 2014 17:37:17 GMT
Date: Wed, 30 April 2014 17:37:17 GMT
Set- Cookie: T=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
Expires = Tue, 13 -May- 2014 10:32:28 GMT;
SecureLocation : https://www.google.com:443/calendar/feeds/default/private/full?t=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content- Type: text / html ; charset = UTF -8
Cache- Control: private , max -age = 0
X -Content -Type -Options : nosniff
X -Frame -Options : SAMEORIGIN
X -XSS -Protection : 1; mode = block
Server : GSE
Alternate -Protocol : 443: quic
In the manual, Google listed me I need a variable called " GSessionID " but does not appear to me,
I would please help me with this problem .
I have two projects with authentication: ClientLogin and OAuth 2.0
as I get to get this parameter?
Thanks a lot.
Us Google Translator
It has to work to retrieve the newly loaded gsessionID condition Realize post procedure twice, the second in the exception
try
idHTTP2.Post(URL,XML);
except on E: EIdHTTPProtocolException do
idHTTP2.Post(URL,XML);
end;
Thanks for your time.

Http connection using apache.DefaultHttpClient goes into TIME_WAIT not getting reused

We have a pool(GenericObjectPool) of HttpClient(apache.DefaultHttpClient) objects. HttpPost objects are put into for execution through these clients may Post request are sent simultaneously. The protocol used is: HTTP/1.1 with keepalive.
Observed during load testing through netstat that new socket connections are indiscriminately created and old connections goes to TIME_WAIT.
Log Excerpts:-
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "POST /INBOX/4504a09e-13c0-3853-a285-9e2b9a22f65e/1e1e5a20-a8c1-11e2-99b8-7c19e9129271 HTTP/1.1[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Type: application/json; charset=UTF-8[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Length: 117[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Host: rwcdtgxb0402:15010[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Connection: Keep-Alive[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "User-Agent: Apache-HttpClient/4.2.1 (java 1.5)[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - << "HTTP/1.1 200 OK[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - << "Content-Length: 0[\r][\n]"
[Worker-2] org.apache.http.impl.conn.Wire 63 - << "[\r][\n]"
[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 254 - Receiving response: HTTP/1.1 200 OK
[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 257 - << HTTP/1.1 200 OK
[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 260 - << Content-Length: 0
[Worker-2] org.apache.http.impl.client.DefaultRequestDirector 540 - Connection can be kept alive indefinitely
**[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 154 - Connection 0.0.0.0:51211<->192.168.88.172:15010 shut down**
[Worker-2] org.apache.http.impl.conn.BasicClientConnectionManager 189 - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl#12f65ce5
Is DefaultClientConnection.shutdown (Connection 0.0.0.0:51210<->192.168.88.172:15010 shut down) closing the connection from Client end? How is it getting invoked?
In code after receiving the response (200OK) from server httpPost.releaseConnection() is only executed in client side code.
What should I do to keep the connections in ESTABLISHED state and reuse them instead of creating the connection for every request and they going into TIME_WAIT.
Any help will be highly appreciated. Thank you.
Note calling EntityUtils.consume(entity) does a bit more and should be used:
/**
* Ensures that the entity content is fully consumed and
* the content stream, if exists, is closed.
*
* #param entity the entity to consume.
* #throws IOException if an error occurs reading the input stream
*
* #since 4.1
*/
public static void consume(final HttpEntity entity) throws IOException {
if (entity == null) {
return;
}
if (entity.isStreaming()) {
final InputStream inStream = entity.getContent();
if (inStream != null) {
inStream.close();
}
}
}
Got the problem resolved few days back.
Mistake: calling releaseConnection() on the HttpClient object. BUT, avoiding it did not solve the problem either.
Correction:
The action to be taken for keeping the connections alive (in state ESTABLISHED) was through following sample code:
HttpClient client = new org.apache.http.impl.client.DefaultHttpClient();
...
org.apache.http.HttpResponse response = client.executed(HttpPost) ;
org.apache.http.HttpEntity en = response.getEntity();
if (en != null) {
en.getContent().close();
}
Once the HttpResponse is received, in order to reuse and maintain the created connection it is necessary to close only the InputStream (en.getContent()) on the http-response. Do not call any other release method on HttpPost or Client objects.
Tested this handling with JMeter load and found it working. Haven't observed any side effects yet!

Resources