I am trying to send post request with esp8266 programmed on arduino IDE, but there's lack of examples how to do it. I would like to send request to json server with raw input so it would look like this:
http://ip:port/something
BODY
{
"valuename":value
}
Would be grateful if anyone could show me such an example.
Greetings
For handling HTTP requests, you can use a RestClient library rather than writing all the low level requests. It saves a lot of time and is less error-prone.
For example, for a GET request, all you have to do is:
String response = "";
int statusCode = client.post("/", "foo=bar", &response);
One good such library with SSL support is written by github user DaKaz.
You can use it for your GET request. The returned response will be without the HTTP header. The function will return the response from the server without the headers.
Now you can use the ArduinoJson Library by bblanchin for decoding the JSON object.
Details can be seen here.
Or you can do plain string manipuation to get the values though it is not a recommended route to take and is prone to errors.
Here is an example to send JSON via HTTP library :
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <ArduinoHttpClient.h>
#define JSON_BUF_SIZE 256
WiFiClient wifi;
HttpClient poster = HttpClient(wifi, IP, PORT);
void HTTPPost(){
String contentType = "application/json";
StaticJsonBuffer<JSON_BUF_SIZE> jsonBuffer;
JsonObject& jsonData = jsonBuffer.createObject();
jsonData["valuename"] = "value";
String postData = "";
jsonData.printTo(postData);
poster.post("/", contentType, postData);
printf("Trace : ResponseCode : %d\n", poster.responseStatusCode());
printf("Trace : Incoming Body : %s\n", poster.responseBody().c_str());
}
Related
I am automating Adobe InDesign to create documents using JSON data gathered from a web API with a SQL Server backend. I am using the Sockets object to make an HTTP 1.0 call to our server. Sometimes the response received is missing about 1700 characters from various points within the JSON string, yet when I call the same API endpoint using curl or Postman I get a complete and valid response.
The response should be about 150k characters long, and I'm using conn.read(99999999) to read it. In addition, the appearance of the end of the string looks correct, so I don't believe it's any kind of truncation problem.
The problem only seems to occur when I request a UTF-8 encoding. If I request ASCII I get a complete and valid response, but missing various Unicode characters. If I request BINARY I get a complete and valid response but the JavaScript/ExtendScript seems to be handling any multi-byte Unicode characters received as individual bytes, rather than as the Unicode characters we want to display.
Here is an illustration of the behavior I'm seeing, using bogus data...
"Expected" response...
[{"Id":1, "name":"Random Name", "Text":"A bunch of text", "AnotherId": 1}]
"Actual" response...
[{"Id":1, "name":"Random Name", "Text":"A bunc": 1}]
The problem first manifested itself as a JSON2 parsing error, for obvious reasons, but the root of it seems to be the fact that parts of the data are going missing in-transit.
So far we've only seen this problem when making the call using the InDesign Sockets object, and not every response exhibits this behavior.
Any help or insights you could offer would be appreciated.
Here is the function I'm using to call for data...
function httpRequest(url, encoding) {
try {
var response = "";
var hostName = getHostFromUrl(url);
var pathAndQuery = getPathAndQueryFromUrl(url);
var httpGet = "GET ";
httpGet += pathAndQuery;
httpGet += " HTTP/1.0\r\nHost: ";
httpGet += hostName;
httpGet += "\r\n";
var conn = new Socket;
conn.timeout = 30;
//conn.encoding = encoding || "UTF-8";
//conn.charset = "UTF-16";
if (conn.open(hostName + ":80", encoding || "UTF-8")) {
// send a HTTP GET request
conn.writeln(httpGet);
// and read the server's response
response = conn.read(99999999);
conn.close();
}
return parseHttpResponse(response);
}
catch (e) {
$.writeln(e);
$.global.alert("There was a problem making an HTTP Request: " + e);
return null;
}
}
It turns out my handling of the HTTP response was too simplistic and needed extra logic to handle Unicode characters properly.
The solution, in my case, was to use the GetURL method made available by Kris Coppieter here.
iam developing a rest service in c++ for a wordpress client in a project for a further education.
The service is written in c++ using casablanca as framework for and service and client communicate over JSON.
Now I have to send PDF Files to each other.
Can sb. tell me a method or an example to do this without sending direct links for a download?
http://casablanca.codeplex.com/
Here is my function to start the server and add the support methods.
void Commanagement::Init(utility::string_t url, utility::string_t port)
{
this->url = &url;
this->port = &port;
listener = new http_listener(U("http://localhost:4711"));
listener->support(methods::GET, std::bind(&Commanagement::handle_GET, this, std::placeholders::_1));
listener->support(methods::POST, std::bind(&Commanagement::handle_POST, this, std::placeholders::_1));
listener->open().wait();
}
And an example of sending a JSON response to my client.
void Commanagement::handle_POST(http_request message)
{
ucout << message.extract_json().wait();
auto paths = http::uri::split_path(http::uri::decode(message.relative_uri().path()));
json::value postData;
postData[L"id"] = json::value::number(13);
postData[L"FirstVal"] = json::value::string(L"Baseball");
postData[L"SomeVal"] = json::value::string(L"test");
message.reply(web::http::status_codes::OK, postData.serialize()).wait();
}
Files can be send serialized in the body to the clients.
This is an example only with the File Date, no headers and nothing else.
ifstream Stream;
Stream.open(FullFileName,std::ios::binary);
string Content, Line;
if (Stream)
{
while (getline(Stream,Line))
{
Content += Line;
}
}
Stream.close();
Request::request->set_body(Content);
I have to pass a json array consisting of json objects from the servlet to the jsp page. This data transfer slows down page responsiveness. Is there any way to optimize performance while passing large json from servlet to jsp.
code looks like:
request.setAttribute("jsonStringForDataTable", jsonArrayForDataTable);
response.setContentType("text/plain");
response.setContentLength(jsonArrayForDataTable.toString().getBytes().length);
ServletOutputStream out=response.getOutputStream();
out.print(jsonArrayForDataTable.toString().replace('_',' '));
out.close();
...
Any help is highly appreciated
You're using ajax, right? It's hard to tell since you're setting that request attribute, as if about to forward to a jsp, but then you're writing directly to the response. If this is ajax, you can compress the response with gzip if the client accepts it. You'll have to try it to know if it will speed things up in your situation. You'll be reducing the size of the response by a ratio that depends on the original content, but you'll be increasing the amount of processor work on the server (and on the client, which has to decompress the response).
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/json");
String strVal = jsonArrayForDataTable.toString().replace('_',''));
if (request.getHeader("Accept-Encoding") != null && request.getHeader("Accept-Encoding").contains("gzip"))
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(strVal.length());
GZipOutputStream gzip = new GZIPOutputStream(baos);
gzip.write(strVal.getBytes());
gzip.close();
response.setHeader("Content-Encoding", "gzip");
out.write(baos.toByteArray());
baos.close();
}
else
{
out.print(strVal);
}
On the client side, you have to be prepared for a gzipped response by setting the Accept-Encoding XMLHttpRequest header to gzip. The browser will decompress it into the json string.
I'm trying to post a json data via Arduino.When ı'm trying to this code.ı will send a json data with QueryString.If ı try this code the server answer me with Wrong QueryString format.Which mean is ı'm connected to server and server got my data.
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("POST /URL?query=jsondata HTTP/1.1");
client.println("Host: **.**.**.**");
client.println("Connection: close\r\nContent-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
}
But My Main Plan is send my json data with querystring.If ı Try this code ;
client.println("POST /URL?query={request:{Header:{Username:kullaniciAdi,Password:123456},Item:{Serial:ABC123QWE,Data:100, DateOn:23/11/1986 15:45:24}}} HTTP/1.1");
I get a HTTP Error 400. The request is badly formed.
Anyone Has a any idea?
Yes, your URI contains spaces and may contain other characters to confuse the format of the post request. You need to encode these characters.
As far as I can tell, the Arduino standard libraries do not include any form of urlEncode method, which is common in other languages and libraries, so you will either have to create your own or look for one.
Your resulting code would be something like:
String request = "/URL?query={request:{Header:{Username:kullaniciAdi,Password:123456},Item:{Serial:ABC123QWE,Data:100, DateOn:23/11/1986 15:45:24}}}";
String encRequest = uriEncode(request); // need to write your own method for this...
String post = "POST " + encRequest + " HTTP/1.1");
client.println( post);
Some discussion on creating a uriEncode function is on the Arduino Forum and there also appears to be a working method on hardwarefun.com
Recently I started taking this guide to get myself started on downloading files from the internet. I read it and came up with the following code to download the HTTP body of a website. The only problem is, it's not working. The code stops when calling the recv() call. It does not crash, it just keeps on running. Is this my fault? Am I using the wrong approch? I intent to use the code to not just download the contents of .html-files, but also to download other files (zip, png, jpg, dmg ...). I hope there's somebody that can help me. This is my code:
#include <stdio.h>
#include <sys/socket.h> /* SOCKET */
#include <netdb.h> /* struct addrinfo */
#include <stdlib.h> /* exit() */
#include <string.h> /* memset() */
#include <errno.h> /* errno */
#include <unistd.h> /* close() */
#include <arpa/inet.h> /* IP Conversion */
#include <stdarg.h> /* va_list */
#define SERVERNAME "developerief2.site11.com"
#define PROTOCOL "80"
#define MAXDATASIZE 1024*1024
void errorOut(int status, const char *format, ...);
void *get_in_addr(struct sockaddr *sa);
int main (int argc, const char * argv[]) {
int status;
// GET ADDRESS INFO
struct addrinfo *infos;
struct addrinfo hints;
// fill hints
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
// get address info
status = getaddrinfo(SERVERNAME,
PROTOCOL,
&hints,
&infos);
if(status != 0)
errorOut(-1, "Couldn't get addres information: %s\n", gai_strerror(status));
// MAKE SOCKET
int sockfd;
// loop, use first valid
struct addrinfo *p;
for(p = infos; p != NULL; p = p->ai_next) {
// CREATE SOCKET
sockfd = socket(p->ai_family,
p->ai_socktype,
p->ai_protocol);
if(sockfd == -1)
continue;
// TRY TO CONNECT
status = connect(sockfd,
p->ai_addr,
p->ai_addrlen);
if(status == -1) {
close(sockfd);
continue;
}
break;
}
if(p == NULL) {
fprintf(stderr, "Failed to connect\n");
return 1;
}
// LET USER KNOW
char printableIP[INET6_ADDRSTRLEN];
inet_ntop(p->ai_family,
get_in_addr((struct sockaddr *)p->ai_addr),
printableIP,
sizeof(printableIP));
printf("Connection to %s\n", printableIP);
// GET RID OF INFOS
freeaddrinfo(infos);
// RECEIVE DATA
ssize_t receivedBytes;
char buf[MAXDATASIZE];
printf("Start receiving\n");
receivedBytes = recv(sockfd,
buf,
MAXDATASIZE-1,
0);
printf("Received %d bytes\n", (int)receivedBytes);
if(receivedBytes == -1)
errorOut(1, "Error while receiving\n");
// null terminate
buf[receivedBytes] = '\0';
// PRINT
printf("Received Data:\n\n%s\n", buf);
// CLOSE
close(sockfd);
return 0;
}
void *get_in_addr(struct sockaddr *sa) {
// IP4
if(sa->sa_family == AF_INET)
return &(((struct sockaddr_in *) sa)->sin_addr);
return &(((struct sockaddr_in6 *) sa)->sin6_addr);
}
void errorOut(int status, const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(status);
}
If you want to grab files using HTTP, then libcURL is probably your best bet in C. However, if you are using this as a way to learn network programming, then you are going to have to learn a bit more about HTTP before you can retrieve a file.
What you are seeing in your current program is that you need to send an explicit request for the file before you can retrieve it. I would start by reading through RFC2616. Don't try to understand it all - it is a lot to read for this example. Read the first section to get an understanding of how HTTP works, then read sections 4, 5, and 6 to understand the basic message format.
Here is an example of what an HTTP request for the stackoverflow Questions page looks like:
GET http://stackoverflow.com/questions HTTP/1.1\r\n
Host: stackoverflow.com:80\r\n
Connection: close\r\n
Accept-Encoding: identity, *;q=0\r\n
\r\n
I believe that is a minimal request. I added the CRLFs explicitly to show that a blank line is used to terminate the request header block as described in RFC2616. If you leave out the Accept-Encoding header, then the result document will probably be transfered as a gzip-compressed stream since HTTP allows for this explicitly unless you tell the server that you do not want it.
The server response also contains HTTP headers for the meta-data describing the response. Here is an example of a response from the previous request:
HTTP/1.1 200 OK\r\n
Server: nginx\r\n
Date: Sun, 01 Aug 2010 13:54:56 GMT\r\n
Content-Type: text/html; charset=utf-8\r\n
Connection: close\r\n
Cache-Control: private\r\n
Content-Length: 49731\r\n
\r\n
\r\n
\r\n
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ... 49,667 bytes follow
This simple example should give you an idea what you are getting into implementing if you want to grab files using HTTP. This is the best case, most simple example. This isn't something that I would undertake lightly, but it is probably the best way to learn and appreciate HTTP.
If you are looking for a simple way to learn network programming, this is a decent way to start. I would recommend picking up a copy of TCP/IP Illustrated, Volume 1 and UNIX Network Programming, Volume 1. These are probably the best way to really learn how to write network-based applications. I would probably start by writing an FTP client since FTP is a much simpler protocol to start with.
If you are trying to learn the details associated with HTTP, then:
Buy HTTP: the Definitive Guide and read it
Read RFC2616 until you understand it
Try examples using telnet server 80 and typing in requests by hand
Download the cURL client and use the --verbose and --include command line options so that you can see what is happening
Read Fielding's dissertation until HTTP really makes sense.
Just don't plan on writing your own HTTP client for enterprise use. You do not want to do that, trust me as one who has been maintaining such a mistake for a little while now...
The problem is, you have to implement the HTTP protocol. Downloading a file is not just a matter of connecting to the server, you have to send HTTP requests (along with proper HTTP header) before you get a response. After this, you would still need to parse the returned data to strip out more HTTP headers.
If you're just trying to download files using C, I suggest the cURL library, which does the HTTP work for you.
You have to send an HTTP request before expecting a response.
You code currently just waits for a response which never comes.
Also, don't write comments in all caps.