// 'end' this connection void clientRequestEnd(JsNetwork *net, JsVar *httpClientReqVar) { SocketType socketType = socketGetType(httpClientReqVar); if (socketType == ST_HTTP) { // on HTTP, this actually means we connect clientRequestConnect(net, httpClientReqVar); } else { // on normal sockets, we actually request close after all data sent jsvUnLock(jsvObjectSetChild(httpClientReqVar, HTTP_NAME_CLOSE, jsvNewFromBool(true))); } }
/*JSON{ "type" : "staticmethod", "class" : "net", "name" : "connect", "generate_full" : "jswrap_net_connect(options, callback, ST_NORMAL)", "params" : [ ["options","JsVar","An object containing host,port fields"], ["callback","JsVar","A function(res) that will be called when a connection is made. You can then call `res.on('data', function(data) { ... })` and `res.on('close', function() { ... })` to deal with the response."] ], "return" : ["JsVar","Returns a new net.Socket object"], "return_object" : "Socket" } Create a socket connection */ JsVar *jswrap_net_connect(JsVar *options, JsVar *callback, SocketType socketType) { bool unlockOptions = false; if (jsvIsString(options)) { options = jswrap_url_parse(options, false); unlockOptions = true; } if (!jsvIsObject(options)) { jsError("Expecting Options to be an Object but it was %t", options); return 0; } #ifdef USE_TLS if ((socketType&ST_TYPE_MASK) == ST_HTTP) { JsVar *protocol = jsvObjectGetChild(options, "protocol", 0); if (protocol && jsvIsStringEqual(protocol, "https:")) { socketType |= ST_TLS; } jsvUnLock(protocol); } #endif // Make sure we have a function as callback, or nothing (which is OK too) JsVar *skippedCallback = jsvSkipName(callback); if (!jsvIsUndefined(skippedCallback)) { if (!jsvIsFunction(skippedCallback)) { jsError("Expecting Callback Function but got %t", skippedCallback); jsvUnLock(skippedCallback); return 0; } jsvUnLock(skippedCallback); } else { callback = NULL; } JsVar *rq = clientRequestNew(socketType, options, callback); if (unlockOptions) jsvUnLock(options); if ((socketType&ST_TYPE_MASK) != ST_HTTP) { JsNetwork net; if (networkGetFromVarIfOnline(&net)) { clientRequestConnect(&net, rq); } networkFree(&net); } return rq; }
void clientRequestWrite(JsNetwork *net, JsVar *httpClientReqVar, JsVar *data) { SocketType socketType = socketGetType(httpClientReqVar); // Append data to sendData JsVar *sendData = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, 0); if (!sendData) { JsVar *options = 0; // Only append a header if we're doing HTTP AND we haven't already connected if ((socketType&ST_TYPE_MASK) == ST_HTTP) if (jsvGetIntegerAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SOCKET, 0))==0) options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, 0); if (options) { // We're an HTTP client - make a header JsVar *method = jsvObjectGetChild(options, "method", 0); JsVar *path = jsvObjectGetChild(options, "path", 0); sendData = jsvVarPrintf("%v %v HTTP/1.0\r\nUser-Agent: Espruino "JS_VERSION"\r\nConnection: close\r\n", method, path); jsvUnLock2(method, path); JsVar *headers = jsvObjectGetChild(options, "headers", 0); bool hasHostHeader = false; if (jsvIsObject(headers)) { JsVar *hostHeader = jsvObjectGetChild(headers, "Host", 0); hasHostHeader = hostHeader!=0; jsvUnLock(hostHeader); httpAppendHeaders(sendData, headers); // if Transfer-Encoding:chunked was set, subsequent writes need to 'chunk' the data that is sent if (jsvIsStringEqualAndUnLock(jsvObjectGetChild(headers, "Transfer-Encoding", 0), "chunked")) { jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CHUNKED, jsvNewFromBool(true)); } } jsvUnLock(headers); if (!hasHostHeader) { JsVar *host = jsvObjectGetChild(options, "host", 0); int port = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0)); if (port>0 && port!=80) jsvAppendPrintf(sendData, "Host: %v:%d\r\n", host, port); else jsvAppendPrintf(sendData, "Host: %v\r\n", host); jsvUnLock(host); } // finally add ending newline jsvAppendString(sendData, "\r\n"); } else { // !options // We're not HTTP (or were already connected), so don't send any header sendData = jsvNewFromString(""); } jsvObjectSetChild(httpClientReqVar, HTTP_NAME_SEND_DATA, sendData); jsvUnLock(options); } // We have data and aren't out of memory... if (data && sendData) { // append the data to what we want to send JsVar *s = jsvAsString(data, false); if (s) { if ((socketType&ST_TYPE_MASK) == ST_HTTP && jsvGetBoolAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_CHUNKED, 0))) { // If we asked to send 'chunked' data, we need to wrap it up, // prefixed with the length jsvAppendPrintf(sendData, "%x\r\n%v\r\n", jsvGetStringLength(s), s); } else { jsvAppendStringVarComplete(sendData,s); } jsvUnLock(s); } } jsvUnLock(sendData); if ((socketType&ST_TYPE_MASK) == ST_HTTP) { // on HTTP we connect after the first write clientRequestConnect(net, httpClientReqVar); } }