pplx::task<http_response> client::http_client::request(http_request request, pplx::cancellation_token token) { if(!request.headers().has(header_names::user_agent)) { request.headers().add(header_names::user_agent, USERAGENT); } request._set_base_uri(base_uri()); request._set_cancellation_token(token); return m_pipeline->propagate(request); }
void MetaCDNReceiver::handle_delete(http_request message) { /* Use cases: 1. when CDN deletes a file from itself to store some other file because of its limited capacity JSON Format Request { "FileName": "a.txt", "CdnId" : 2 } Response: status OK or Forbidden (no json object included) */ try { int result; if(message.headers().content_type()==U("application/json")) { cout << endl << "---------------"<< endl; cout << message.to_string() << endl <<endl; json::value jsonObj = message.extract_json().get(); int cdnId = jsonObj.at(U("CdnId")).as_integer(); string fileName = utility::conversions::to_utf8string(jsonObj.at(U("FileName")).as_string()); result = m_meta->deleteCdnFromMetaEntry(fileName, cdnId); message.reply(status_codes::OK, result==0? U("Deleted successfully") : U("Delete failed")); } else { message.reply(status_codes::Forbidden, U("Json object is required")); } } catch(json::json_exception &e) { message.reply(status_codes::Forbidden, U("Invalid json object")); return; } }
void MetaCDNReceiver::handle_register(http_request message) { /* -when a new CDN joins, it has to register itself to Meta Server JSON Format Request { "Type": 0, //0=for cdn, 1=for fss "IP": "1.1.1.1:4000", //the sender CDN's IP address + port(listening to incoming requests) "Lat": 23.00, //the sender CDN's location "Lng": 148.12 } Response { "CdnId": 1 //the assigned id for the cdn } */ try { int assignedId = -1; if(message.headers().content_type()==U("application/json")) { cout << endl << "---------------"<< endl; cout << message.to_string() << endl <<endl; json::value jsonObj = message.extract_json().get(); if(jsonObj.at(U("Type")).as_integer() == 0) { string ipAddr = utility::conversions::to_utf8string(jsonObj.at(U("IP")).as_string()); //TODO: validate ip address Address cdnAddr(make_pair(jsonObj.at(U("Lat")).as_double(), jsonObj.at(U("Lng")).as_double()), ipAddr); assignedId = m_meta->registerCdn(cdnAddr); json::value respFinal = json::value::object(); respFinal[U("CdnId")] = json::value::number(assignedId); message.reply(assignedId!=-1? status_codes::OK : status_codes::NotFound, respFinal); } else if(jsonObj.at(U("Type")).as_integer() == 1){ string ipAddr = utility::conversions::to_utf8string(jsonObj.at(U("IP")).as_string()); //TODO: validate ip address Address fssAddr(make_pair(jsonObj.at(U("Lat")).as_double(), jsonObj.at(U("Lng")).as_double()), ipAddr); m_meta->setFssAddr(fssAddr); message.reply(status_codes::OK, "FSS registration complete"); } else { message.reply(status_codes::Forbidden, U("Invalid type")); } } else { message.reply(status_codes::Forbidden, U("Json object is required")); } } catch(json::json_exception &e) { message.reply(status_codes::Forbidden, U("Invalid json object")); return; } }
boost::tribool request_parser::parse_line(http_request &request, const std::string &line) { if (line.empty() || line[line.size() - 1] != '\r') return false; const bool is_empty_line = line.compare(0, line.size(), "\r", 1) == 0; switch (m_state_new) { case request_line: { if (is_empty_line) { // Ignore CRLF characters between requests in Keep-Alive connection return boost::indeterminate; } const auto first_space = line.find(' '); if (first_space == std::string::npos) return false; request.set_method(line.substr(0, first_space)); const auto second_space = line.find(' ', first_space + 1); if (second_space == std::string::npos) return false; request.set_url(line.substr(first_space + 1, second_space - first_space - 1)); if (line.compare(second_space + 1, 5, "HTTP/", 5) != 0) return false; const auto version_major_start = second_space + 1 + 5; const auto dot = line.find('.', version_major_start); if (dot == std::string::npos) return false; const auto version_minor_end = line.find('\r', dot); if (version_minor_end == std::string::npos) return false; boost::tribool result = boost::indeterminate; const auto major_version = parse_int(line.data() + version_major_start, line.data() + dot, result); const auto minor_version = parse_int(line.data() + dot + 1, line.data() + version_minor_end, result); request.set_http_version(major_version, minor_version); m_state_new = header_line; return result; } case header_line: { if (!m_header.first.empty() && (line[0] == ' ' || line[0] == '\t')) { // any number of LWS is allowed after field, rfc 2068 auto begin = line.begin() + 1; auto end = line.end(); trim_line(begin, end); m_header.second += ' '; m_header.second.append(begin, end); return boost::indeterminate; } if (!m_header.first.empty()) { request.headers().add(m_header); m_header.first.resize(0); m_header.second.resize(0); } if (is_empty_line) { return true; } const auto colon = line.find(':'); if (colon == std::string::npos) return false; auto name_begin = line.begin(); auto name_end = line.begin() + colon; trim_line(name_begin, name_end); m_header.first.assign(name_begin, name_end); auto value_begin = line.begin() + colon + 1; auto value_end = line.end(); trim_line(value_begin, value_end); m_header.second.assign(value_begin, value_end); return boost::indeterminate; } } return false; }
void MetaCDNReceiver::handle_update(http_request message) { /* Use cases: 0. when CDN pulls a file from FSS (syncdown flow) 1. when CDN updates an existing file (syncup flow; need invalidation process) 2. when CDN creates a new file and stores in FSS and itself JSON Format Request { "Type": 0, // 0=CDN pulls a file from FSS, 1=CDN updates a file (+invalidation process), 2=CDN creates a new file and stores in FSS "FileName": "a.txt", "FileHash": "ahash", //could be empty string when Type=0 //only for type 1,2 "CdnId": 1 "TimeStamp": "12312312312" //REQUIRED for use case 1 and 2 } Response: status OK or Forbidden (no json object included) */ try { if(message.headers().content_type()==U("application/json")) { cout << endl << "---------------"<< endl; cout << message.to_string() << endl <<endl; json::value jsonObj = message.extract_json().get(); int cdnId = jsonObj.at(U("CdnId")).as_integer(); string fileName = utility::conversions::to_utf8string(jsonObj.at(U("FileName")).as_string()); int result; if(jsonObj.at(U("Type")).as_integer() == 0) { result = m_meta->addCdnToMetaEntry(fileName, cdnId); } else if(jsonObj.at(U("Type")).as_integer() == 1) { string fileHash = utility::conversions::to_utf8string(jsonObj.at(U("FileHash")).as_string()); vector<int> newCdnList; newCdnList.push_back(cdnId); result = m_meta->updateMetaEntry(fileName, fileHash, newCdnList); if(result == 0) { result = m_meta->updateTimeStamp(fileName, jsonObj.at(U("TimeStamp")).as_string()); } else { cout<<"MetaCDNReceiver::handle_update() - failed to update meta entry"<<endl; return; } //now, send invalidation msgs to other cdns unordered_map<int, Address>::const_iterator itr = m_meta->getCdnIdToAddrMap().begin(); while(itr != m_meta->getCdnIdToAddrMap().end()) { if(itr->first == cdnId) { ++itr; continue; } http_client cdn_client = http_client("http://" + itr->second.ipAddr); http_response resp = cdn_client.request(methods::DEL, "cdn/cache"+fileName).get(); if (resp.status_code() != status_codes::OK) { cout<<"MetaCDNReceiver::handle_update() - failed to send invalidation message to "+itr->second.ipAddr<<endl; } ++itr; } } else if(jsonObj.at(U("Type")).as_integer() == 2) { string fileHash = utility::conversions::to_utf8string(jsonObj.at(U("FileHash")).as_string()); vector<int> newCdnList; newCdnList.push_back(cdnId); result = m_meta->addNewMetaEntry(fileName, fileHash, newCdnList); if(result == 0) result = m_meta->addNewTimeStamp(fileName, jsonObj.at(U("TimeStamp")).as_string()); } else { message.reply(status_codes::Forbidden, U("Undefined Type")); return; } message.reply(result==0? status_codes::OK : status_codes::NotFound, result==0? U("Updated successfully") : U("Update failed")); } else { message.reply(status_codes::Forbidden, U("Json object is required")); } } catch(json::json_exception &e) { message.reply(status_codes::Forbidden, U("Invalid json object")); return; } }
// Handler to process HTTP::GET requests. // Replies to the request with data. void odata_test_service::handle_get(http_request message) { try { bool is_async = false; auto prefer_header = message.headers().find(U("Prefer")); if (prefer_header != message.headers().end()) { if (prefer_header->second.find(U("respond-async")) != ::odata::utility::string_t::npos) { is_async = true; } } auto parsed_uri = m_uri_parser->parse_uri(message.relative_uri()); odata_message_writer writer(m_model, m_service_root); odata_context_url_builder context_url_builder(m_model, m_service_root); odata_metadata_builder metadata_builder(m_model, m_service_root); ::odata::utility::string_t content; if (parsed_uri->is_service_document()) { // Write service document content = writer.write_service_document(m_service_document); } else if (parsed_uri->is_metadata_document()) { // Write metadata document content = writer.write_metadata_document(); } else { if (parsed_uri->path()->size() >= 1) { if (parsed_uri->path()->segment_at(0)->segment_type() == odata_path_segment_type::EntitySet) { auto entity_set_segment = parsed_uri->path()->segment_at(0)->as<odata_entity_set_segment>(); if (entity_set_segment->entity_set()->get_name() == U("People")) { if (parsed_uri->path()->size() == 1) { auto people = get_people(); auto context_url = context_url_builder.get_context_uri_for_collection_of_entities(entity_set_segment->entity_set()); people->set_context_url(context_url); if (is_async) { std::unordered_map<string_t, string_t> headers; headers[U("OData-Version")] = U("4.0"); headers[U("Content-Type")] = U("application/json;odata.metadata=full"); content = writer.write_asynchronous_odata_value(people, 200, U("OK"), headers); } else { content = writer.write_odata_value(people); } } else if (parsed_uri->path()->segment_at(1)->segment_type() == odata_path_segment_type::Key) { auto key_segment = parsed_uri->path()->segment_at(1)->as<odata_key_segment>(); auto key = key_segment->keys()[0].second->as<::odata::utility::string_t>(); auto single_person = get_single_people(key); single_person->set_is_top_level(true); auto context_url = context_url_builder.get_context_uri_for_entity(entity_set_segment->entity_set()); single_person->set_context_url(context_url); auto id = metadata_builder.get_entity_id(single_person, entity_set_segment->entity_set()); single_person->set_id(id); auto read_link = metadata_builder.get_read_link(single_person, entity_set_segment->entity_set()); single_person->set_read_link(read_link); auto edit_link = metadata_builder.get_edit_link(single_person, entity_set_segment->entity_set()); single_person->set_edit_link(edit_link); content = writer.write_odata_value(single_person); } } } } } message.reply(status_codes::OK, content).then(std::bind(&handle_error, std::placeholders::_1)); } catch (::odata::core::odata_exception &e) { message.reply(status_codes::BadRequest, U("Exception: ") + e.what()).then(std::bind(&handle_error, std::placeholders::_1)); } ////Get odata objects from resorce and odata_path // }
void RestEngineUri::handle_post(http_request request) { std::cout << request.method() << " : " << request.absolute_uri().path() << std::endl; std::cout << request.method() << " : " << request.headers()["Cookie"] << std::endl; int rc = 0; std::string resultstr; std::pair<bool, std::string> result {true, std::string()}; std::string cookie = request.headers()["Cookie"]; if (cookie != "session_cookie=" + _active_session_token) { //http_response response(status_codes::Locked); //make_response(response, resultstr, result); //request.reply(response); //return; } if (!is_session_owner(request)) { send_busy_response(request); return; } ostringstream o; o << "COOKIE:" << cookie << std::endl; o << "ACTIVE COOKIE:" << _active_session_token << std::endl; std::cout << o.str(); log (m_s.masterlogfile,o.str()); char json[1024]; // extract json from request snprintf(json, sizeof(json), "%s", request.extract_string(true).get().c_str()); std::cout << "JSON:\n" << json << std::endl; rapidjson::Document document; if (document.Parse(json).HasParseError()) { rc = 1; resultstr += "document invalid"; } rapidjson::SchemaValidator validator(*_schema); if (!document.Accept(validator)) { rc = 1; resultstr += get_schema_validation_error(&validator); } std::string select_str; std::string hosts_list; const Value& hosts = document["hosts"]; json_to_host_list(hosts, hosts_list); const Value& select = document["select"]; json_to_select_str(select, select_str); // Execute Ivy Engine command if (rc == 0) { std::unique_lock<std::mutex> u_lk(goStatementMutex); std::string outputfolder = m_s.get("output_folder_root").second; std::string testname = m_s.get("test_name").second; result = m_s.startup(outputfolder, testname, m_s.ivyscript_filename, hosts_list, select_str); } http_response response(status_codes::OK); make_response(response, resultstr, result); request.reply(response); }