void test_parse_http(void* data) { (void)(data); // prepare structure http_response_t response; memset( &response, 0, sizeof( http_response_t ) ); // simplest { const char test_response[] = "HTTP/1.1 200 OK\r\n" "Date: Sun, 14 Apr 2013 20:20:01 GMT\r\n" "Content-Type: text/plain; charset=utf-8\r\n" "Content-Length: 0\r\n" "Connection: keep-alive\r\n" "X-Request-Id: 9de9ac7071bdbf105804ce0eaf7979adc77f6e25\r\n" "Cache-Control: max-age=0\r\n" "Vary: Accept-Encoding\r\n\r\n"; http_response_t* ret = parse_http( &response, test_response ); tt_assert( ret != 0 ); tt_assert( ret->http_headers_size == 7 ); } memset( &response, 0, sizeof( http_response_t ) ); xi_set_err( XI_NO_ERR ); // with content { const char test_response[] = "HTTP/1.1 404 Not Found\r\n" "Date: Sun, 14 Apr 2013 20:20:01 GMT\r\n" "Content-Type: text/plain; charset=utf-8\r\n" "Content-Length: 9\r\n" "Connection: keep-alive\r\n" "Vary: Accept-Encoding\r\n\r\n" "Not Found"; http_response_t* ret = parse_http( &response, test_response ); tt_assert( ret != 0 ); tt_assert( ret->http_headers_size == 5 ); tt_assert( strcmp( ret->http_content, "Not Found" ) == 0 ); } memset( &response, 0, sizeof( http_response_t ) ); xi_set_err( XI_NO_ERR ); /* Every test-case function needs to finish with an "end:" label and (optionally) code to clean up local variables. */ end: xi_set_err( XI_NO_ERR ); ; }
void Socket::http_get(const char *uri, std::vector<std::string>& header, std::vector<std::string>& resheader, std::vector<unsigned char>& resdata) { resheader.clear(); resdata.clear(); if (strncmp(uri, "http://", 7) != 0) { return; } http_request_t http = parse_http(uri); socket(AF_INET, SOCK_STREAM, 0); connect(http.name.c_str(), http.port); std::string req; req = std::string("GET ") + http.query + " HTTP/1.1\r\n"; req += std::string("User-Agent: ") + USER_AGENT + "\r\n"; req += std::string("Host: ") + http.name + "\r\n"; for (std::vector<std::string>::iterator it = header.begin(); it != header.end(); it++ ) { req += *it; req += "\r\n"; } req += "\r\n"; write(req.c_str(), req.size()); parse_http_result(resheader, resdata); }
void Socket::http_post(char const *uri, char const *content, size_t contentlen, std::vector<std::string> const *header, std::vector<std::string> *resheader, std::vector<unsigned char> *resdata) { resheader->clear(); resdata->clear(); if (strncmp(uri, "http://", 7) != 0) { return; } http_request_t http = parse_http(uri); socket(AF_INET, SOCK_STREAM, 0); connect(http.name.c_str(), http.port); std::string req; req = "POST "; req += http.query; req += " HTTP/1.1\r\n"; std::vector<std::string> preheader; preheader.push_back(std::string("User-Agent: ") + USER_AGENT); preheader.push_back("Host: " + http.name); preheader.push_back("Accept: */*"); preheader.push_back("Content-Length: " + to_s(contentlen)); preheader.push_back("Content-Type: application/x-www-form-urlencoded"); for (std::vector<std::string>::const_iterator it = preheader.begin(); it != preheader.end(); it++) { req += *it; req += "\r\n"; } if (header) { for (std::vector<std::string>::const_iterator it = header->begin(); it != header->end(); it++) { req += *it; req += "\r\n"; } } req += "\r\n"; write(req.c_str(), req.size()); write(content, contentlen); // std::vector<unsigned char> data; read(&data); if (!data.empty()) { unsigned char const *begin = &data[0]; unsigned char const *end = begin + data.size(); parse_http_result(begin, end, resheader, resdata); } }
void Socket::http_post(const char *uri, std::vector<std::string>& header, const void *content, size_t contentlen, const char *contet_type, std::vector<std::string>& resheader, std::vector<unsigned char>& resdata) { resheader.clear(); resdata.clear(); if (strncmp(uri, "http://", 7) != 0) { return; } http_request_t http = parse_http(uri); socket(AF_INET, SOCK_STREAM, 0); connect(http.name.c_str(), http.port); std::string req; req = std::string("POST ") + http.query + " HTTP/1.1\r\n"; req += std::string("User-Agent: ") + USER_AGENT + "\r\n"; req += std::string("Host: ") + http.name + "\r\n"; req += std::string("Content-Length: ") + to_s(contentlen) + "\r\n"; if (contet_type) { req += std::string("Content-Type: ") + contet_type + "\r\n"; } else { req += std::string("Content-Type: application/x-www-form-urlencoded\r\n"); } for (std::vector<std::string>::iterator it = header.begin(); it != header.end(); it++ ) { req += *it; req += "\r\n"; } req += "\r\n"; //OutputDebugStringA(req.c_str()); write(req.c_str(), req.size()); write(content, contentlen); parse_http_result(resheader, resdata); //OutputDebugStringA((const char*)&resdata[0]); }
//parsing to first http message line int parse(char *inlin, char **commandp, char **serverp, char**pathp, char **protocolp, char **portp) { char *requests[3] = {NULL,NULL,NULL}; //delimeter to initial message char deli[] = " "; //token for delimeter char *token = strtok(inlin,deli); //while index int index = 0; //parse the first request header while(index <3) { requests[index] = token; token = strtok(NULL,deli); index++; } if(index == 3){ char* server_host = parse_http(requests[1]); char cpserver[CLIBUFF_SIZE]; strcpy(cpserver,server_host); char* server_filepath = strstr(server_host,"/"); char* server_hostNport = strtok(cpserver,"/"); char* server_hostname = strtok(server_hostNport,":");//hostname char* server_port = strtok(NULL,":");//port number *commandp = requests[0]; *serverp = server_hostname; *pathp = server_filepath; *protocolp = requests[2]; *portp = server_port; // free(cpserver); return 1; } return 0; }
void ICACHE_FLASH_ATTR server_recv_cb(void *arg, char *http_raw, unsigned short length) { struct espconn *pespconn = (struct espconn *)arg; //print("[server_recv_cb] Received data:"); char method[10]; char path[60]; char headers[60]; char body[256]; parse_http(http_raw, length, method, path, headers, body); int GET = (os_strcmp(method, "GET") == 0); int POST = (os_strcmp(method, "POST") == 0); if (GET) { // No body if not [post/put/patch]ing // Static files if (os_strcmp(path, "/base.css") == 0) { send_ok(pespconn, base_css); } else if (os_strcmp(path, "/connect.js") == 0) { send_ok(pespconn, connect_js); } else if (os_strcmp(path, "/register.js") == 0) { send_ok(pespconn, register_js); } // JSON responses else if (os_strcmp(path, "/connection.json") == 0) { int station_connect_status = wifi_station_get_connect_status(); if (station_connect_status == STATION_GOT_IP) { struct ip_info ipConfig; wifi_get_ip_info(STATION_IF, &ipConfig); char json_str[54]; os_sprintf(json_str, "{\"status\": \"connected\", \"ip\": \"%d.%d.%d.%d\"}", IP2STR(&ipConfig.ip)); send_json(pespconn, json_str); } else { char *status_str; if (connection_status == CONNECTION_UNCONFIGURED) status_str = "unconfigured"; else switch (station_connect_status) { case STATION_CONNECTING: status_str = "connecting"; break; case STATION_WRONG_PASSWORD: status_str = "failed"; break; case STATION_NO_AP_FOUND: status_str = "failed"; break; case STATION_CONNECT_FAIL: status_str = "failed"; break; } char json_str[54]; os_sprintf(json_str, "{\"status\": \"%s\"}", status_str); send_json(pespconn, json_str); } } else if (os_strcmp(path, "/registration.json") == 0) { char *status_str; switch (registration_status) { case REGISTER_UNREGISTERED: status_str = "unregistered"; break; case REGISTER_REGISTERING: status_str = "registering"; break; case REGISTER_REGISTERED: status_str = "registered"; break; case REGISTER_FAILED: status_str = "failed"; break; } char json_str[54]; os_sprintf(json_str, "{\"status\": \"%s\"}", status_str); send_json(pespconn, json_str); } // HTML pages else if (os_strcmp(path, "/read") == 0) { if (registration_status == REGISTER_REGISTERED) { char temp_json_str[128]; char hum_json_str[128]; measurement_json(temp_json_str, "temperature", "F", last_temp); measurement_json(hum_json_str, "humidity", "%", last_hum); char full_json_str[256] = ""; strcat(full_json_str, temp_json_str); strcat(full_json_str, hum_json_str); full_json_str[os_strlen(temp_json_str)+os_strlen(hum_json_str)] = 0; send_ok_templated(pespconn, full_json_str); } else { send_ok_templated(pespconn, last_unknown); } } else if (os_strcmp(path, "/register") == 0) { send_ok_templated(pespconn, register_html); } else if (os_strcmp(path, "/scan.json") == 0) { char json_str[256] = "["; int si = 0; for (; si < n_scanned; si++) { char json_obj[100]; os_sprintf(json_obj, "{\"ssid\": \"%s\", \"rssi\": %d}", scanned_stations[si], scanned_dbs[si]); os_strcat(json_str, json_obj); if (si < n_scanned - 1) { os_strcat(json_str, ","); } else { os_strcat(json_str, "]"); } } send_json(pespconn, json_str); } else if (os_strcmp(path, "/") == 0) { send_ok_templated(pespconn, index_html); } else { send_404(pespconn); } return; } else if (POST) { // Parse JSON with jsmn jsmn_parser parser; jsmn_init(&parser); jsmntok_t tokens[32]; jsmnerr_t r; r = jsmn_parse(&parser, body, 1024, tokens, 256); if (r < 0) { //print("JSON Parse error?"); return; } // Look for ssid and pass char station_ssid[20]; char station_pass[20]; //print("JSON Parse success?"); if (os_strcmp(path, "/connect.json") == 0) { // Parse ssid and pass from JSON int ti = 0; int has_ssid = 0; int has_pass = 0; int on_ssid = 0; int on_pass = 0; for(; tokens[ti].end; ti++) { char tv[256]; token_string(tv, body, tokens[ti]); if (on_ssid) { //print("Found ssid"); on_ssid = 0; os_strcpy(station_ssid, tv); has_ssid = 1; } if (on_pass) { //print("Found pass"); on_pass = 0; os_strcpy(station_pass, tv); has_pass = 1; if (has_ssid) { break; } } on_ssid = ti % 2 == 1 && os_strcmp(tv, "ssid") == 0; on_pass = ti % 2 == 1 && os_strcmp(tv, "pass") == 0; } //ets_uart_printf("Hopefully ssid=%s and pass=%s\r\n", station_ssid, station_pass); send_ok(pespconn, "<h1>maia</h1><p>OK</p>"); setup_station(station_ssid, station_pass); } else if (os_strcmp(path, "/register.json") == 0) { // Parse email and password from JSON int ti = 0; char user_email[64]; char user_password[64]; int has_email = 0; int has_password = 0; int on_email = 0; int on_password = 0; for(; tokens[ti].end; ti++) { char tv[256]; token_string(tv, body, tokens[ti]); if (on_email) { //print("Found email"); on_email = 0; os_strcpy(user_email, tv); has_email = 1; } if (on_password) { //print("Found password"); on_password = 0; os_strcpy(user_password, tv); has_password = 1; if (has_email) { break; } } on_email = ti % 2 == 1 && os_strcmp(tv, "email") == 0; on_password = ti % 2 == 1 && os_strcmp(tv, "password") == 0; } char register_response[256]; os_sprintf(register_response, "Registering as %d...", DEVICE_ID); send_ok_templated(pespconn, register_response); char register_json[256]; os_sprintf(register_json, "{" "\"device_id\": \"0x%x\"," "\"kind\": \"%s\"," "\"email\": \"%s\"," "\"password\": \"%s\"" "}", DEVICE_ID, DEVICE_KIND, user_email, user_password); registration_status = REGISTER_REGISTERING; post_json(API_BASE "/devices.json", register_json); } else { send_404(pespconn); } return; } send_404(pespconn); return; }