/** Performs an HTTP POST operation to the path at the address / port specified. A buffer with the data to be POSTed is passed in, and up to maxresponse bytes of the response from the server are written back into the same buffer. @param hostname The name of the host to connect to. @param path The path on the server to post to. @param port The port to connect on - standard http port is 80 @param data The buffer to write from, and then read the response back into @param data_length The number of bytes to write from \b data @param maxresponse How many bytes of the response to read back into \b data @param headers (optional) An array of strings to be sent as headers - last element in the array must be 0. @return The number of bytes written, or -1 on failure. \b Example \code // we'll post a test message to www.makingthings.com/post/path int bufLength = 100; char myBuffer[bufLength]; int datalength = siprintf(myBuffer, "A test message to post"); // load the buffer with some data to send webclientPost("www.makingthings.com", "/post/path", 80, myBuffer, datalength, bufLength, 0); \endcode */ int webclientPost(const char* hostname, const char* path, int port, char* data, int data_length, int maxresponse, const char* headers[]) { int s = tcpOpen(networkGetHostByName(hostname), port); if (s > -1) { int len = sniprintf(webclientBuf, WEBCLIENT_BUFFER_SIZE, "POST %s HTTP/1.1\r\nContent-Length: %d\r\n%s%s%s", path, data_length, (hostname != NULL) ? "Host: " : "", (hostname != NULL) ? hostname : "", (hostname != NULL) ? "\r\n" : ""); tcpWrite(s, webclientBuf, len); if (headers != NULL) { for ( ; *headers != 0; headers++) { tcpWrite(s, *headers, strlen(*headers)); tcpWrite(s, "\r\n", 2); } } tcpWrite(s, "\r\n", 2); // all done with headers // send the body...just check our last write here... if (tcpWrite(s, data, data_length) <= 0) { tcpClose(s); return -1; } // read back the response len = webclientReadResponse(s, data, maxresponse); tcpClose(s); return len; } return -1; }
/** Performs an HTTP GET operation to the path at the address / port specified. The data returned from the web server (up to maxresponse bytes) is written into the given buffer. @param hostname The name of the host to connect to. @param path The path on the server to connect to. @param port The port to connect on - standard http port is 80 @param response The buffer read the response back into. @param maxresponse An integer specifying the size of the response buffer. @param headers (optional) An array of strings to be sent as headers - last element in the array must be 0. @return the number of bytes received, or < 0 on error. \b Example \code #define BUF_LENGTH 100 char myBuffer[BUF_LENGTH]; int justGot = webclientGet("www.makingthings.com", "/test/path", 80, myBuffer, BUF_LENGTH, 0); \endcode Now we should have the results of the HTTP GET from \b www.makingthings.com/test/path in \b myBuffer. */ int webclientGet(const char* hostname, const char* path, int port, char* response, int maxresponse, const char* headers[]) { int s = tcpOpen(networkGetHostByName(hostname), port); if (s > -1) { // construct the GET request int len = sniprintf(webclientBuf, WEBCLIENT_BUFFER_SIZE, "GET %s HTTP/1.1\r\n%s%s%s", path, (hostname != NULL) ? "Host: " : "", (hostname != NULL) ? hostname : "", (hostname != NULL) ? "\r\n" : "" ); tcpWrite(s, webclientBuf, len); if (headers != NULL) { for ( ; *headers != 0; headers++) { tcpWrite(s, *headers, strlen(*headers)); tcpWrite(s, "\r\n", 2); } } if (tcpWrite(s, "\r\n", 2 ) < 0) { // all done with headers...just check our last write here... tcpClose(s); return -1; } // read the data into the given buffer until there's none left, or the passed in buffer is full len = webclientReadResponse(s, response, maxresponse); tcpClose(s); return len; } return -1; }
// Connect this connection/socket void clientRequestConnect(JsNetwork *net, JsVar *httpClientReqVar) { // Have we already connected? If so, don't go further if (jsvGetIntegerAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SOCKET, 0))>0) return; SocketType socketType = socketGetType(httpClientReqVar); JsVar *options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, false); unsigned short port = (unsigned short)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0)); char hostName[128]; JsVar *hostNameVar = jsvObjectGetChild(options, "host", 0); if (jsvIsUndefined(hostNameVar)) strncpy(hostName, "localhost", sizeof(hostName)); else jsvGetString(hostNameVar, hostName, sizeof(hostName)); jsvUnLock(hostNameVar); uint32_t host_addr = 0; networkGetHostByName(net, hostName, &host_addr); if(!host_addr) { jsError("Unable to locate host\n"); // As this is already in the list of connections, an error will be thrown on idle anyway jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true)); jsvUnLock(options); netCheckError(net); return; } NetCreateFlags flags = NCF_NORMAL; #ifdef USE_TLS if (socketType & ST_TLS) { flags |= NCF_TLS; if (port==0) port = 443; } #endif if (port==0) port = 80; int sckt = netCreateSocket(net, host_addr, port, flags, options); if (sckt<0) { jsError("Unable to create socket\n"); // As this is already in the list of connections, an error will be thrown on idle anyway jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true)); } else { jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_SOCKET, jsvNewFromInteger(sckt+1)); } jsvUnLock(options); netCheckError(net); }
// Connect this connection/socket void clientRequestConnect(JsNetwork *net, JsVar *httpClientReqVar) { SocketType socketType = socketGetType(httpClientReqVar); clientRequestWrite(httpClientReqVar, 0); // force sendData to be made JsVar *options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, false); unsigned short port = (unsigned short)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0)); if (port==0) port=80; char hostName[128]; JsVar *hostNameVar = jsvObjectGetChild(options, "host", 0); if (jsvIsUndefined(hostNameVar)) strncpy(hostName, "localhost", sizeof(hostName)); else jsvGetString(hostNameVar, hostName, sizeof(hostName)); jsvUnLock(hostNameVar); uint32_t host_addr = 0; networkGetHostByName(net, hostName, &host_addr); if(!host_addr) { jsError("Unable to locate host"); jsvUnLock(jsvObjectSetChild(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true))); jsvUnLock(options); net->checkError(net); return; } int sckt = net->createsocket(net, host_addr, port); if (sckt<0) { jsError("Unable to create socket\n"); jsvUnLock(jsvObjectSetChild(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true))); } else { jsvUnLock(jsvObjectSetChild(httpClientReqVar, HTTP_NAME_SOCKET, jsvNewFromInteger(sckt+1))); // For HTTP we get the connection callback when we've got a header back // Otherwise we just call back on success if (socketType != ST_HTTP) { jsiQueueObjectCallbacks(httpClientReqVar, HTTP_NAME_ON_CONNECT, &httpClientReqVar, 1); } } jsvUnLock(options); net->checkError(net); }