POCO C++库学习和分析 -- URI

POCO C++库学习和分析 -- URI (Uniform Resource Identifiers)



1. 概述

          URI(RFC 3986)意为统一资源标记,通常被用来标志web上的资源。
          在Poco库中提供了POCO::URI、POCO::URIStreamFactory、POCO::URIStreamOpener类来对URI信息进行管理。其中POCO::URI用于进行URI操作和存储。URIStreamFactory可以打开一个URI资源,并且把该URI资源和一个输入流相关联。URIStreamOpener类用来设计成对URIStreamFactory进行管理。通过URIStreamFactory和URIStreamOpener可以把对所有资源的读取都适配一个流接口。

          下面是Poco中Uri部分的类图。



2. POCO::URI

          一个URI标志通常包括下列部分:
          Scheme:协议
          Authority:包括了主机地址、端口、用户信息(通常指用户名/密码)
          Path:  路径
          Query:  查询
          Fragment: 内部资源地址

          下面是URI的一些例子:
http    ://    www.google.com    /    search    ?    q=POCO
 |                  |                   |               |
 |                  |                   |               |
Scheme             Host                Path           Query

http    ://    appinf.com    /    poco/docs/Poco.URI.html    #    5589
 |                  |                       |                      |
 |                  |                       |                      |
Scheme             Host                    Path                 Fragment

ftp    ://    anonymous    @    upload.sourceforge.com    /    incoming
 |                  |                       |                      |
 |                  |                       |                      |
Scheme             User                    Host                   Path

          POCO::URI类可以被看成是URI标记的集合。其接口定义如下:

class Foundation_API URI
{
public:
	URI();
		/// Creates an empty URI.

	explicit URI(const std::string& uri);
		/// Parses an URI from the given string. Throws a
		/// SyntaxException if the uri is not valid.
		
	explicit URI(const char* uri);
		/// Parses an URI from the given string. Throws a
		/// SyntaxException if the uri is not valid.
		
	URI(const std::string& scheme, const std::string& pathEtc);
		/// Creates an URI from its parts.
		
	URI(const std::string& scheme, const std::string& authority, const std::string& pathEtc);
		/// Creates an URI from its parts.

	URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query);
		/// Creates an URI from its parts.

	URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query, const std::string& fragment);
		/// Creates an URI from its parts.

	URI(const URI& uri);
		/// Copy constructor. Creates an URI from another one.
		
	URI(const URI& baseURI, const std::string& relativeURI);
		/// Creates an URI from a base URI and a relative URI, according to
		/// the algorithm in section 5.2 of RFC 3986.

	~URI();
		/// Destroys the URI.
	
	URI& operator = (const URI& uri);
		/// Assignment operator.
		
	URI& operator = (const std::string& uri);
		/// Parses and assigns an URI from the given string. Throws a
		/// SyntaxException if the uri is not valid.

	URI& operator = (const char* uri);
		/// Parses and assigns an URI from the given string. Throws a
		/// SyntaxException if the uri is not valid.
		
	void swap(URI& uri);
		/// Swaps the URI with another one.	
		
	void clear();
		/// Clears all parts of the URI.
	
	std::string toString() const;
		/// Returns a string representation of the URI.
		///
		/// Characters in the path, query and fragment parts will be 
		/// percent-encoded as necessary.
	
	const std::string& getScheme() const;
		/// Returns the scheme part of the URI.
		
	void setScheme(const std::string& scheme);
		/// Sets the scheme part of the URI. The given scheme
		/// is converted to lower-case.
		///
		/// A list of registered URI schemes can be found
		/// at <http://www.iana.org/assignments/uri-schemes>.
		
	const std::string& getUserInfo() const;
		/// Returns the user-info part of the URI.
		
	void setUserInfo(const std::string& userInfo);
		/// Sets the user-info part of the URI.
		
	const std::string& getHost() const;
		/// Returns the host part of the URI.
		
	void setHost(const std::string& host);
		/// Sets the host part of the URI.
		
	unsigned short getPort() const;
		/// Returns the port number part of the URI.
		///
		/// If no port number (0) has been specified, the
		/// well-known port number (e.g., 80 for http) for
		/// the given scheme is returned if it is known.
		/// Otherwise, 0 is returned.
		
	void setPort(unsigned short port);
		/// Sets the port number part of the URI.
		
	std::string getAuthority() const;
		/// Returns the authority part (userInfo, host and port)
		/// of the URI. 
		///
		/// If the port number is a well-known port
		/// number for the given scheme (e.g., 80 for http), it
		/// is not included in the authority.
		
	void setAuthority(const std::string& authority);
		/// Parses the given authority part for the URI and sets
		/// the user-info, host, port components accordingly.
		
	const std::string& getPath() const;
		/// Returns the path part of the URI.
		
	void setPath(const std::string& path);
		/// Sets the path part of the URI.
	
	std::string getQuery() const;
		/// Returns the query part of the URI.
		
	void setQuery(const std::string& query);	
		/// Sets the query part of the URI.

	const std::string& getRawQuery() const;
		/// Returns the unencoded query part of the URI.
		
	void setRawQuery(const std::string& query);	
		/// Sets the query part of the URI.
	
	const std::string& getFragment() const;
		/// Returns the fragment part of the URI.
		
	void setFragment(const std::string& fragment);
		/// Sets the fragment part of the URI.
		
	void setPathEtc(const std::string& pathEtc);
		/// Sets the path, query and fragment parts of the URI.
		
	std::string getPathEtc() const;
		/// Returns the path, query and fragment parts of the URI.
		
	std::string getPathAndQuery() const;
		/// Returns the path and query parts of the URI.	
		
	void resolve(const std::string& relativeURI);
		/// Resolves the given relative URI against the base URI.
		/// See section 5.2 of RFC 3986 for the algorithm used.

	void resolve(const URI& relativeURI);
		/// Resolves the given relative URI against the base URI.
		/// See section 5.2 of RFC 3986 for the algorithm used.

	bool isRelative() const;
		/// Returns true if the URI is a relative reference, false otherwise.
		///
		/// A relative reference does not contain a scheme identifier.
		/// Relative references are usually resolved against an absolute
		/// base reference.
	
	bool empty() const;
		/// Returns true if the URI is empty, false otherwise.
		
	bool operator == (const URI& uri) const;
		/// Returns true if both URIs are identical, false otherwise.
		///
		/// Two URIs are identical if their scheme, authority,
		/// path, query and fragment part are identical.

	bool operator == (const std::string& uri) const;
		/// Parses the given URI and returns true if both URIs are identical,
		/// false otherwise.

	bool operator != (const URI& uri) const;
		/// Returns true if both URIs are identical, false otherwise.

	bool operator != (const std::string& uri) const;
		/// Parses the given URI and returns true if both URIs are identical,
		/// false otherwise.
		
	void normalize();
		/// Normalizes the URI by removing all but leading . and .. segments from the path.
		///
		/// If the first path segment in a relative path contains a colon (:), 
		/// such as in a Windows path containing a drive letter, a dot segment (./) 
		/// is prepended in accordance with section 3.3 of RFC 3986.
	
	void getPathSegments(std::vector<std::string>& segments);
		/// Places the single path segments (delimited by slashes) into the
		/// given vector.
	
	static void encode(const std::string& str, const std::string& reserved, std::string& encodedStr);
		/// URI-encodes the given string by escaping reserved and non-ASCII
		/// characters. The encoded string is appended to encodedStr.
		
	static void decode(const std::string& str, std::string& decodedStr);
		/// URI-decodes the given string by replacing percent-encoded
		/// characters with the actual character. The decoded string
		/// is appended to decodedStr.

	....
	
