/** * Stream the contents of a file to a given URL. * @param fileContents :: The contents of the file to publish. * @param uploadURL :: The REST URL to stream the data from the file to. */ void CatalogPublish::publish(std::istream &fileContents, const std::string &uploadURL) { try { Poco::URI uri(uploadURL); std::string path(uri.getPathAndQuery()); Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> certificateHandler = new Poco::Net::AcceptCertificateHandler(true); // Currently do not use any means of authentication. This should be updated // IDS has signed certificate. const Poco::Net::Context::Ptr context = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE); // Create a singleton for holding the default context. E.g. any future // requests to publish are made to this certificate and context. Poco::Net::SSLManager::instance().initializeClient(NULL, certificateHandler, context); Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), context); // Send the HTTP request, and obtain the output stream to write to. E.g. the // data to publish to the server. Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_PUT, path, Poco::Net::HTTPMessage::HTTP_1_1); // Sets the encoding type of the request. This enables us to stream data to // the server. request.setChunkedTransferEncoding(true); std::ostream &os = session.sendRequest(request); // Copy data from the input stream to the server (request) output stream. Poco::StreamCopier::copyStream(fileContents, os); // Close the request by requesting a response. Poco::Net::HTTPResponse response; // Store the response for use IF an error occurs (e.g. 404). std::istream &responseStream = session.receiveResponse(response); // Obtain the status returned by the server to verify if it was a success. Poco::Net::HTTPResponse::HTTPStatus HTTPStatus = response.getStatus(); // The error message returned by the IDS (if one exists). std::string IDSError = CatalogAlgorithmHelper().getIDSError(HTTPStatus, responseStream); // Cancel the algorithm and display the message if it exists. if (!IDSError.empty()) { // As an error occurred we must cancel the algorithm. // We cannot throw an exception here otherwise it is caught below as // Poco::Exception catches runtimes, // and then the I/O error is thrown as it is generated above first. this->cancel(); // Output an appropriate error message from the JSON object returned by // the IDS. g_log.error(IDSError); } } catch (Poco::Net::SSLException &error) { throw std::runtime_error(error.displayText()); } // This is bad, but is needed to catch a POCO I/O error. // For more info see comments (of I/O error) in CatalogDownloadDataFiles.cpp catch (Poco::Exception &) { } }
/** * Downloads datafiles from the archives, and saves to the users save default directory. * @param URL :: The URL of the file to download. * @param fileName :: The name of the file to save to disk. * @return The full path to the saved file. */ std::string CatalogDownloadDataFiles::doDownloadandSavetoLocalDrive(const std::string& URL,const std::string& fileName) { std::string pathToDownloadedDatafile; clock_t start; try { Poco::URI uri(URL); std::string path(uri.getPathAndQuery()); start=clock(); Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> certificateHandler = new Poco::Net::AcceptCertificateHandler(true); // Currently do not use any means of authentication. This should be updated IDS has signed certificate. const Poco::Net::Context::Ptr context = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE); // Create a singleton for holding the default context. E.g. any future requests to publish are made to this certificate and context. Poco::Net::SSLManager::instance().initializeClient(NULL, certificateHandler,context); Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), context); Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1); session.sendRequest(request); // Close the request by requesting a response. Poco::Net::HTTPResponse response; // Store the response for use IF an error occurs (e.g. 404). std::istream& responseStream = session.receiveResponse(response); // Obtain the status returned by the server to verify if it was a success. Poco::Net::HTTPResponse::HTTPStatus HTTPStatus = response.getStatus(); // The error message returned by the IDS (if one exists). std::string IDSError = CatalogAlgorithmHelper().getIDSError(HTTPStatus, responseStream); // Cancel the algorithm and display the message if it exists. if(!IDSError.empty()) { // As an error occurred we must cancel the algorithm to prevent success message. this->cancel(); // Output an appropriate error message from the JSON object returned by the IDS. g_log.error(IDSError); return ""; } // Save the file to local disk if no errors occurred on the IDS. pathToDownloadedDatafile = saveFiletoDisk(responseStream,fileName); clock_t end=clock(); float diff = float(end - start)/CLOCKS_PER_SEC; g_log.information()<<"Time taken to download file "<< fileName<<" is "<<std::fixed << std::setprecision(2) << diff <<" seconds" << std::endl; } catch(Poco::Net::SSLException& error) { throw std::runtime_error(error.displayText()); } // A strange error occurs (what returns: {I/O error}, while message returns: { 9: The BIO reported an error }. // This bug has been fixed in POCO 1.4 and is noted - http://sourceforge.net/p/poco/bugs/403/ // I have opted to catch the exception and do nothing as this allows the load/download functionality to work. // However, the port the user used to download the file will be left open. catch(Poco::Exception&) {} return pathToDownloadedDatafile; }