DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/HTTPClient
2024-12-25 07:49:36 +08:00

453 lines
14 KiB
C++

/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_HTTP_CLIENT_H
#define OSGEARTH_HTTP_CLIENT_H 1
#include <osgEarth/Common>
#include <osgEarth/IOTypes>
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <osgDB/ReaderWriter>
#include <sstream>
#include <iostream>
#include <string>
#include <map>
#include <vector>
namespace osgEarth
{
class ProgressCallback;
}
namespace osgEarth { namespace Util
{
using namespace osgEarth;
/**
* An HTTP request for use with the HTTPClient class.
*/
class OSGEARTH_EXPORT HTTPRequest
{
public:
/** Constructs a new HTTP request that will acces the specified base URL. */
HTTPRequest( const std::string& url );
/** copy constructor. */
HTTPRequest( const HTTPRequest& rhs );
/** dtor */
virtual ~HTTPRequest() { }
/** Adds an HTTP parameter to the request query string. */
void addParameter( const std::string& name, const std::string& value );
void addParameter( const std::string& name, int value );
void addParameter( const std::string& name, double value );
using Parameters = std::unordered_map<std::string, std::string>;
/** Ready-only access to the parameter list (as built with addParameter) */
const Parameters& getParameters() const;
//! Add a header name/value pair to an HTTP request
void addHeader( const std::string& name, const std::string& value );
//! Collection of headers in this request
const Headers& getHeaders() const;
//! Collection of headers in this request
Headers& getHeaders();
/**
* Sets the last modified date of any locally cached data for this request. This will
* automatically add a If-Modified-Since header to the request
*/
void setLastModified( const DateTime &lastModified );
/** Gets a copy of the complete URL (base URL + query string) for this request */
std::string getURL() const;
private:
Parameters _parameters;
Headers _headers;
std::string _url;
};
/**
* An HTTP response object for use with the HTTPClient class - supports
* multi-part mime responses.
*/
class OSGEARTH_EXPORT HTTPResponse
{
public:
enum Code {
NONE = 0,
OK = 200,
NOT_MODIFIED = 304,
BAD_REQUEST = 400,
FORBIDDEN = 403,
NOT_FOUND = 404,
CONFLICT = 409,
INTERNAL_SERVER_ERROR = 500
};
enum CodeCategory {
CATEGORY_UNKNOWN = 0,
CATEGORY_INFORMATIONAL = 100,
CATEGORY_SUCCESS = 200,
CATEGORY_REDIRECTION = 300,
CATEGORY_CLIENT_ERROR = 400,
CATEGORY_SERVER_ERROR = 500
};
public:
/** Constructs a response with the specified HTTP response code */
HTTPResponse( long code =0L );
/** Copy constructor */
HTTPResponse( const HTTPResponse& rhs );
/** dtor */
virtual ~HTTPResponse() { }
/** Gets the HTTP response code (Code) in this response */
unsigned getCode() const;
/** Gets the HTTP response code category for this response */
unsigned getCodeCategory() const;
/** True is the HTTP response code is OK (200) */
bool isOK() const;
/** True if the request associated with this response was cancelled before it completed */
void setCanceled(bool value) { _canceled = value; }
bool isCanceled() const { return _canceled; }
/** Gets the number of parts in a (possibly multipart mime) response */
unsigned int getNumParts() const;
/** Gets the input stream for the nth part in the response */
std::istream& getPartStream( unsigned int n ) const;
/** Gets the nth response part as a string */
std::string getPartAsString( unsigned int n ) const;
/** Gets the length of the nth response part */
unsigned int getPartSize( unsigned int n ) const;
/** Gets the HTTP header associated with the nth multipart/mime response part */
const std::string& getPartHeader( unsigned int n, const std::string& name ) const;
/** Gets the master mime-type returned by the request */
void setMimeType(const std::string& value) { _mimeType = value; }
const std::string& getMimeType() const;
/** How long did it take to fetch this response (in seconds) */
void setDuration(double value) { _duration_s = value; }
double getDuration() const { return _duration_s; }
void setMessage(const std::string& value) { _message = value; }
const std::string& getMessage() const { return _message; }
void setLastModified(TimeStamp value) { _lastModified = value; }
TimeStamp getLastModified() const { return _lastModified; }
bool getFromCache() const { return _fromCache; }
void setFromCache(bool fromCache) { _fromCache = fromCache; }
struct Part : public osg::Referenced
{
Part() : _size(0) { }
Headers _headers;
unsigned int _size;
std::stringstream _stream;
};
typedef std::vector< osg::ref_ptr<Part> > Parts;
Parts& getParts() { return _parts; }
private:
Parts _parts;
long _response_code;
std::string _mimeType;
bool _canceled;
double _duration_s;
TimeStamp _lastModified;
std::string _message;
bool _fromCache;
Config getHeadersAsConfig() const;
void setHeadersFromConfig(const Config& conf);
friend class HTTPClient;
};
/**
* Object that lets you modify and incoming URL before it's passed to the server
*/
struct OSGEARTH_EXPORT URLRewriter : public osg::Referenced
{
virtual std::string rewrite( const std::string& url ) = 0;
};
/**
* A configuration handler to apply settings. It can be used for setting client certificates
*/
struct OSGEARTH_EXPORT ConfigHandler : public osg::Referenced
{
virtual void onInitialize(void* handle) = 0;
virtual void onGet(void* handle) = 0;
};
/**
* Utility class for making HTTP requests.
*/
class OSGEARTH_EXPORT HTTPClient
{
public:
//! Interface for pluggable HTTP implementations
class Implementation : public osg::Referenced
{
public:
virtual void initialize() = 0;
virtual HTTPResponse doGet(
const HTTPRequest& request,
const osgDB::Options* options,
ProgressCallback* progress ) const = 0;
virtual void setUserAgent(const std::string&) { }
virtual void setTimeout(long) { }
virtual void setConnectTimeout(long) { }
//! Implementation-specific handle if applicable
virtual void* getHandle() const { return NULL; }
protected:
virtual ~Implementation() {}
};
//! Factory object to create implementation instances.
class ImplementationFactory
{
public:
virtual Implementation* create() const = 0;
virtual ~ImplementationFactory() {};
};
//! Install an implementation factory. Do this before anything else
static void setImplementationFactory(ImplementationFactory* factory);
/**
* Returns true is the result code represents a recoverable situation,
* i.e. one in which retrying might work.
*/
static bool isRecoverable(ReadResult::Code code)
{
return
code == ReadResult::RESULT_OK ||
code == ReadResult::RESULT_SERVER_ERROR ||
code == ReadResult::RESULT_TIMEOUT ||
code == ReadResult::RESULT_CANCELED;
}
/** Gets the user-agent string that all HTTP requests will use. */
static const std::string& getUserAgent();
/** Sets a user-agent string to use in all HTTP requests. */
static void setUserAgent(const std::string& userAgent);
/** Sets up proxy info to use in all HTTP requests. */
static void setProxySettings( const optional<ProxySettings> &proxySettings );
/** Gets up proxy info to use in all HTTP requests. */
static const optional<ProxySettings> & getProxySettings();
/**
Gets the timeout in seconds to use for HTTP requests.*/
static long getTimeout();
/**
Sets the timeout in seconds to use for HTTP requests.
Setting to 0 (default) is infinite timeout */
static void setTimeout( long timeout );
/** Sets the suggested delay (in seconds) before a retry should be attempted
in the case of a canceled request */
static void setRetryDelay(float value_seconds);
static float getRetryDelay();
/**
Gets the timeout in seconds to use for HTTP connect requests.*/
static long getConnectTimeout();
/**
Sets the timeout in seconds to use for HTTP connect requests.
Setting to 0 (default) is infinite timeout */
static void setConnectTimeout( long timeout );
/**
* Gets the URLRewriter that is used to modify urls before sending them to the server
*/
static URLRewriter* getURLRewriter();
/**
* Sets the URLRewriter that is used to modify urls before sending them to the server
*/
static void setURLRewriter( URLRewriter* rewriter );
static ConfigHandler* getConfigHandler();
/**
* Sets the CurlConfigHandler to configurate the CURL library. It can be used for apply client certificates
*/
static void setConfigHandler(ConfigHandler* handler);
/**
* One time thread safe initialization. In osgEarth, you don't need
* to call this directly; osgEarth::Registry will call it at
* startup.
*/
static void globalInit();
public:
/**
* Reads an image.
*/
static ReadResult readImage(
const HTTPRequest& request,
const osgDB::Options* dbOptions =0L,
ProgressCallback* progress =0L );
/**
* Reads an osg::Node.
*/
static ReadResult readNode(
const HTTPRequest& request,
const osgDB::Options* dbOptions =0L,
ProgressCallback* progress =0L );
/**
* Reads an object.
*/
static ReadResult readObject(
const HTTPRequest& request,
const osgDB::Options* dbOptions =0L,
ProgressCallback* progress =0L );
/**
* Reads a string.
*/
static ReadResult readString(
const HTTPRequest& request,
const osgDB::Options* dbOptions =0L,
ProgressCallback* progress =0L );
/**
* Downloads a file directly to disk.
*/
static bool download(
const std::string& uri,
const std::string& localPath );
public:
/**
* Performs an HTTP "GET".
*/
static HTTPResponse get( const HTTPRequest& request,
const osgDB::Options* dbOptions =0L,
ProgressCallback* progress =0L );
static HTTPResponse get( const std::string& url,
const osgDB::Options* options =0L,
ProgressCallback* progress =0L );
public:
HTTPClient();
virtual ~HTTPClient();
private:
void readOptions( const osgDB::ReaderWriter::Options* options, std::string &proxy_host, std::string &proxy_port ) const;
HTTPResponse doGet( const HTTPRequest& request,
const osgDB::Options* options =0L,
ProgressCallback* callback =0L ) const;
ReadResult doReadObject(
const HTTPRequest& request,
const osgDB::Options* dbOptions,
ProgressCallback* progress );
ReadResult doReadImage(
const HTTPRequest& request,
const osgDB::Options* dbOptions,
ProgressCallback* progress );
ReadResult doReadNode(
const HTTPRequest& request,
const osgDB::Options* dbOptions,
ProgressCallback* progress );
ReadResult doReadString(
const HTTPRequest& request,
const osgDB::Options* dbOptions,
ProgressCallback* progress );
/**
* Convenience method for downloading a URL directly to a file
*/
bool doDownload(const std::string& url, const std::string& filename);
private:
void* _curl_handle;
std::string _previousPassword;
long _previousHttpAuthentication;
bool _initialized;
long _simResponseCode;
osg::ref_ptr<Implementation> _impl;
void initialize() const;
void initializeImpl();
static ImplementationFactory* _implFactory;
static HTTPClient& getClient();
};
class OSGEARTH_EXPORT CURLHTTPImplementationFactory : public HTTPClient::ImplementationFactory
{
public:
HTTPClient::Implementation* create() const;
};
class OSGEARTH_EXPORT WinInetHTTPImplementationFactory : public HTTPClient::ImplementationFactory
{
public:
HTTPClient::Implementation* create() const;
};
} }
#endif // OSGEARTH_HTTP_CLIENT_H