private:
	std::string    _scheme;
	std::string    _userInfo;
	std::string    _host;
	unsigned short _port;
	std::string    _path;
	std::string    _query;
	std::string    _fragment;
};

          可以看到,在POCO::URI内部单独定义了不同字段来对应存储URI的不同部分。值得注意到是,在POCO::URI中存在两个函静态数encode()和decode()。这两个函数用来对URI资源进行Percent-encoding编码。这是由于在URI标准中定义了一些保留字符,如果URI资源中存在保留字符,必须对它们进行转义。

          下面是其一个例子:
#include "Poco/URI.h"
#include <iostream>

int main(int argc, char** argv)
{
	Poco::URI uri1("http://www.appinf.com:88/sample?example-query#frag");
	std::string scheme(uri1.getScheme()); // "http"
	std::string auth(uri1.getAuthority()); // "www.appinf.com:88"
	std::string host(uri1.getHost()); // "www.appinf.com"
	unsigned short port = uri1.getPort(); // 88
	std::string path(uri1.getPath()); // "/sample"
	std::string query(uri1.getQuery()); // "example-query"
	std::string frag(uri1.getFragment()); // "frag"
	std::string pathEtc(uri1.getPathEtc()); // "/sample?examplequery#frag"

	Poco::URI uri2;
	uri2.setScheme("https");
	uri2.setAuthority("www.appinf.com");
	uri2.setPath("/another sample");
	std::string s(uri2.toString());
	// "https://www.appinf.com/another%20sample"

	Poco::URI uri3("http://www.appinf.com");
	uri3.resolve("/poco/info/index.html");
	s = uri3.toString(); // "http://www.appinf.com/poco/info/index.html"
	uri3.resolve("support.html");
	s = uri3.toString(); // "http://www.appinf.com/poco/info/support.html"
	uri3.resolve("http://sourceforge.net/projects/poco");
	s = uri3.toString(); // "http://sourceforge.net/projects/poco"
	return 0;
}


3. POCO::URIStreamOpener

          POCO::URIStreamOpener类主要用于为URI资源,创建并打开一个对应的输入流。对于每一种URI协议,Poco::URIStreamFactory的子类必须向POCO::URIStreamOpener注册。
          在Poco库中,内置了文件(包括网络文件) 流工厂类FileStreamFactory,HTTP流工厂类 HTTPStreamFactory,FTP流工厂类 FTPStreamFactory。

          下面是其一个例子:

#include "Poco/URIStreamOpener.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/FTPStreamFactory.h"
#include <memory>
int main(int argc, char** argv)
{
	Poco::Net::HTTPStreamFactory::registerFactory();
	Poco::Net::FTPStreamFactory::registerFactory();
	Poco::URIStreamOpener& opener =
		Poco::URIStreamOpener::defaultOpener();
	std::auto_ptr<std::istream> istr1(
		opener.open("http://www.appinf.com/index.html")
		);
	std::auto_ptr<std::istream> istr2(
		opener.open("ftp://ftp.appinf.com/pub/poco/poco-1.2.5.tar.gz")
		);
	std::auto_ptr<std::istream> istr3(
		opener.open("file:///usr/include/stdio.h")
		);
	return 0;
}


(版权所有,转载时请注明作者和出处  http://blog.csdn.net/arau_sh/article/details/8698463
posted @ 2013-05-07 20:00  在天与地之间  阅读(930)  评论(0编辑  收藏  举报