Problem sending simple HTTP Post request

Hey there I just received an internet button and am trying to do a simple HTTP post request without using the integrations through particle cloud. I am using the HTTP Client and attempting to send a small amount of data. I am currently doing this through curl commands and it works fine, just struggling to make it work with the internet button.

Here is my current code:

#include "application.h"
#include "HttpClient.h"
/**
* Declaring the variables.
*/
unsigned int nextTime = 0;    // Next time to contact the server
HttpClient http;

// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    // { "Content-Type", "application/json" },
    //  { "Accept" , "application/json" },
    { "Accept" , "*/*"},
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;

void setup() {
    Serial.begin(9600);
}

void loop() {
    if (nextTime > millis()) {
        return;
    }

    Serial.println();
    Serial.println("Application>\tStart of Loop.");
    // Request path and body can be set at runtime or at setup.
    request.hostname = "url.com";
    request.port = 80;
    request.path = "/services/uniqueurl";

    // The library also supports sending a body with your request:
    request.body = "{\"text\":\"Hello, World!\"}";

    // Get request
    http.post(request, response, headers);
    Serial.print("Application>\tResponse status: ");
    Serial.println(response.status);

    Serial.print("Application>\tHTTP Response Body: ");
    Serial.println(response.body);

    nextTime = millis() + 10000;
}

Here is the curl command I’ve been using:

curl -X POST -H ‘Content-type: application/json’ --data ‘{“text”:“Hello, World!”}’ https://url.com

I’m not sure what I am missing, but when watching the serial port it prints the following:

Application> Start of Loop.
Application> Response status: 302
Application> HTTP Response Body:

Any help would be greatly appreciated!

A HTTP POST request is a bit more than just pushing some “raw” data to the host.
e.g.


I’ve been able to make this work through Python, just trying to make it work here. I’ve made it work in python sending it as json. I was thinking “request.body = “{“text”:“Hello, World!”}”;” would format the request as json and allow it to be sent through HTTP.

:blush: sorry, I messed up! I mistook your HTTPClient for TCPClient :flushed:

I’d have to look closer, but maybe @tylercpeacock or @rickkas beat me to it :wink:

The HttpClient request is receiving an HTTP 302, which is an http redirect response code from the web server.

Your curl request is using https so will use port 443.

I don’t know whether url.com is the real URL that you are trying to access or is illustrative, but some websites try to force the use of https by responding to http requests with an http redirect.

2 Likes

url.com is a fake url, I am attempting to send a webhook to Slack. The real URL is https://hooks.slack.com/services/ I did attempt to change the port to 443. When I did that it returned this:

Application>    Start of Loop.
Application>    Response status: 400
Application>    HTTP Response Body: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
                                                          <HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
                                                              <TITLE>ERROR: The request could not be satisfied</TITLE>
                                      </HEAD><BODY>
                                                   <H1>ERROR</H1>
                                                                 <H2>The request could not be satisfied.</H2>
                             <HR noshade size="1px">
                                                    Bad request.
                                                                <BR clear="all">
                                                                               <HR noshade size="1px">
                      <PRE>
                           Generated by cloudfront (CloudFront)
                                                               Request ID: JOg0FYodS562RWdp0-vFW7UZi7dUwoN4VjMX5ayg9bsdHAhF_agMXQ==
                                                   </PRE>
                                                         <ADDRESS>
                                                                  </ADDRESS>
                                                                            </BODY></HTML>

You need an HTTPS library which is a very much larger scope thing than a simple HTTP library. There are a few ports of HTTPS libraries here in the forum but managing certificates is the tricky and memory consuming part. So what you are trying to do is advanced and somewhat hard via direct HTTPS POST.

This would be much simpler using a webhook and the Particle cloud. In that case the Particle cloud server acts as an intermediary getting the data from your device and posting over HTTPS to Slack.

Quick edit: Slack has an IFTTT integration so you can get this working very quickly via that.

Thanks for the response I will do some more research on the HTTPS libraries. We are trying to keep everything local as much as possible and not rely on sending requests to the Particle cloud servers or IFTTT due to the amount of requests we will be sending. We will max out the requests very quickly so we need to keep everything as local as possible.

Reading through Slack’s API documentation Here for incoming webhooks. I don’t see anything in regards to having to include any certificates in the POST. I am just needing a way to include a JSON payload with the post request.

Hi @absent_moose

When you make an HTTPS connection, there is a negotiated encryption of the data that happens that always involves certificates and a stream cipher. During that negotiation the browser or in this case your Particle device is supposed to check the certificate of the host it is connecting to using a chain of signed certificates back to some root certificate that the browser/device knows is good. Once it checks out, the browser/device uses the public key of the host it is connecting to to send a message that only that host could decode and then encryption starts up on the link using the negotiated on stream cipher.

So when you want to use this type of connection on a small platform like Particle you have some choices to make since doing the entire signed certificate chain of trust and all the possible ciphers is not really practical. Some make the choice to just blindly trust any certificate while others do some checking. You have to decide what is right for your security requirements.

If you want to see some of this machinery in action, fire up Chrome and go to a HTTPS link such as api.slack.com. Then type ctrl-shift-i to bring up the inspector and click on the Security button. This should show you that the page is secure and have a “View Certificate” button which you can click. You can also find out which negotiated type of secure connection is being used.

When I do that for say api.slack.com, I see that the first certificate is good for “*.slack.com” and signed by GeoTrust SSL CA G3. That certificate is then signed by GeoTrust Global CA which is a root or primary trusted certificate that the browser knows is good. The actual link encryption after the certificates are checked and everything is negotiated is TLS 1.2 ECDHE_RSA with P-256 key exchange and uses AES_128_GCM as the stream cipher.

If you are looking for terms to research I would recommend reading up on HTTPS and TLS