Example #1
0
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;
}
Example #2
0
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;
}
Example #4
0
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;
}
Example #6
0
    /**
     * 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;
    }
Example #7
0
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;
}