ReadResult HTTPClient::doReadString(const std::string& location, const osgDB::Options* options, ProgressCallback* callback ) { initialize(); ReadResult result; HTTPResponse response = this->doGet( location, options, callback ); if ( response.isOK() ) { result = ReadResult( new StringObject(response.getPartAsString(0)), response.getHeadersAsConfig()); } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl; callback->setNeedsRetry( true ); } } } return result; }
ReadResult HTTPClient::doReadNode(const std::string& location, const osgDB::Options* options, ProgressCallback* callback) { initialize(); ReadResult result; HTTPResponse response = this->doGet(location, options, callback); if (response.isOK()) { osgDB::ReaderWriter* reader = getReader(location, response); if (!reader) { OE_WARN << LC << "Can't find an OSG plugin to read "<<location<<std::endl; result = ReadResult(ReadResult::RESULT_NO_READER); } else { osgDB::ReaderWriter::ReadResult rr = reader->readNode(response.getPartStream(0), options); if ( rr.validNode() ) { result = ReadResult(rr.takeNode(), response.getHeadersAsConfig()); } else { if ( !rr.message().empty() ) { OE_WARN << LC << "HTTP error: " << rr.message() << std::endl; } OE_WARN << LC << reader->className() << " failed to read node from " << location << std::endl; result = ReadResult(ReadResult::RESULT_READER_ERROR); } } } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl; callback->setNeedsRetry( true ); } } } return result; }
ReadResult HTTPClient::doReadString(const HTTPRequest& request, const osgDB::Options* options, ProgressCallback* callback ) { initialize(); ReadResult result; HTTPResponse response = this->doGet( request, options, callback ); if ( response.isOK() ) { result = ReadResult( new StringObject(response.getPartAsString(0)) ); } else if ( response.getCode() >= 400 && response.getCode() < 500 && response.getCode() != 404 ) { // for request errors, return an error result with the part data intact // so the user can parse it as needed. We only do this for readString. result = ReadResult( ReadResult::RESULT_SERVER_ERROR, new StringObject(response.getPartAsString(0)) ); } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : response.getCode() == HTTPResponse::NOT_MODIFIED ? ReadResult::RESULT_NOT_MODIFIED : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { if ( s_HTTP_DEBUG ) { OE_NOTICE << LC << "Error in HTTPClient for " << request.getURL() << " but it's recoverable" << std::endl; } callback->setNeedsRetry( true ); } } } // encode headers result.setMetadata( response.getHeadersAsConfig() ); // last-modified (file time) result.setLastModifiedTime( getCurlFileTime(_curl_handle) ); return result; }
ReadResult HTTPClient::doReadString(const std::string& location, const osgDB::Options* options, ProgressCallback* callback ) { initialize(); ReadResult result; HTTPResponse response = this->doGet( location, options, callback ); if ( response.isOK() ) { result = ReadResult( new StringObject(response.getPartAsString(0)), response.getHeadersAsConfig()); } else if ( response.getCode() >= 400 && response.getCode() < 500 && response.getCode() != 404 ) { // for request errors, return an error result with the part data intact // so the user can parse it as needed. We only do this for readString. result = ReadResult( ReadResult::RESULT_SERVER_ERROR, new StringObject(response.getPartAsString(0)), response.getHeadersAsConfig() ); } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl; callback->setNeedsRetry( true ); } } } // last-modified (file time) TimeStamp filetime = 0; if ( CURLE_OK == curl_easy_getinfo(_curl_handle, CURLINFO_FILETIME, &filetime) ) { result.setLastModifiedTime( filetime ); } return result; }
ReadResult HTTPClient::doReadObject(const HTTPRequest& request, const osgDB::Options* options, ProgressCallback* callback) { initialize(); ReadResult result; HTTPResponse response = this->doGet(request, options, callback); if (response.isOK()) { osgDB::ReaderWriter* reader = getReader(request.getURL(), response); if (!reader) { result = ReadResult(ReadResult::RESULT_NO_READER); } else { osgDB::ReaderWriter::ReadResult rr = reader->readObject(response.getPartStream(0), options); if ( rr.validObject() ) { result = ReadResult(rr.takeObject()); } else { if ( s_HTTP_DEBUG ) { OE_WARN << LC << reader->className() << " failed to read object from " << request.getURL() << "; message = " << rr.message() << std::endl; } result = ReadResult(ReadResult::RESULT_READER_ERROR); result.setErrorDetail( rr.message() ); } } // last-modified (file time) result.setLastModifiedTime( getCurlFileTime(_curl_handle) ); } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : response.getCode() == HTTPResponse::NOT_MODIFIED ? ReadResult::RESULT_NOT_MODIFIED : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { if ( s_HTTP_DEBUG ) { OE_NOTICE << LC << "Error in HTTPClient for " << request.getURL() << " but it's recoverable" << std::endl; } callback->setNeedsRetry( true ); } } } result.setMetadata( response.getHeadersAsConfig() ); return result; }
/** * Create and return an image for the given TileKey. */ osg::Image* createImage( const TileKey& key, ProgressCallback* progress ) { if (_debugDirect) { //osg::Image* image = new osg::Image; //image->allocateImage(256,256,1, GL_RGB, GL_UNSIGNED_BYTE); //return image; return osgDB::readImageFile( getDirectURI(key) ); //return URI(getDirectURI(key)).getImage(_dbOptions.get(), progress); } // center point of the tile (will be in spherical mercator) double x, y; key.getExtent().getCentroid(x, y); // transform it to lat/long: GeoPoint geo; GeoPoint( getProfile()->getSRS(), x, y ).transform( getProfile()->getSRS()->getGeographicSRS(), geo ); // contact the REST API. Docs are here: // http://msdn.microsoft.com/en-us/library/ff701716.aspx // construct the request URI: std::string request = Stringify() << std::setprecision(12) << _options.imageryMetadataAPI().get() // base REST API << "/" << _options.imagerySet().get() // imagery set to use << "/" << geo.y() << "," << geo.x() // center point in lat/long << "?zl=" << key.getLOD() + 1 // zoom level << "&o=json" // response format << "&key=" << _options.key().get(); // API key // check the URI cache. URI location; TileURICache::Record rec; if ( _tileURICache.get(request, rec) ) { location = URI(rec.value()); //CacheStats stats = _tileURICache.getStats(); //OE_INFO << "Ratio = " << (stats._hitRatio*100) << "%" << std::endl; } else { unsigned c = ++_apiCount; if ( c % 25 == 0 ) OE_INFO << LC << "API calls = " << c << std::endl; // fetch it: ReadResult metadataResult = URI(request).readString(_dbOptions, progress); if ( metadataResult.failed() ) { // check for a REST error: if ( metadataResult.code() == ReadResult::RESULT_SERVER_ERROR ) { OE_WARN << LC << "REST API request error!" << std::endl; Config metadata; std::string content = metadataResult.getString(); metadata.fromJSON( content ); ConfigSet errors = metadata.child("errorDetails").children(); for(ConfigSet::const_iterator i = errors.begin(); i != errors.end(); ++i ) { OE_WARN << LC << "REST API: " << i->value() << std::endl; } return 0L; } else { OE_WARN << LC << "Request error: " << metadataResult.getResultCodeString() << std::endl; } return 0L; } // decode it: Config metadata; if ( !metadata.fromJSON(metadataResult.getString()) ) { OE_WARN << LC << "Error decoding REST API response" << std::endl; return 0L; } // check the vintage field. If it's empty, that means we got a "no data" tile. Config* vintageEnd = metadata.find("vintageEnd"); if ( !vintageEnd || vintageEnd->value().empty() ) { OE_DEBUG << LC << "NO data image encountered." << std::endl; return 0L; } // find the tile URI: Config* locationConf= metadata.find("imageUrl"); if ( !locationConf ) { OE_WARN << LC << "REST API JSON parsing error (imageUrl not found)" << std::endl; return 0L; } location = URI( locationConf->value() ); _tileURICache.insert( request, location.full() ); } // request the actual tile //OE_INFO << "key = " << key.str() << ", URL = " << location->value() << std::endl; //osg::Image* image = location.getImage(_dbOptions.get(), progress); osg::Image* image = osgDB::readImageFile( location.full() ); if ( image && _geom.valid() ) { GeometryRasterizer rasterizer( image->s(), image->t() ); rasterizer.draw( _geom.get(), osg::Vec4(1,1,1,1) ); osg::ref_ptr<osg::Image> overlay = rasterizer.finalize(); ImageUtils::PixelVisitor<AlphaBlend> blend; blend.accept( overlay.get(), image ); } return image; }
ReadResult HTTPClient::doReadImage(const std::string& location, const osgDB::Options* options, ProgressCallback* callback) { initialize(); ReadResult result; HTTPResponse response = this->doGet(location, options, callback); if (response.isOK()) { osgDB::ReaderWriter* reader = getReader(location, response); if (!reader) { result = ReadResult(ReadResult::RESULT_NO_READER); } else { osgDB::ReaderWriter::ReadResult rr = reader->readImage(response.getPartStream(0), options); if ( rr.validImage() ) { result = ReadResult(rr.takeImage(), response.getHeadersAsConfig() ); } else { if ( !rr.message().empty() ) { OE_WARN << LC << "HTTP error: " << rr.message() << std::endl; } OE_WARN << LC << reader->className() << " failed to read image from " << location << std::endl; result = ReadResult(ReadResult::RESULT_READER_ERROR); } } // last-modified (file time) TimeStamp filetime = 0; if ( CURLE_OK == curl_easy_getinfo(_curl_handle, CURLINFO_FILETIME, &filetime) ) { result.setLastModifiedTime( filetime ); } } else { result = ReadResult( response.isCancelled() ? ReadResult::RESULT_CANCELED : response.getCode() == HTTPResponse::NOT_FOUND ? ReadResult::RESULT_NOT_FOUND : response.getCode() == HTTPResponse::SERVER_ERROR ? ReadResult::RESULT_SERVER_ERROR : ReadResult::RESULT_UNKNOWN_ERROR ); //If we have an error but it's recoverable, like a server error or timeout then set the callback to retry. if (HTTPClient::isRecoverable( result.code() ) ) { if (callback) { OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl; callback->setNeedsRetry( true ); } } } // set the source name if ( result.getImage() ) result.getImage()->setName( location ); return result; }