mirror of
https://github.com/tristanpenman/valijson.git
synced 2024-12-12 10:13:51 +01:00
Remove vendored copy of urdl
This commit is contained in:
parent
9e7dbd8460
commit
0e3f48c889
4
thirdparty/urdl-2013-08-15/COPYING
vendored
4
thirdparty/urdl-2013-08-15/COPYING
vendored
@ -1,4 +0,0 @@
|
||||
Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
55
thirdparty/urdl-2013-08-15/Jamroot
vendored
55
thirdparty/urdl-2013-08-15/Jamroot
vendored
@ -1,55 +0,0 @@
|
||||
import modules ;
|
||||
import package ;
|
||||
|
||||
path-constant URDL_ROOT : . ;
|
||||
|
||||
BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
|
||||
if $(BOOST_ROOT)
|
||||
{
|
||||
use-project /boost : $(BOOST_ROOT) ;
|
||||
}
|
||||
|
||||
rule handle-static-runtime ( properties * )
|
||||
{
|
||||
if <link>shared in $(properties) && <runtime-link>static in $(properties)
|
||||
{
|
||||
return <build>no ;
|
||||
}
|
||||
}
|
||||
|
||||
project
|
||||
:
|
||||
build-dir build/bin
|
||||
:
|
||||
requirements
|
||||
<threading>multi
|
||||
<conditional>@handle-static-runtime
|
||||
:
|
||||
default-build
|
||||
debug release
|
||||
<threading>multi
|
||||
<link>shared <link>static
|
||||
<runtime-link>shared <runtime-link>static
|
||||
;
|
||||
|
||||
install lib
|
||||
:
|
||||
build
|
||||
:
|
||||
<location>lib
|
||||
<install-type>LIB
|
||||
;
|
||||
|
||||
local patterns = *.hpp *.ipp ;
|
||||
|
||||
local dirs = include/urdl include/urdl/* ;
|
||||
|
||||
package.install install
|
||||
:
|
||||
<install-source-root>include
|
||||
:
|
||||
:
|
||||
build
|
||||
:
|
||||
[ glob $(dirs)/$(patterns) ]
|
||||
;
|
23
thirdparty/urdl-2013-08-15/LICENSE_1_0.txt
vendored
23
thirdparty/urdl-2013-08-15/LICENSE_1_0.txt
vendored
@ -1,23 +0,0 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
4
thirdparty/urdl-2013-08-15/README
vendored
4
thirdparty/urdl-2013-08-15/README
vendored
@ -1,4 +0,0 @@
|
||||
urdl version 0.1
|
||||
Released Wednesday, 03 June 2009.
|
||||
|
||||
See doc/index.html for build information and API documentation.
|
102
thirdparty/urdl-2013-08-15/build/Jamfile
vendored
102
thirdparty/urdl-2013-08-15/build/Jamfile
vendored
@ -1,102 +0,0 @@
|
||||
import common ;
|
||||
import os ;
|
||||
import modules ;
|
||||
|
||||
if [ os.name ] = SOLARIS
|
||||
{
|
||||
lib socket ;
|
||||
lib nsl ;
|
||||
}
|
||||
else if [ os.name ] = NT
|
||||
{
|
||||
lib ws2_32 ;
|
||||
lib mswsock ;
|
||||
}
|
||||
else if [ os.name ] = HPUX
|
||||
{
|
||||
lib ipv6 ;
|
||||
}
|
||||
|
||||
local SSL_OPTIONS ;
|
||||
if [ modules.peek : URDL_DISABLE_SSL ] = 1
|
||||
{
|
||||
SSL_OPTIONS = <define>URDL_DISABLE_SSL=1 ;
|
||||
}
|
||||
else if [ os.name ] = NT
|
||||
{
|
||||
OPENSSL_ROOT = [ modules.peek : OPENSSL_ROOT ] ;
|
||||
lib user32 ;
|
||||
lib advapi32 ;
|
||||
lib gdi32 ;
|
||||
SSL_OPTIONS = <include>$(OPENSSL_ROOT)/inc32
|
||||
<library>$(OPENSSL_ROOT)/out32dll/libeay32.lib
|
||||
<library>$(OPENSSL_ROOT)/out32dll/ssleay32.lib
|
||||
<library>user32 <library>advapi32 <library>gdi32 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
lib ssl ;
|
||||
lib crypto ;
|
||||
SSL_OPTIONS = <library>ssl <library>crypto ;
|
||||
}
|
||||
|
||||
project urdl
|
||||
:
|
||||
source-location ../src
|
||||
:
|
||||
requirements
|
||||
<threading>multi
|
||||
:
|
||||
usage-requirements
|
||||
<link>shared:<define>URDL_DYN_LINK=1
|
||||
<link>static:<define>URDL_STATIC_LINK=1
|
||||
<include>$(URDL_ROOT)/include
|
||||
<library>/boost/system//boost_system
|
||||
<library>/boost/date_time//boost_date_time
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<os>SOLARIS:<library>socket
|
||||
<os>SOLARIS:<library>nsl
|
||||
<os>NT:<define>_WIN32_WINNT=0x0501
|
||||
<os>NT:<define>WIN32_LEAN_AND_MEAN=1
|
||||
<os>NT,<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||
<os>NT,<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
||||
<os>NT,<toolset>gcc:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>mswsock
|
||||
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
|
||||
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
|
||||
<os>HPUX:<library>ipv6
|
||||
$(SSL_OPTIONS)
|
||||
;
|
||||
|
||||
lib urdl
|
||||
:
|
||||
urdl.cpp
|
||||
:
|
||||
<link>shared:<define>BOOST_ALL_DYN_LINK=1
|
||||
<link>static:<define>BOOST_ALL_STATIC_LINK=1
|
||||
<include>$(URDL_ROOT)/include
|
||||
<library>/boost/system//boost_system
|
||||
<library>/boost/date_time//boost_date_time
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<os>SOLARIS:<library>socket
|
||||
<os>SOLARIS:<library>nsl
|
||||
<os>NT:<define>_WIN32_WINNT=0x0501
|
||||
<os>NT,<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||
<os>NT,<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
||||
<os>NT,<toolset>gcc:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>mswsock
|
||||
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
|
||||
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
|
||||
<os>HPUX:<library>ipv6
|
||||
<debug-symbols>on
|
||||
<tag>@tag
|
||||
$(SSL_OPTIONS)
|
||||
;
|
||||
|
||||
rule tag ( name : type ? : property-set )
|
||||
{
|
||||
local result = [ common.format-name
|
||||
<base> <runtime>
|
||||
: $(name) : $(type) : $(property-set) ] ;
|
||||
return "$(result)" ;
|
||||
}
|
62
thirdparty/urdl-2013-08-15/doc/Jamfile
vendored
62
thirdparty/urdl-2013-08-15/doc/Jamfile
vendored
@ -1,62 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
using quickbook ;
|
||||
|
||||
project
|
||||
:
|
||||
default-build
|
||||
debug
|
||||
<threading>multi
|
||||
<link>shared
|
||||
<runtime-link>shared
|
||||
;
|
||||
|
||||
xml standalone_doc
|
||||
:
|
||||
urdl.qbk
|
||||
;
|
||||
|
||||
boostbook standalone
|
||||
:
|
||||
standalone_doc
|
||||
:
|
||||
<xsl:param>boost.image.src=urdl.png
|
||||
<xsl:param>boost.image.alt="Urdl C++ Library"
|
||||
<xsl:param>boost.image.w=160
|
||||
<xsl:param>boost.image.h=60
|
||||
<xsl:param>nav.layout=none
|
||||
<xsl:param>navig.graphics.path=""
|
||||
<xsl:param>admon.graphics.path=""
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>chunk.section.depth=8
|
||||
<xsl:param>chunk.first.sections=1
|
||||
<xsl:param>toc.section.depth=3
|
||||
<xsl:param>toc.max.depth=3
|
||||
<xsl:param>generate.section.toc.level=2
|
||||
<xsl:param>generate.toc="chapter toc section toc"
|
||||
;
|
||||
|
||||
install html
|
||||
:
|
||||
/boost//doc/src/boostbook.css
|
||||
/boost//doc/src/images/blank.png
|
||||
/boost//doc/src/images/caution.png
|
||||
/boost//doc/src/images/draft.png
|
||||
/boost//doc/src/images/home.png
|
||||
/boost//doc/src/images/important.png
|
||||
/boost//doc/src/images/next_disabled.png
|
||||
/boost//doc/src/images/next.png
|
||||
/boost//doc/src/images/note.png
|
||||
/boost//doc/src/images/prev_disabled.png
|
||||
/boost//doc/src/images/prev.png
|
||||
/boost//doc/src/images/tip.png
|
||||
/boost//doc/src/images/up_disabled.png
|
||||
/boost//doc/src/images/up.png
|
||||
/boost//doc/src/images/warning.png
|
||||
urdl.png
|
||||
;
|
15
thirdparty/urdl-2013-08-15/doc/doxy2qbk.pl
vendored
15
thirdparty/urdl-2013-08-15/doc/doxy2qbk.pl
vendored
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
use strict;
|
||||
|
||||
system("doxygen reference.dox");
|
||||
chdir("xml");
|
||||
system("xsltproc combine.xslt index.xml > all.xml");
|
||||
chdir("..");
|
||||
system("xsltproc reference.xsl xml/all.xml > reference.qbk");
|
||||
system("rm -rf xml");
|
21
thirdparty/urdl-2013-08-15/doc/index.html
vendored
21
thirdparty/urdl-2013-08-15/doc/index.html
vendored
@ -1,21 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Urdl</title>
|
||||
<meta http-equiv="refresh" content="0; URL=html/index.html"/>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="html/index.html">html/index.html</a>
|
||||
</p>
|
||||
<hr/>
|
||||
<p>
|
||||
Copyright (c) 2009-2013 Christopher M. Kohlhoff
|
||||
</p>
|
||||
<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
16
thirdparty/urdl-2013-08-15/doc/index.xml
vendored
16
thirdparty/urdl-2013-08-15/doc/index.xml
vendored
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "../../boost/tools/boostbook/dtd/boostbook.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
|
||||
<section id="urdl.index">
|
||||
<title>Index</title>
|
||||
<index>
|
||||
<title></title>
|
||||
</index>
|
||||
</section>
|
223
thirdparty/urdl-2013-08-15/doc/reference.dox
vendored
223
thirdparty/urdl-2013-08-15/doc/reference.dox
vendored
@ -1,223 +0,0 @@
|
||||
# Doxyfile 1.4.5
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = "Urdl Reference"
|
||||
PROJECT_NUMBER =
|
||||
OUTPUT_DIRECTORY = .
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = YES
|
||||
INLINE_INHERITED_MEMB = YES
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = ./../../../
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = YES
|
||||
DETAILS_AT_TOP = YES
|
||||
INHERIT_DOCS = NO
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 2
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = NO
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
INLINE_INFO = NO
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TESTLIST = NO
|
||||
GENERATE_BUGLIST = NO
|
||||
GENERATE_DEPRECATEDLIST= NO
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = NO
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./../include/urdl std_dox.txt
|
||||
FILE_PATTERNS = *.hpp
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = YES
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 1
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = NO
|
||||
HTML_OUTPUT = .
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = YES
|
||||
ENUM_VALUES_PER_LINE = 1
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = URDL_DECL
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = NO
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = NO
|
||||
GROUP_GRAPHS = NO
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = YES
|
||||
INCLUDE_GRAPH = NO
|
||||
INCLUDED_BY_GRAPH = NO
|
||||
CALL_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = NO
|
||||
DIRECTORY_GRAPH = NO
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 640
|
||||
MAX_DOT_GRAPH_HEIGHT = 640
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = NO
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
4535
thirdparty/urdl-2013-08-15/doc/reference.qbk
vendored
4535
thirdparty/urdl-2013-08-15/doc/reference.qbk
vendored
File diff suppressed because it is too large
Load Diff
1251
thirdparty/urdl-2013-08-15/doc/reference.xsl
vendored
1251
thirdparty/urdl-2013-08-15/doc/reference.xsl
vendored
File diff suppressed because it is too large
Load Diff
7
thirdparty/urdl-2013-08-15/doc/std_dox.txt
vendored
7
thirdparty/urdl-2013-08-15/doc/std_dox.txt
vendored
@ -1,7 +0,0 @@
|
||||
/**
|
||||
\class std::basic_istream
|
||||
*/
|
||||
|
||||
/**
|
||||
\class std::streambuf
|
||||
*/
|
BIN
thirdparty/urdl-2013-08-15/doc/urdl.png
vendored
BIN
thirdparty/urdl-2013-08-15/doc/urdl.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
556
thirdparty/urdl-2013-08-15/doc/urdl.qbk
vendored
556
thirdparty/urdl-2013-08-15/doc/urdl.qbk
vendored
@ -1,556 +0,0 @@
|
||||
[/
|
||||
/ Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[library Urdl
|
||||
[quickbook 1.4]
|
||||
[copyright 2009-2013 Christopher M. Kohlhoff]
|
||||
[purpose Networking/HTTP library]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
[category template]
|
||||
[category generic]
|
||||
]
|
||||
|
||||
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
[def SyncReadStream [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/SyncReadStream.html SyncReadStream]]
|
||||
[def AsyncReadStream [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/AsyncReadStream.html AsyncReadStream]]
|
||||
[def boost::asio::read [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/read.html boost::asio::read]]
|
||||
[def boost::asio::read_until [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/read_until.html boost::asio::read_until]]
|
||||
[def boost::asio::async_read [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/async_read.html boost::asio::async_read]]
|
||||
[def boost::asio::async_read_until [@http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/async_read_until.html boost::asio::async_read_until]]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[heading What is Urdl?]
|
||||
|
||||
Urdl is a cross-platform C++ library for downloading web content using a URL.
|
||||
It provides an easy-to-use extension to standard C++ iostreams and an
|
||||
asynchronous interface for use with Boost.Asio.
|
||||
|
||||
[heading What can Urdl be used for?]
|
||||
|
||||
Possible uses for Urdl include:
|
||||
|
||||
* Downloading application configuration or data files.
|
||||
|
||||
* Downloading software updates.
|
||||
|
||||
* Accessing RSS feeds.
|
||||
|
||||
* Web service clients (e.g. SOAP, XML-RPC or REST).
|
||||
|
||||
* Web scraping.
|
||||
|
||||
[heading Obtaining Urdl]
|
||||
|
||||
The latest release of Urdl can be downloaded from
|
||||
[@http://sourceforge.net/project/showfiles.php?group_id=262090 SourceForge.net].
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:rationale Rationale]
|
||||
|
||||
The primary goal of Urdl is:
|
||||
|
||||
* To provide a simple abstraction for accessing and downloading internet
|
||||
resources.
|
||||
|
||||
Some secondary goals include:
|
||||
|
||||
* To act as an example of using Boost.Asio to create client-side abstractions.
|
||||
|
||||
* To act as an example of how to extend the Boost.System `error_code` facility.
|
||||
|
||||
* To explore the use of coroutine for implementing protocols using Boost.Asio.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:features Features]
|
||||
|
||||
* [*Support for HTTP, HTTPS and local files.]
|
||||
|
||||
[:Resources may be downloaded using HTTP 1.0 (using URLs of the form
|
||||
`"http://..."`), HTTPS (`"https://..."`). Local files are also supported
|
||||
(`"file://..."`). See [link urdl.planned_features Planned Features] for
|
||||
limitations in the current protocol implementations.]
|
||||
|
||||
* [*Extension to C++ IOStreams.]
|
||||
|
||||
[:The [link urdl.reference.core.istream urdl::istream] class provides a way to
|
||||
easily access content using standard C++ I/O facilities.]
|
||||
|
||||
* [*Integration with Boost.Asio.]
|
||||
|
||||
[:The [link urdl.reference.core.read_stream urdl::read_stream] class allows
|
||||
Urdl functionality to be used with other Boost.Asio features such as sockets
|
||||
and timers.]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:planned_features Planned features]
|
||||
|
||||
The following features are planned for a future release of Urdl:
|
||||
|
||||
* [*Support for HTTP chunking.]
|
||||
|
||||
[:Add the ability to handle HTTP responses where the [^Transfer-Encoding] is
|
||||
[^chunked].]
|
||||
|
||||
* [*Support for HTTP proxies.]
|
||||
|
||||
[:Add support for making HTTP and HTTPS requests through a proxy.]
|
||||
|
||||
* [*Support for FTP.]
|
||||
|
||||
[:Add support for downloading files using FTP.]
|
||||
|
||||
* [*SSL options to control peer verification.]
|
||||
|
||||
[:Add new options for controlling the way Urdl uses SSL to implement HTTPS, e.g.
|
||||
the ability to specify a certificate authority file or directory, whether
|
||||
peers are verified, etc. The current implementation always verifies the
|
||||
peer using OpenSSL's default certificate chains.]
|
||||
|
||||
* [*Support for wildcard SSL certificates.]
|
||||
|
||||
[:The current implementation of SSL peer verification supports only certificates
|
||||
issued to a single hostname.]
|
||||
|
||||
* [*Status function callback.]
|
||||
|
||||
[:Allow the user to register a `boost::function<>` object using `set_option()`.
|
||||
This will be called by the implementation to provide progress updates (e.g.
|
||||
resolving, connection, reading, etc).]
|
||||
|
||||
* [*Runtime polymorphism and user-supplied backends.]
|
||||
|
||||
[:Change the underlying implementation to use runtime polymorphism (abstract
|
||||
base classes) to invoke the appropriate protocol implementation. The user
|
||||
will be able to register a factory object to provide custom support for
|
||||
additional protocols.]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:prerequisites Prerequisites]
|
||||
|
||||
Urdl depends on the following libraries:
|
||||
|
||||
* [@http://www.boost.org/ Boost] 1.38 or later.
|
||||
|
||||
* [@http://www.openssl.org/ OpenSSL] (optional) for HTTPS support.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:platforms Supported platforms]
|
||||
|
||||
Urdl has been tested on the following platforms and compilers:
|
||||
|
||||
* Debian Linux 5.0 using g++ 4.1.
|
||||
|
||||
* Debian Linux 5.0 using g++ 4.3.
|
||||
|
||||
* Mac OS X 10.4 using g++ 4.0.1
|
||||
|
||||
* Windows using MinGW / g++ 3.4.5
|
||||
|
||||
* Windows using Visual C++ 8.0
|
||||
|
||||
* Windows using Visual C++ 9.0
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[section:getting_started Getting started]
|
||||
|
||||
[section:building Building and using Urdl]
|
||||
|
||||
There are three options for using Urdl in an application:
|
||||
|
||||
* as a separately compiled library;
|
||||
|
||||
* by compiling the source directly into the application; or
|
||||
|
||||
* as a header-file-only library.
|
||||
|
||||
[heading Using Urdl as a separately compiled library]
|
||||
|
||||
Urdl uses [^bjam] and Boost.Build to build shared and static libraries. To
|
||||
build the libraries, perform the following steps:
|
||||
|
||||
# Set a [^BOOST_ROOT] environment variable pointing to the location of Boost.
|
||||
|
||||
# If building on Windows, set an [^OPENSSL_ROOT] environment variable pointing
|
||||
to the location of OpenSSL. When building on UNIX, the build scripts assume
|
||||
that the OpenSSL headers and libraries may be found in the system's include
|
||||
and library paths, respectively. To disable Urdl's SSL support, define
|
||||
[^URDL_DISABLE_SSL=1] as an environment variable.
|
||||
|
||||
# Run [^bjam] in the top-level directory of the Urdl distribution. Libraries
|
||||
should be built into the [^lib] subdirectory.
|
||||
|
||||
Then, to use Urdl in an application:
|
||||
|
||||
# Add the [^include] subdirectory to your compiler's include path.
|
||||
|
||||
# Add the [^lib] subdirectory to your linker's library path.
|
||||
|
||||
# Add the Boost directory to your compiler's include path.
|
||||
|
||||
# Add the Boost library directory (e.g. [^stage/lib]) to your linker's library
|
||||
path. Urdl needs the application to link against the Boost.System and
|
||||
Boost.Date_Time libraries.
|
||||
|
||||
# If disabling Urdl's SSL support, add [^URDL_DISABLE_SSL=1] to your compiler's
|
||||
preprocessor definitions.
|
||||
|
||||
# If using the DLL version of Urdl on Windows, add [^URDL_DYN_LINK=1] to your
|
||||
compiler's preprocessor definitions.
|
||||
|
||||
[heading Compiling Urdl directly into an application]
|
||||
|
||||
To compile Urdl directly into an application, perform the following steps:
|
||||
|
||||
# Add the [^include] subdirectory to your compiler's include path.
|
||||
|
||||
# Add the file [^src/urdl.cpp] to your project or makefile.
|
||||
|
||||
# Add the Boost directory to your compiler's include path.
|
||||
|
||||
# Add the Boost library directory (e.g. [^stage/lib]) to your linker's library
|
||||
path. Urdl needs the application to link against the Boost.System and
|
||||
Boost.Date_Time libraries.
|
||||
|
||||
# If disabling Urdl's SSL support, add [^URDL_DISABLE_SSL=1] to your compiler's
|
||||
preprocessor definitions.
|
||||
|
||||
# If building on Windows, add [^URDL_NO_LIB=1] to your compiler's preprocessor
|
||||
definitions to disable autolinking.
|
||||
|
||||
[heading Using Urdl as a header-only library]
|
||||
|
||||
To use Urdl as a header-only library, perform the following steps:
|
||||
|
||||
# Add the [^include] subdirectory to your compiler's include path.
|
||||
|
||||
# Add the Boost directory to your compiler's include path.
|
||||
|
||||
# Add the Boost library directory (e.g. [^stage/lib]) to your linker's library
|
||||
path. Urdl needs the application to link against the Boost.System library and
|
||||
possibly the Boost.Date_Time library.
|
||||
|
||||
# If disabling Urdl's SSL support, add [^URDL_DISABLE_SSL=1] to your compiler's
|
||||
preprocessor definitions.
|
||||
|
||||
# Add [^URDL_HEADER_ONLY=1] to your compiler's preprocessor definitions.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Downloading a file using an istream]
|
||||
|
||||
The simplest use of Urdl is to download a file or other resource using the
|
||||
[link urdl.reference.core.istream urdl::istream] class.
|
||||
|
||||
// For std::cout and std::cerr.
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
// For urdl::istream. Each of Urdl's core classes has its own header file.
|
||||
#include <urdl/istream.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Open the URL. The connection is established and the HTTP request is sent.
|
||||
urdl::istream is("http://www.boost.org/LICENSE_1_0.txt");
|
||||
|
||||
// Check whether we opened the URL successfully.
|
||||
if (!is)
|
||||
{
|
||||
std::cerr << "Unable to open URL" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From here on, we can use urdl::istream like any other std::istream
|
||||
// object. Let's output the downloaded content one line at a time.
|
||||
std::string line;
|
||||
while (std::getline(is, line))
|
||||
{
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Checking for errors]
|
||||
|
||||
If we are unable to open a URL for any reason, we can find out the last error
|
||||
from the [link urdl.reference.core.istream urdl::istream] class:
|
||||
|
||||
urdl::istream is("http://somehost/path");
|
||||
if (!is)
|
||||
{
|
||||
std::cerr << "Unable to open URL: ";
|
||||
std::cerr << is.error().message() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Alternatively, we may test for a specific error:
|
||||
|
||||
// For the HTTP error codes.
|
||||
#include <urdl/http.hpp>
|
||||
|
||||
...
|
||||
|
||||
urdl::istream is("http://somehost/path");
|
||||
if (!is)
|
||||
{
|
||||
if (is.error() == urdl::http::errc::not_found)
|
||||
{
|
||||
// Hmm, maybe we can try downloading the file from somewhere else...
|
||||
}
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Setting options to perform an HTTP POST]
|
||||
|
||||
To upload over HTTP, we set the [link urdl.reference.opt.http__request_method
|
||||
http::request_method], [link urdl.reference.opt.http__request_content
|
||||
http::request_content] and [link urdl.reference.opt.http__request_content_type
|
||||
http::request_content_type] options on the stream prior to opening the URL:
|
||||
|
||||
// For the HTTP options.
|
||||
#include <urdl/http.hpp>
|
||||
|
||||
...
|
||||
|
||||
urdl::istream is;
|
||||
|
||||
// We're doing an HTTP POST ...
|
||||
is.set_option(urdl::http::request_method("POST"));
|
||||
|
||||
// ... where the MIME type indicates plain text ...
|
||||
is.set_option(urdl::http::request_content_type("text/plain"));
|
||||
|
||||
// ... and here's the content.
|
||||
is.set_option(urdl::http::request_content("Hello, world!"));
|
||||
|
||||
// All options set, so now we can open the URL.
|
||||
is.open("http://somehost/path");
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Grouping and reusing options]
|
||||
|
||||
Options may be grouped using an [link urdl.reference.core.option_set
|
||||
urdl::option_set] object. This allows the options to be reused across multiple
|
||||
requests.
|
||||
|
||||
// For urdl::option_set.
|
||||
#include <urdl/option_set.hpp>
|
||||
|
||||
...
|
||||
|
||||
urdl::option_set common_options;
|
||||
|
||||
// Prevent HTTP redirections.
|
||||
common_options.set_option(urdl::http::max_redirects(0));
|
||||
|
||||
// Tell the web server about Urdl.
|
||||
common_options.set_option(urdl::http::user_agent("Urdl"));
|
||||
|
||||
// Open a URL using only the common options.
|
||||
urdl::istream is1("http://somehost/path1", common_options);
|
||||
|
||||
// Open a URL with additional options. In this case, the common options are
|
||||
// applied to the stream as if we had called set_option invidiually for each
|
||||
// option in the set.
|
||||
urdl::istream is2;
|
||||
is2.set_option(urdl::http::request_method("POST"));
|
||||
is2.set_option(urdl::http::request_content_type("text/plain"));
|
||||
is2.set_option(urdl::http::request_content("Hello, world!"));
|
||||
is2.set_options(common_options);
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Specifying timeouts]
|
||||
|
||||
To prevent unresponsive servers from indefinitely hanging a program, the [link
|
||||
urdl.reference.core.istream urdl::istream] class uses a timeout when opening
|
||||
the stream and when reading content.
|
||||
|
||||
urdl::istream is;
|
||||
|
||||
// Fail if the URL cannot be opened within 60 seconds.
|
||||
is.open_timeout(60000);
|
||||
is.open("http://somehost/path");
|
||||
|
||||
if (!is)
|
||||
{
|
||||
// If the open operation timed out then:
|
||||
// is.error() == boost::system::errc::timed_out
|
||||
// holds true.
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Fail if an individual read does not complete within 30 seconds.
|
||||
is.read_timeout(30000);
|
||||
|
||||
// From here on, use urdl::istream like any other std::istream object.
|
||||
std::string line;
|
||||
while (std::getline(is, line))
|
||||
{
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
|
||||
// If a read operation timed out then:
|
||||
// is.error() == boost::system::errc::timed_out
|
||||
// holds true.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Parsing URLs]
|
||||
|
||||
The [link urdl.reference.core.url urdl::url] class gives us the ability to parse
|
||||
URLs and access their component parts. The default constructor:
|
||||
|
||||
// For urdl::url.
|
||||
#include <urdl/url.hpp>
|
||||
|
||||
...
|
||||
|
||||
urdl::url url("http://somehost/path");
|
||||
|
||||
provides a conversion from `std::string` or `const char*` to URLs. If the URL
|
||||
does not parse correctly, the constructor throws an exception of type
|
||||
`boost::system::system_error`. It is this constructor that is used when we
|
||||
write:
|
||||
|
||||
urdl::istream is("http://somehost/path");
|
||||
|
||||
We can also use the [link urdl.reference.core.url.from_string
|
||||
urdl::url::from_string] static member function to explicitly parse a URL, with
|
||||
the option of choosing a throwing overload:
|
||||
|
||||
urdl::url url = urdl::url::from_string("http://somehost/path");
|
||||
|
||||
or an overload that does not throw an exception on failure:
|
||||
|
||||
boost::system::error_code ec;
|
||||
urdl::url url = urdl::url::from_string("http://somehost/path", ec);
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Integrating with Boost.Asio]
|
||||
|
||||
The [link urdl.reference.core.read_stream urdl::read_stream] class allows
|
||||
applications to use Urdl's functionality in conjunction with Boost.Asio.
|
||||
|
||||
To synchronously open a URL, we may use:
|
||||
|
||||
// For urdl::read_stream.
|
||||
#include <urdl/read_stream.hpp>
|
||||
|
||||
...
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
|
||||
...
|
||||
|
||||
// An urdl::read_stream must always have an associated io_service.
|
||||
urdl::read_stream stream(io_service);
|
||||
|
||||
// Open the URL synchronously. Throws boost::system::system_error on failure.
|
||||
stream.open("http://somehost/path");
|
||||
|
||||
...
|
||||
|
||||
// Alternatively, open the URL synchronously without throwing on error.
|
||||
boost::system::error_code ec;
|
||||
stream.open("http://somehost/path", ec);
|
||||
|
||||
To asynchronously open a URL, we can write:
|
||||
|
||||
void open_handler(const boost::system::error_code& ec)
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
// URL successfully opened.
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unable to open URL: ";
|
||||
std::cerr << is.error().message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
stream.async_open("http://somehost/path", open_handler);
|
||||
|
||||
and the callback function `open_handler` will be invoked once the asynchronous
|
||||
operation completes.
|
||||
|
||||
The [link urdl.reference.core.read_stream urdl::read_stream] class meets
|
||||
Boost.Asio's SyncReadStream and AsyncReadStream type requirements. This means
|
||||
we can use it with the synchronous functions boost::asio::read and
|
||||
boost::asio::read_until:
|
||||
|
||||
boost::array<char, 512> data;
|
||||
boost::asio::read(stream, boost::asio::buffer(data));
|
||||
|
||||
...
|
||||
|
||||
boost::asio::streambuf buffer;
|
||||
boost::asio::read_until(stream, buffer, "\r\n");
|
||||
|
||||
or with the asynchronous functions boost::asio::async_read and
|
||||
boost::asio::async_read_until:
|
||||
|
||||
void read_handler(const boost::system::error_code& ec, std::size_t length)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
boost::array<char, 512> data;
|
||||
boost::asio::async_read(stream, boost::asio::buffer(data), read_handler);
|
||||
|
||||
...
|
||||
|
||||
boost::asio::streambuf buffer;
|
||||
boost::asio::async_read_until(stream, buffer, "\r\n", read_handler);
|
||||
|
||||
The asynchronous functions on the [link urdl.reference.core.read_stream
|
||||
urdl::read_stream] class allow concurrent access to multiple URLs without
|
||||
requiring additional threads. Furthermore, we can perform the operations
|
||||
concurrently with any of the other asynchronous facilities provided by
|
||||
Boost.Asio (sockets, timers and so on).
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/=============================================================================]
|
||||
|
||||
[include reference.qbk]
|
||||
[xinclude index.xml]
|
27
thirdparty/urdl-2013-08-15/example/Jamfile
vendored
27
thirdparty/urdl-2013-08-15/example/Jamfile
vendored
@ -1,27 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
project
|
||||
:
|
||||
requirements <library>../build//urdl
|
||||
:
|
||||
default-build
|
||||
debug
|
||||
<threading>multi
|
||||
<link>shared
|
||||
<runtime-link>shared
|
||||
;
|
||||
|
||||
exe get1 : get1.cpp ;
|
||||
exe get2 : get2.cpp ;
|
||||
exe multiget1 : multiget1.cpp ;
|
||||
|
||||
explicit multiget2 ;
|
||||
exe multiget2 : multiget2.cpp
|
||||
/boost/context//boost_context
|
||||
/boost/coroutine//boost_coroutine
|
||||
;
|
57
thirdparty/urdl-2013-08-15/example/get1.cpp
vendored
57
thirdparty/urdl-2013-08-15/example/get1.cpp
vendored
@ -1,57 +0,0 @@
|
||||
//
|
||||
// get1.cpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <urdl/istream.hpp>
|
||||
#include <boost/progress.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cerr << "Usage: get1 <url> <outputfile>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
urdl::istream is(argv[1]);
|
||||
if (!is)
|
||||
{
|
||||
std::cout << is.error().message() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream os(argv[2], std::ios_base::out | std::ios_base::binary);
|
||||
if (is.content_length() != std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
boost::progress_display progress(is.content_length());
|
||||
while (is && os)
|
||||
{
|
||||
char buffer[1024] = "";
|
||||
is.read(buffer, sizeof(buffer));
|
||||
os.write(buffer, is.gcount());
|
||||
progress += is.gcount();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << is.rdbuf();
|
||||
}
|
||||
|
||||
std::cout << is.error().message() << std::endl;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
48
thirdparty/urdl-2013-08-15/example/get2.cpp
vendored
48
thirdparty/urdl-2013-08-15/example/get2.cpp
vendored
@ -1,48 +0,0 @@
|
||||
//
|
||||
// get2.cpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <urdl/read_stream.hpp>
|
||||
#include <boost/progress.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cerr << "Usage: get2 <url> <outputfile>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
|
||||
urdl::read_stream stream(io_service);
|
||||
stream.open(argv[1]);
|
||||
|
||||
std::ofstream os(argv[2], std::ios_base::out | std::ios_base::binary);
|
||||
for (;;)
|
||||
{
|
||||
char data[1024];
|
||||
boost::system::error_code ec;
|
||||
std::size_t length = stream.read_some(boost::asio::buffer(data), ec);
|
||||
if (ec == boost::asio::error::eof)
|
||||
break;
|
||||
if (ec)
|
||||
throw boost::system::system_error(ec);
|
||||
os.write(data, length);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
92
thirdparty/urdl-2013-08-15/example/multiget1.cpp
vendored
92
thirdparty/urdl-2013-08-15/example/multiget1.cpp
vendored
@ -1,92 +0,0 @@
|
||||
//
|
||||
// multiget1.cpp
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <urdl/read_stream.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
class downloader
|
||||
: public boost::enable_shared_from_this<downloader>
|
||||
{
|
||||
public:
|
||||
downloader(boost::asio::io_service& io_service)
|
||||
: read_stream_(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
void start(const urdl::url& url, const std::string& file)
|
||||
{
|
||||
file_ = file;
|
||||
read_stream_.async_open(url,
|
||||
boost::bind(&downloader::handle_open,
|
||||
shared_from_this(), _1));
|
||||
}
|
||||
|
||||
private:
|
||||
void handle_open(const boost::system::error_code& ec)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ofstream_.open(file_.c_str(), std::ios_base::out | std::ios_base::binary);
|
||||
read_stream_.async_read_some(
|
||||
boost::asio::buffer(buffer_),
|
||||
boost::bind(&downloader::handle_read,
|
||||
shared_from_this(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_read(const boost::system::error_code& ec, std::size_t length)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ofstream_.write(buffer_, length);
|
||||
read_stream_.async_read_some(
|
||||
boost::asio::buffer(buffer_),
|
||||
boost::bind(&downloader::handle_read,
|
||||
shared_from_this(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
urdl::read_stream read_stream_;
|
||||
std::string file_;
|
||||
std::ofstream ofstream_;
|
||||
char buffer_[1024];
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc < 3 || argc % 2 == 0)
|
||||
{
|
||||
std::cerr << "Usage: multiget1 <url> <outputfile> ";
|
||||
std::cerr << "[<url> <outputfile> ...]\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
|
||||
for (int i = 1; i < argc; i += 2)
|
||||
{
|
||||
boost::shared_ptr<downloader> d(new downloader(io_service));
|
||||
d->start(argv[i], argv[i + 1]);
|
||||
}
|
||||
|
||||
io_service.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
74
thirdparty/urdl-2013-08-15/example/multiget2.cpp
vendored
74
thirdparty/urdl-2013-08-15/example/multiget2.cpp
vendored
@ -1,74 +0,0 @@
|
||||
//
|
||||
// multiget2.cpp
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <urdl/read_stream.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
void download(boost::asio::io_service& io_service,
|
||||
const urdl::url& url, const std::string& file,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
try
|
||||
{
|
||||
urdl::read_stream read_stream(io_service);
|
||||
read_stream.async_open(url, yield);
|
||||
|
||||
std::ofstream ofstream(file.c_str(),
|
||||
std::ios_base::out | std::ios_base::binary);
|
||||
|
||||
char buffer[1024];
|
||||
std::size_t length;
|
||||
boost::system::error_code ec;
|
||||
|
||||
do
|
||||
{
|
||||
length = read_stream.async_read_some(
|
||||
boost::asio::buffer(buffer), yield[ec]);
|
||||
ofstream.write(buffer, length);
|
||||
} while (length > 0);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Download exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (argc < 3 || argc % 2 == 0)
|
||||
{
|
||||
std::cerr << "Usage: multiget2 <url> <outputfile> ";
|
||||
std::cerr << "[<url> <outputfile> ...]\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
|
||||
for (int i = 1; i < argc; i += 2)
|
||||
{
|
||||
boost::asio::spawn(io_service,
|
||||
boost::bind(download, boost::ref(io_service),
|
||||
urdl::url(argv[i]), std::string(argv[i + 1]), _1));
|
||||
}
|
||||
|
||||
io_service.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
//
|
||||
// abi_prefix.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// No include guard.
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
// Disable some pesky MSVC warnings.
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable:4127)
|
||||
# pragma warning (disable:4251)
|
||||
# pragma warning (disable:4355)
|
||||
# pragma warning (disable:4512)
|
||||
# pragma warning (disable:4996)
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
// Force external visibility of all types.
|
||||
#if defined(__GNUC__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
# pragma GCC visibility push (default)
|
||||
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
#endif // defined(__GNUC__)
|
||||
|
@ -1,23 +0,0 @@
|
||||
//
|
||||
// abi_suffix.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// No include guard.
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning (pop)
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
# pragma GCC visibility pop
|
||||
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
@ -1,94 +0,0 @@
|
||||
//
|
||||
// config.hpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// No include guard.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# define URDL_DECL inline
|
||||
#else // defined(URDL_HEADER_ONLY)
|
||||
# if defined(BOOST_HAS_DECLSPEC)
|
||||
// We need to import/export our code only if the user has specifically asked
|
||||
// for it by defining either BOOST_ALL_DYN_LINK if they want all boost
|
||||
// libraries to be dynamically linked (and if boost is dynamically linked, urdl
|
||||
// must be dynamically linked too), or URDL_DYN_LINK if they want just urdl to
|
||||
// be dynamically liked.
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(URDL_DYN_LINK)
|
||||
# if !defined(URDL_DYN_LINK)
|
||||
# define URDL_DYN_LINK
|
||||
# endif // !defined(URDL_DYN_LINK)
|
||||
// Export if this is our own source, otherwise import.
|
||||
# if defined(URDL_SOURCE)
|
||||
# define URDL_DECL __declspec(dllexport)
|
||||
# else // defined(URDL_SOURCE)
|
||||
# define URDL_DECL __declspec(dllimport)
|
||||
# endif // defined(URDL_SOURCE)
|
||||
# endif // defined(BOOST_ALL_DYN_LINK) || defined(URDL_DYN_LINK)
|
||||
# endif // defined(BOOST_HAS_DECLSPEC)
|
||||
#endif // defined(URDL_HEADER_ONLY)
|
||||
|
||||
// If URDL_DECL isn't defined yet define it now.
|
||||
#if !defined(URDL_DECL)
|
||||
# define URDL_DECL
|
||||
#endif // !defined(URDL_DECL)
|
||||
|
||||
#if !defined(URDL_ERROR_CATEGORY_NOEXCEPT)
|
||||
# if (BOOST_VERSION >= 105300)
|
||||
# define URDL_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT
|
||||
# else // (BOOOST_VERSION >= 105300)
|
||||
# define URDL_ERROR_CATEGORY_NOEXCEPT
|
||||
# endif // (BOOOST_VERSION >= 105300)
|
||||
#endif // !defined(URDL_ERROR_CATEGORY_NOEXCEPT)
|
||||
|
||||
#if (BOOST_VERSION >= 105400)
|
||||
# define URDL_INITFN_RESULT_TYPE(h, sig) BOOST_ASIO_INITFN_RESULT_TYPE(h, sig)
|
||||
#else // (BOOST_VERSION >= 105400)
|
||||
# define URDL_INITFN_RESULT_TYPE(h, sig) void
|
||||
#endif // (BOOST_VERSION >= 105400)
|
||||
|
||||
// Enable library autolinking for MSVC.
|
||||
|
||||
#if !defined(BOOST_ALL_NO_LIB) && !defined(URDL_NO_LIB) \
|
||||
&& !defined(URDL_SOURCE) && !defined(URDL_HEADER_ONLY) \
|
||||
&& defined(_MSC_VER)
|
||||
|
||||
# if !defined(_MT)
|
||||
# error "You must use the multithreaded runtime."
|
||||
# endif
|
||||
|
||||
# if (defined(_DLL) || defined(_RTLDLL)) && defined(URDL_DYN_LINK)
|
||||
# define URDL_LIB_PREFIX
|
||||
# elif defined(URDL_DYN_LINK)
|
||||
# error "Mixing a dll library with a static runtime is unsupported."
|
||||
# else
|
||||
# define URDL_LIB_PREFIX "lib"
|
||||
# endif
|
||||
|
||||
# if defined(_DEBUG)
|
||||
# if defined(_DLL)
|
||||
# define URDL_LIB_SUFFIX "-gd"
|
||||
# else
|
||||
# define URDL_LIB_SUFFIX "-sgd"
|
||||
# endif
|
||||
# else
|
||||
# if defined(_DLL)
|
||||
# define URDL_LIB_SUFFIX
|
||||
# else
|
||||
# define URDL_LIB_SUFFIX "-s"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# pragma comment(lib, URDL_LIB_PREFIX "urdl" URDL_LIB_SUFFIX ".lib")
|
||||
|
||||
#endif // !defined(BOOST_ALL_NO_LIB) && !defined(URDL_NO_LIB)
|
||||
// && !defined(URDL_SOURCE) && !defined(URDL_HEADER_ONLY)
|
||||
// && defined(_MSC_VER)
|
@ -1,181 +0,0 @@
|
||||
//
|
||||
// connect.hpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_CONNECT_HPP
|
||||
#define URDL_DETAIL_CONNECT_HPP
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <sstream>
|
||||
#include "urdl/detail/coroutine.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
inline boost::system::error_code connect(
|
||||
boost::asio::ip::tcp::socket::lowest_layer_type& socket,
|
||||
boost::asio::ip::tcp::resolver& resolver,
|
||||
const url& u, boost::system::error_code& ec)
|
||||
{
|
||||
// Create a query that corresponds to the url.
|
||||
std::ostringstream port_string;
|
||||
port_string << u.port();
|
||||
boost::asio::ip::tcp::resolver::query query(u.host(), port_string.str());
|
||||
|
||||
// Get a list of endpoints corresponding to the query.
|
||||
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Try each endpoint until we successfully establish a connection.
|
||||
ec = boost::asio::error::host_not_found;
|
||||
while (ec && iter != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
socket.close(ec);
|
||||
socket.connect(*iter++, ec);
|
||||
}
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Disable the Nagle algorithm on all sockets.
|
||||
return socket.set_option(boost::asio::ip::tcp::no_delay(true), ec);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class connect_coro : coroutine
|
||||
{
|
||||
public:
|
||||
connect_coro(Handler handler,
|
||||
boost::asio::ip::tcp::socket::lowest_layer_type& socket,
|
||||
boost::asio::ip::tcp::resolver& resolver)
|
||||
: handler_(handler),
|
||||
socket_(socket),
|
||||
resolver_(resolver)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec,
|
||||
boost::asio::ip::tcp::resolver::iterator iter)
|
||||
{
|
||||
iter_ = iter;
|
||||
(*this)(ec);
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec,
|
||||
const boost::asio::ip::tcp::resolver::query* query = 0)
|
||||
{
|
||||
URDL_CORO_BEGIN;
|
||||
|
||||
// Open the socket to give the caller something to close to cancel the
|
||||
// asynchronous operation.
|
||||
socket_.open(boost::asio::ip::tcp::v4(), ec);
|
||||
if (ec)
|
||||
{
|
||||
URDL_CORO_YIELD(socket_.get_io_service().post(
|
||||
boost::asio::detail::bind_handler(*this, ec)));
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a list of endpoints corresponding to the host name.
|
||||
URDL_CORO_YIELD(resolver_.async_resolve(*query, *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try each endpoint until we successfully establish a connection.
|
||||
ec = boost::asio::error::host_not_found;
|
||||
while (ec && iter_ != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
// Check whether the operation has been cancelled.
|
||||
if (!socket_.is_open())
|
||||
{
|
||||
ec = boost::asio::error::operation_aborted;
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try next endpoint.
|
||||
socket_.close(ec);
|
||||
endpoint_ = *iter_++;
|
||||
URDL_CORO_YIELD(socket_.async_connect(endpoint_, *this));
|
||||
}
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether the operation has been cancelled.
|
||||
if (!socket_.is_open())
|
||||
{
|
||||
ec = boost::asio::error::operation_aborted;
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable the Nagle algorithm on all sockets.
|
||||
socket_.set_option(boost::asio::ip::tcp::no_delay(true), ec);
|
||||
|
||||
handler_(ec);
|
||||
|
||||
URDL_CORO_END;
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate(std::size_t size,
|
||||
connect_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
connect_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(pointer, size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke(const Function& function,
|
||||
connect_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, &this_handler->handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
boost::asio::ip::tcp::socket::lowest_layer_type& socket_;
|
||||
boost::asio::ip::tcp::resolver& resolver_;
|
||||
boost::asio::ip::tcp::resolver::iterator iter_;
|
||||
boost::asio::ip::tcp::endpoint endpoint_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
void async_connect(boost::asio::ip::tcp::socket::lowest_layer_type& socket,
|
||||
boost::asio::ip::tcp::resolver& resolver, const url& u, Handler handler)
|
||||
{
|
||||
std::ostringstream port_string;
|
||||
port_string << u.port();
|
||||
boost::asio::ip::tcp::resolver::query query(u.host(), port_string.str());
|
||||
connect_coro<Handler>(handler, socket, resolver)(
|
||||
boost::system::error_code(), &query);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_CONNECT_HPP
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// coroutine.hpp
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_COROUTINE_HPP
|
||||
#define URDL_DETAIL_COROUTINE_HPP
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
class coroutine
|
||||
{
|
||||
protected:
|
||||
coroutine() : coro_value_(0) {}
|
||||
int coro_value_;
|
||||
};
|
||||
|
||||
#define URDL_CORO_BEGIN \
|
||||
switch (this->coroutine::coro_value_) \
|
||||
{ \
|
||||
case 0:
|
||||
|
||||
#define URDL_CORO_YIELD_IMPL(s,n) \
|
||||
do \
|
||||
{ \
|
||||
this->coroutine::coro_value_ = n; \
|
||||
s; \
|
||||
return; \
|
||||
case n: \
|
||||
; \
|
||||
} while (0)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define URDL_CORO_YIELD(s) URDL_CORO_YIELD_IMPL(s, __COUNTER__ + 1)
|
||||
#else // defined(_MSC_VER)
|
||||
# define URDL_CORO_YIELD(s) URDL_CORO_YIELD_IMPL(s, __LINE__)
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
#define URDL_CORO_END \
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_COROUTINE_HPP
|
@ -1,129 +0,0 @@
|
||||
//
|
||||
// file_read_stream.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_FILE_READ_STREAM_HPP
|
||||
#define URDL_DETAIL_FILE_READ_STREAM_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
#include <cctype>
|
||||
#include <fstream>
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "urdl/url.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
class file_read_stream
|
||||
{
|
||||
public:
|
||||
explicit file_read_stream(boost::asio::io_service& io_service,
|
||||
option_set& options)
|
||||
: io_service_(io_service),
|
||||
options_(options)
|
||||
{
|
||||
}
|
||||
|
||||
boost::system::error_code open(const url& u, boost::system::error_code& ec)
|
||||
{
|
||||
file_.clear();
|
||||
std::string path = u.path();
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (path.length() >= 3 && path[0] == '/'
|
||||
&& std::isalpha(path[1]) && path[2] == ':')
|
||||
path = path.substr(1);
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
file_.open(path.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!file_)
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::no_such_file_or_directory);
|
||||
return ec;
|
||||
}
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void async_open(const url& u, Handler handler)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
open(u, ec);
|
||||
io_service_.post(boost::asio::detail::bind_handler(handler, ec));
|
||||
}
|
||||
|
||||
boost::system::error_code close(boost::system::error_code& ec)
|
||||
{
|
||||
file_.close();
|
||||
file_.clear();
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
// Some older versions of libstdc++ have a non-const is_open().
|
||||
return const_cast<std::ifstream&>(file_).is_open();
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (!file_)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typename MutableBufferSequence::const_iterator iter = buffers.begin();
|
||||
typename MutableBufferSequence::const_iterator end = buffers.end();
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
boost::asio::mutable_buffer buffer(*iter);
|
||||
size_t length = boost::asio::buffer_size(buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
file_.read(boost::asio::buffer_cast<char*>(buffer), length);
|
||||
length = file_.gcount();
|
||||
if (length == 0 && !file_)
|
||||
ec = boost::asio::error::eof;
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
ec = boost::system::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_read_some(const MutableBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::size_t bytes_transferred = read_some(buffers, ec);
|
||||
io_service_.post(boost::asio::detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service& io_service_;
|
||||
option_set& options_;
|
||||
std::ifstream file_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_FILE_READ_STREAM_HPP
|
@ -1,279 +0,0 @@
|
||||
//
|
||||
// handshake.hpp
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_HANDSHAKE_HPP
|
||||
#define URDL_DETAIL_HANDSHAKE_HPP
|
||||
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
#include "urdl/detail/coroutine.hpp"
|
||||
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
# include <boost/asio/ssl.hpp>
|
||||
# include <openssl/x509v3.h>
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
inline boost::system::error_code handshake(
|
||||
boost::asio::ip::tcp::socket& /*socket*/,
|
||||
const std::string& /*host*/, boost::system::error_code& ec)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void async_handshake(boost::asio::ip::tcp::socket& socket,
|
||||
const std::string& /*host*/, Handler handler)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
socket.get_io_service().post(boost::asio::detail::bind_handler(handler, ec));
|
||||
}
|
||||
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
inline bool match_pattern(const char* pattern,
|
||||
std::size_t pattern_length, const char* host)
|
||||
{
|
||||
const char* p = pattern;
|
||||
const char* p_end = p + pattern_length;
|
||||
const char* h = host;
|
||||
|
||||
while (p != p_end && *h)
|
||||
{
|
||||
if (*p == '*')
|
||||
{
|
||||
++p;
|
||||
while (*h && *h != '.')
|
||||
if (match_pattern(p, p_end - p, h++))
|
||||
return true;
|
||||
}
|
||||
else if (std::tolower(*p) == std::tolower(*h))
|
||||
{
|
||||
++p;
|
||||
++h;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return p == p_end && !*h;
|
||||
}
|
||||
|
||||
inline bool certificate_matches_host(X509* cert, const std::string& host)
|
||||
{
|
||||
// Try converting host name to an address. If it is an address then we need
|
||||
// to look for an IP address in the certificate rather than a host name.
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address address
|
||||
= boost::asio::ip::address::from_string(host, ec);
|
||||
bool is_address = !ec;
|
||||
|
||||
// Go through the alternate names in the certificate looking for matching DNS
|
||||
// or IP address entries.
|
||||
GENERAL_NAMES* gens = static_cast<GENERAL_NAMES*>(
|
||||
X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0));
|
||||
for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
|
||||
{
|
||||
GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
|
||||
if (gen->type == GEN_DNS && !is_address)
|
||||
{
|
||||
ASN1_IA5STRING* domain = gen->d.dNSName;
|
||||
if (domain->type == V_ASN1_IA5STRING
|
||||
&& domain->data && domain->length)
|
||||
{
|
||||
const char* pattern = reinterpret_cast<const char*>(domain->data);
|
||||
std::size_t pattern_length = domain->length;
|
||||
if (match_pattern(pattern, pattern_length, host.c_str()))
|
||||
{
|
||||
GENERAL_NAMES_free(gens);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gen->type == GEN_IPADD && is_address)
|
||||
{
|
||||
ASN1_OCTET_STRING* ip_address = gen->d.iPAddress;
|
||||
if (ip_address->type == V_ASN1_OCTET_STRING && ip_address->data)
|
||||
{
|
||||
if (address.is_v4() && ip_address->length == 4)
|
||||
{
|
||||
boost::asio::ip::address_v4::bytes_type address_bytes
|
||||
= address.to_v4().to_bytes();
|
||||
if (std::memcmp(address_bytes.data(), ip_address->data, 4) == 0)
|
||||
{
|
||||
GENERAL_NAMES_free(gens);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (address.is_v6() && ip_address->length == 16)
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type address_bytes
|
||||
= address.to_v6().to_bytes();
|
||||
if (std::memcmp(address_bytes.data(), ip_address->data, 16) == 0)
|
||||
{
|
||||
GENERAL_NAMES_free(gens);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GENERAL_NAMES_free(gens);
|
||||
|
||||
// No match in the alternate names, so try the common names. We should only
|
||||
// use the "most specific" common name, which is the last one in the list.
|
||||
X509_NAME* name = X509_get_subject_name(cert);
|
||||
int i = -1;
|
||||
ASN1_STRING* common_name = 0;
|
||||
while ((i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
|
||||
{
|
||||
X509_NAME_ENTRY* name_entry = X509_NAME_get_entry(name, i);
|
||||
common_name = X509_NAME_ENTRY_get_data(name_entry);
|
||||
}
|
||||
if (common_name && common_name->data && common_name->length)
|
||||
{
|
||||
const char* pattern = reinterpret_cast<const char*>(common_name->data);
|
||||
std::size_t pattern_length = common_name->length;
|
||||
if (match_pattern(pattern, pattern_length, host.c_str()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline boost::system::error_code handshake(
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>& socket,
|
||||
const std::string& host, boost::system::error_code& ec)
|
||||
{
|
||||
// Perform SSL handshake.
|
||||
socket.handshake(boost::asio::ssl::stream_base::client, ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Verify the certificate returned by the host.
|
||||
if (X509* cert = SSL_get_peer_certificate(socket.impl()->ssl))
|
||||
{
|
||||
if (SSL_get_verify_result(socket.impl()->ssl) == X509_V_OK)
|
||||
{
|
||||
if (certificate_matches_host(cert, host))
|
||||
ec = boost::system::error_code();
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
}
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
X509_free(cert);
|
||||
}
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class handshake_coro : coroutine
|
||||
{
|
||||
public:
|
||||
handshake_coro(Handler handler,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>& socket,
|
||||
const std::string& host)
|
||||
: handler_(handler),
|
||||
socket_(socket),
|
||||
host_(host)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec)
|
||||
{
|
||||
URDL_CORO_BEGIN;
|
||||
|
||||
// Perform SSL handshake.
|
||||
URDL_CORO_YIELD(socket_.async_handshake(
|
||||
boost::asio::ssl::stream_base::client, *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the certificate returned by the host.
|
||||
if (X509* cert = SSL_get_peer_certificate(socket_.impl()->ssl))
|
||||
{
|
||||
if (SSL_get_verify_result(socket_.impl()->ssl) == X509_V_OK)
|
||||
{
|
||||
if (certificate_matches_host(cert, host_))
|
||||
ec = boost::system::error_code();
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
}
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
X509_free(cert);
|
||||
}
|
||||
else
|
||||
ec = make_error_code(boost::system::errc::permission_denied);
|
||||
|
||||
handler_(ec);
|
||||
|
||||
URDL_CORO_END;
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate(std::size_t size,
|
||||
handshake_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
handshake_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(pointer, size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke(const Function& function,
|
||||
handshake_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, &this_handler->handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>& socket_;
|
||||
std::string host_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
void async_handshake(
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>& socket,
|
||||
const std::string& host, Handler handler)
|
||||
{
|
||||
handshake_coro<Handler>(handler, socket, host)(boost::system::error_code());
|
||||
}
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_HANDSHAKE_HPP
|
@ -1,533 +0,0 @@
|
||||
//
|
||||
// http_read_stream.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_HTTP_READ_STREAM_HPP
|
||||
#define URDL_DETAIL_HTTP_READ_STREAM_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/read_until.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <iterator>
|
||||
#include "urdl/http.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "urdl/url.hpp"
|
||||
#include "urdl/detail/connect.hpp"
|
||||
#include "urdl/detail/coroutine.hpp"
|
||||
#include "urdl/detail/handshake.hpp"
|
||||
#include "urdl/detail/parsers.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
template <typename Stream>
|
||||
class http_read_stream
|
||||
{
|
||||
public:
|
||||
explicit http_read_stream(boost::asio::io_service& io_service,
|
||||
option_set& options)
|
||||
: resolver_(io_service),
|
||||
socket_(io_service),
|
||||
options_(options),
|
||||
content_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
http_read_stream(boost::asio::io_service& io_service,
|
||||
option_set& options, Arg& arg)
|
||||
: resolver_(io_service),
|
||||
socket_(io_service, arg),
|
||||
options_(options),
|
||||
content_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
boost::system::error_code open(const url& u, boost::system::error_code& ec)
|
||||
{
|
||||
// Fail if the socket is already open.
|
||||
if (socket_.lowest_layer().is_open())
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Establish a connection to the HTTP server.
|
||||
connect(socket_.lowest_layer(), resolver_, u, ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Perform SSL handshake if required.
|
||||
handshake(socket_, u.host(), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Get the HTTP options used to build the request.
|
||||
std::string request_method
|
||||
= options_.get_option<urdl::http::request_method>().value();
|
||||
std::string request_content
|
||||
= options_.get_option<urdl::http::request_content>().value();
|
||||
std::string request_content_type
|
||||
= options_.get_option<urdl::http::request_content_type>().value();
|
||||
std::string user_agent
|
||||
= options_.get_option<urdl::http::user_agent>().value();
|
||||
|
||||
// Form the request. We specify the "Connection: close" header so that the
|
||||
// server will close the socket after transmitting the response. This will
|
||||
// allow us to treat all data up until the EOF as the content.
|
||||
std::ostream request_stream(&request_buffer_);
|
||||
request_stream << request_method << " ";
|
||||
request_stream << u.to_string(url::path_component | url::query_component);
|
||||
request_stream << " HTTP/1.0\r\n";
|
||||
request_stream << "Host: ";
|
||||
request_stream << u.to_string(url::host_component | url::port_component);
|
||||
request_stream << "\r\n";
|
||||
request_stream << "Accept: */*\r\n";
|
||||
if (request_content.length())
|
||||
{
|
||||
request_stream << "Content-Length: ";
|
||||
request_stream << request_content.length() << "\r\n";
|
||||
if (request_content_type.length())
|
||||
{
|
||||
request_stream << "Content-Type: ";
|
||||
request_stream << request_content_type << "\r\n";
|
||||
}
|
||||
}
|
||||
if (user_agent.length())
|
||||
request_stream << "User-Agent: " << user_agent << "\r\n";
|
||||
request_stream << "Connection: close\r\n\r\n";
|
||||
request_stream << request_content;
|
||||
|
||||
// Send the request.
|
||||
boost::asio::write(socket_, request_buffer_,
|
||||
boost::asio::transfer_all(), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
int status_code = 0;
|
||||
for (;;)
|
||||
{
|
||||
// Read the reply status line.
|
||||
boost::asio::read_until(socket_, reply_buffer_, "\r\n", ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Extract the response code from the status line.
|
||||
int version_major = 0;
|
||||
int version_minor = 0;
|
||||
if (!parse_http_status_line(
|
||||
std::istreambuf_iterator<char>(&reply_buffer_),
|
||||
std::istreambuf_iterator<char>(),
|
||||
version_major, version_minor, status_code))
|
||||
{
|
||||
ec = http::errc::malformed_status_line;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// A "continue" header means we need to keep waiting.
|
||||
if (status_code != http::errc::continue_request)
|
||||
break;
|
||||
}
|
||||
|
||||
// Read list of headers and save them. If there's anything left in the reply
|
||||
// buffer afterwards, it's the start of the content returned by the HTTP
|
||||
// server.
|
||||
std::size_t bytes_transferred = boost::asio::read_until(
|
||||
socket_, reply_buffer_, "\r\n\r\n", ec);
|
||||
headers_.resize(bytes_transferred);
|
||||
reply_buffer_.sgetn(&headers_[0], bytes_transferred);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Parse the headers to get Content-Type and Content-Length.
|
||||
if (!parse_http_headers(headers_.begin(), headers_.end(),
|
||||
content_type_, content_length_, location_))
|
||||
{
|
||||
ec = http::errc::malformed_response_headers;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Check the response code to see if we got the page correctly.
|
||||
if (status_code != http::errc::ok)
|
||||
ec = make_error_code(static_cast<http::errc::errc_t>(status_code));
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class open_coro : coroutine
|
||||
{
|
||||
public:
|
||||
open_coro(Handler handler, boost::asio::ip::tcp::resolver& resolver,
|
||||
Stream& socket, const option_set& options,
|
||||
boost::asio::streambuf& request_buffer,
|
||||
boost::asio::streambuf& reply_buffer, const url& u,
|
||||
std::string& headers, std::string& content_type,
|
||||
std::size_t& content_length, std::string& location)
|
||||
: handler_(handler),
|
||||
resolver_(resolver),
|
||||
socket_(socket),
|
||||
options_(options),
|
||||
request_buffer_(request_buffer),
|
||||
reply_buffer_(reply_buffer),
|
||||
url_(u),
|
||||
headers_(headers),
|
||||
status_code_(0),
|
||||
content_type_(content_type),
|
||||
content_length_(content_length),
|
||||
location_(location)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec,
|
||||
std::size_t bytes_transferred = 0)
|
||||
{
|
||||
URDL_CORO_BEGIN;
|
||||
|
||||
// Fail if the socket is already open.
|
||||
if (socket_.lowest_layer().is_open())
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
URDL_CORO_YIELD(socket_.get_io_service().post(
|
||||
boost::asio::detail::bind_handler(*this, ec)));
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Establish a connection to the HTTP server.
|
||||
URDL_CORO_YIELD(async_connect(socket_.lowest_layer(),
|
||||
resolver_, url_, *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform SSL handshake if required.
|
||||
URDL_CORO_YIELD(async_handshake(socket_, url_.host(), *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
// Get the HTTP options used to build the request.
|
||||
std::string request_method
|
||||
= options_.get_option<urdl::http::request_method>().value();
|
||||
std::string request_content
|
||||
= options_.get_option<urdl::http::request_content>().value();
|
||||
std::string request_content_type
|
||||
= options_.get_option<urdl::http::request_content_type>().value();
|
||||
std::string user_agent
|
||||
= options_.get_option<urdl::http::user_agent>().value();
|
||||
|
||||
// Form the request. We specify the "Connection: close" header so that
|
||||
// the server will close the socket after transmitting the response.
|
||||
// This will allow us to treat all data up until the EOF as the
|
||||
// content.
|
||||
std::ostream request_stream(&request_buffer_);
|
||||
request_stream << request_method << " ";
|
||||
request_stream << url_.to_string(
|
||||
url::path_component | url::query_component);
|
||||
request_stream << " HTTP/1.0\r\n";
|
||||
request_stream << "Host: ";
|
||||
request_stream << url_.to_string(
|
||||
url::host_component | url::port_component);
|
||||
request_stream << "\r\n";
|
||||
request_stream << "Accept: */*\r\n";
|
||||
if (request_content.length())
|
||||
{
|
||||
request_stream << "Content-Length: ";
|
||||
request_stream << request_content.length() << "\r\n";
|
||||
if (request_content_type.length())
|
||||
{
|
||||
request_stream << "Content-Type: ";
|
||||
request_stream << request_content_type << "\r\n";
|
||||
}
|
||||
}
|
||||
if (user_agent.length())
|
||||
request_stream << "User-Agent: " << user_agent << "\r\n";
|
||||
request_stream << "Connection: close\r\n\r\n";
|
||||
request_stream << request_content;
|
||||
}
|
||||
|
||||
// Send the request.
|
||||
URDL_CORO_YIELD(boost::asio::async_write(socket_,
|
||||
request_buffer_, boost::asio::transfer_all(), *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Read the reply status line.
|
||||
URDL_CORO_YIELD(boost::asio::async_read_until(socket_,
|
||||
reply_buffer_, "\r\n", *this));
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the response code to see if we got the page correctly.
|
||||
{
|
||||
int version_major = 0;
|
||||
int version_minor = 0;
|
||||
if (!parse_http_status_line(
|
||||
std::istreambuf_iterator<char>(&reply_buffer_),
|
||||
std::istreambuf_iterator<char>(),
|
||||
version_major, version_minor, status_code_))
|
||||
{
|
||||
ec = http::errc::malformed_status_line;
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A "continue" header means we need to keep waiting.
|
||||
if (status_code_ != http::errc::continue_request)
|
||||
break;
|
||||
}
|
||||
|
||||
// Read list of headers and save them. If there's anything left in the
|
||||
// reply buffer afterwards, it's the start of the content returned by the
|
||||
// HTTP server.
|
||||
URDL_CORO_YIELD(boost::asio::async_read_until(socket_,
|
||||
reply_buffer_, "\r\n\r\n", *this));
|
||||
headers_.resize(bytes_transferred);
|
||||
reply_buffer_.sgetn(&headers_[0], bytes_transferred);
|
||||
if (ec)
|
||||
{
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the headers to get Content-Type and Content-Length.
|
||||
if (!parse_http_headers(headers_.begin(), headers_.end(),
|
||||
content_type_, content_length_, location_))
|
||||
{
|
||||
ec = http::errc::malformed_response_headers;
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the response code to see if we got the page correctly.
|
||||
if (status_code_ != http::errc::ok)
|
||||
ec = make_error_code(static_cast<http::errc::errc_t>(status_code_));
|
||||
|
||||
handler_(ec);
|
||||
|
||||
URDL_CORO_END;
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate(std::size_t size,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(pointer, size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke(const Function& function,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, &this_handler->handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
boost::asio::ip::tcp::resolver& resolver_;
|
||||
Stream& socket_;
|
||||
const option_set& options_;
|
||||
boost::asio::streambuf& request_buffer_;
|
||||
boost::asio::streambuf& reply_buffer_;
|
||||
url url_;
|
||||
std::string& headers_;
|
||||
int status_code_;
|
||||
std::string& content_type_;
|
||||
std::size_t& content_length_;
|
||||
std::string& location_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
void async_open(const url& u, Handler handler)
|
||||
{
|
||||
open_coro<Handler>(handler, resolver_, socket_, options_, request_buffer_,
|
||||
reply_buffer_, u, headers_, content_type_, content_length_, location_)(
|
||||
boost::system::error_code(), 0);
|
||||
}
|
||||
|
||||
boost::system::error_code close(boost::system::error_code& ec)
|
||||
{
|
||||
resolver_.cancel();
|
||||
if (!socket_.lowest_layer().close(ec))
|
||||
{
|
||||
request_buffer_.consume(request_buffer_.size());
|
||||
reply_buffer_.consume(reply_buffer_.size());
|
||||
headers_.clear();
|
||||
content_type_.clear();
|
||||
content_length_ = 0;
|
||||
location_.clear();
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
{
|
||||
return socket_.lowest_layer().is_open();
|
||||
}
|
||||
|
||||
std::string content_type() const
|
||||
{
|
||||
return content_type_;
|
||||
}
|
||||
|
||||
std::size_t content_length() const
|
||||
{
|
||||
return content_length_;
|
||||
}
|
||||
|
||||
std::string location() const
|
||||
{
|
||||
return location_;
|
||||
}
|
||||
|
||||
std::string headers() const
|
||||
{
|
||||
return headers_;
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
// If we have any data in the reply_buffer_, return that first.
|
||||
if (reply_buffer_.size() > 0)
|
||||
{
|
||||
std::size_t bytes_transferred = 0;
|
||||
typename MutableBufferSequence::const_iterator iter = buffers.begin();
|
||||
typename MutableBufferSequence::const_iterator end = buffers.end();
|
||||
for (; iter != end && reply_buffer_.size() > 0; ++iter)
|
||||
{
|
||||
boost::asio::mutable_buffer buffer(*iter);
|
||||
size_t length = boost::asio::buffer_size(buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
bytes_transferred += reply_buffer_.sgetn(
|
||||
boost::asio::buffer_cast<char*>(buffer), length);
|
||||
}
|
||||
}
|
||||
ec = boost::system::error_code();
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
// Otherwise we forward the call to the underlying socket.
|
||||
std::size_t bytes_transferred = socket_.read_some(buffers, ec);
|
||||
if (ec == boost::asio::error::shut_down)
|
||||
ec = boost::asio::error::eof;
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
class read_handler
|
||||
{
|
||||
public:
|
||||
read_handler(Handler handler)
|
||||
: handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (ec == boost::asio::error::shut_down)
|
||||
ec = boost::asio::error::eof;
|
||||
handler_(ec, bytes_transferred);
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate(std::size_t size,
|
||||
read_handler<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
read_handler<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(pointer, size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke(const Function& function,
|
||||
read_handler<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, &this_handler->handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_read_some(const MutableBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
// If we have any data in the reply_buffer_, return that first.
|
||||
if (reply_buffer_.size() > 0)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::size_t bytes_transferred = read_some(buffers, ec);
|
||||
socket_.get_io_service().post(boost::asio::detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we forward the call to the underlying socket.
|
||||
socket_.async_read_some(buffers, read_handler<Handler>(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::ip::tcp::resolver resolver_;
|
||||
Stream socket_;
|
||||
option_set& options_;
|
||||
boost::asio::streambuf request_buffer_;
|
||||
boost::asio::streambuf reply_buffer_;
|
||||
std::string headers_;
|
||||
std::string content_type_;
|
||||
std::size_t content_length_;
|
||||
std::string location_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_HTTP_READ_STREAM_HPP
|
@ -1,297 +0,0 @@
|
||||
//
|
||||
// parsers.hpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_PARSERS_HPP
|
||||
#define URDL_DETAIL_PARSERS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
inline bool is_char(int c)
|
||||
{
|
||||
return c >= 0 && c <= 127;
|
||||
}
|
||||
|
||||
inline bool is_ctl(int c)
|
||||
{
|
||||
return (c >= 0 && c <= 31) || c == 127;
|
||||
}
|
||||
|
||||
inline bool is_tspecial(int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '(': case ')': case '<': case '>': case '@':
|
||||
case ',': case ';': case ':': case '\\': case '"':
|
||||
case '/': case '[': case ']': case '?': case '=':
|
||||
case '{': case '}': case ' ': case '\t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_digit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
inline bool tolower_compare(char a, char b)
|
||||
{
|
||||
return std::tolower(a) == std::tolower(b);
|
||||
}
|
||||
|
||||
inline bool headers_equal(const std::string& a, const std::string& b)
|
||||
{
|
||||
if (a.length() != b.length())
|
||||
return false;
|
||||
return std::equal(a.begin(), a.end(), b.begin(), tolower_compare);
|
||||
}
|
||||
|
||||
inline void check_header(const std::string& name, const std::string& value,
|
||||
std::string& content_type, std::size_t& content_length,
|
||||
std::string& location)
|
||||
{
|
||||
if (headers_equal(name, "Content-Type"))
|
||||
content_type = value;
|
||||
else if (headers_equal(name, "Content-Length"))
|
||||
content_length = std::atoi(value.c_str());
|
||||
else if (headers_equal(name, "Location"))
|
||||
location = value;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
bool parse_http_status_line(Iterator begin, Iterator end,
|
||||
int& version_major, int& version_minor, int& status)
|
||||
{
|
||||
enum
|
||||
{
|
||||
http_version_h,
|
||||
http_version_t_1,
|
||||
http_version_t_2,
|
||||
http_version_p,
|
||||
http_version_slash,
|
||||
http_version_major_start,
|
||||
http_version_major,
|
||||
http_version_minor_start,
|
||||
http_version_minor,
|
||||
status_code_start,
|
||||
status_code,
|
||||
reason_phrase,
|
||||
linefeed,
|
||||
fail
|
||||
} state = http_version_h;
|
||||
|
||||
Iterator iter = begin;
|
||||
std::string reason;
|
||||
while (iter != end && state != fail)
|
||||
{
|
||||
char c = *iter++;
|
||||
switch (state)
|
||||
{
|
||||
case http_version_h:
|
||||
state = (c == 'H') ? http_version_t_1 : fail;
|
||||
break;
|
||||
case http_version_t_1:
|
||||
state = (c == 'T') ? http_version_t_2 : fail;
|
||||
break;
|
||||
case http_version_t_2:
|
||||
state = (c == 'T') ? http_version_p : fail;
|
||||
break;
|
||||
case http_version_p:
|
||||
state = (c == 'P') ? http_version_slash : fail;
|
||||
break;
|
||||
case http_version_slash:
|
||||
state = (c == '/') ? http_version_major_start : fail;
|
||||
break;
|
||||
case http_version_major_start:
|
||||
if (is_digit(c))
|
||||
{
|
||||
version_major = version_major * 10 + c - '0';
|
||||
state = http_version_major;
|
||||
}
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case http_version_major:
|
||||
if (c == '.')
|
||||
state = http_version_minor_start;
|
||||
else if (is_digit(c))
|
||||
version_major = version_major * 10 + c - '0';
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case http_version_minor_start:
|
||||
if (is_digit(c))
|
||||
{
|
||||
version_minor = version_minor * 10 + c - '0';
|
||||
state = http_version_minor;
|
||||
}
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case http_version_minor:
|
||||
if (c == ' ')
|
||||
state = status_code_start;
|
||||
else if (is_digit(c))
|
||||
version_minor = version_minor * 10 + c - '0';
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case status_code_start:
|
||||
if (is_digit(c))
|
||||
{
|
||||
status = status * 10 + c - '0';
|
||||
state = status_code;
|
||||
}
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case status_code:
|
||||
if (c == ' ')
|
||||
state = reason_phrase;
|
||||
else if (is_digit(c))
|
||||
status = status * 10 + c - '0';
|
||||
else
|
||||
state = fail;
|
||||
break;
|
||||
case reason_phrase:
|
||||
if (c == '\r')
|
||||
state = linefeed;
|
||||
else if (is_ctl(c))
|
||||
state = fail;
|
||||
else
|
||||
reason.push_back(c);
|
||||
break;
|
||||
case linefeed:
|
||||
return (c == '\n');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
bool parse_http_headers(Iterator begin, Iterator end,
|
||||
std::string& content_type, std::size_t& content_length,
|
||||
std::string& location)
|
||||
{
|
||||
enum
|
||||
{
|
||||
first_header_line_start,
|
||||
header_line_start,
|
||||
header_lws,
|
||||
header_name,
|
||||
space_before_header_value,
|
||||
header_value,
|
||||
linefeed,
|
||||
final_linefeed,
|
||||
fail
|
||||
} state = first_header_line_start;
|
||||
|
||||
Iterator iter = begin;
|
||||
std::string reason;
|
||||
std::string name;
|
||||
std::string value;
|
||||
while (iter != end && state != fail)
|
||||
{
|
||||
char c = *iter++;
|
||||
switch (state)
|
||||
{
|
||||
case first_header_line_start:
|
||||
if (c == '\r')
|
||||
state = final_linefeed;
|
||||
else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
|
||||
state = fail;
|
||||
else
|
||||
{
|
||||
name.push_back(c);
|
||||
state = header_name;
|
||||
}
|
||||
break;
|
||||
case header_line_start:
|
||||
if (c == '\r')
|
||||
{
|
||||
check_header(name, value, content_type, content_length, location);
|
||||
name.clear();
|
||||
value.clear();
|
||||
state = final_linefeed;
|
||||
}
|
||||
else if (c == ' ' || c == '\t')
|
||||
state = header_lws;
|
||||
else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
|
||||
state = fail;
|
||||
else
|
||||
{
|
||||
check_header(name, value, content_type, content_length, location);
|
||||
name.clear();
|
||||
value.clear();
|
||||
name.push_back(c);
|
||||
state = header_name;
|
||||
}
|
||||
break;
|
||||
case header_lws:
|
||||
if (c == '\r')
|
||||
state = linefeed;
|
||||
else if (c == ' ' || c == '\t')
|
||||
; // Discard character.
|
||||
else if (is_ctl(c))
|
||||
state = fail;
|
||||
else
|
||||
{
|
||||
state = header_value;
|
||||
value.push_back(c);
|
||||
}
|
||||
break;
|
||||
case header_name:
|
||||
if (c == ':')
|
||||
state = space_before_header_value;
|
||||
else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
|
||||
state = fail;
|
||||
else
|
||||
name.push_back(c);
|
||||
break;
|
||||
case space_before_header_value:
|
||||
state = (c == ' ') ? header_value : fail;
|
||||
break;
|
||||
case header_value:
|
||||
if (c == '\r')
|
||||
state = linefeed;
|
||||
else if (is_ctl(c))
|
||||
state = fail;
|
||||
else
|
||||
value.push_back(c);
|
||||
break;
|
||||
case linefeed:
|
||||
state = (c == '\n') ? header_line_start : fail;
|
||||
break;
|
||||
case final_linefeed:
|
||||
return (c == '\n');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_PARSERS_HPP
|
@ -1,85 +0,0 @@
|
||||
//
|
||||
// detail/scoped_ptr.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_DETAIL_SCOPED_PTR_HPP
|
||||
#define URDL_DETAIL_SCOPED_PTR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class scoped_ptr
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
explicit scoped_ptr(T* p = 0)
|
||||
: p_(p)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~scoped_ptr()
|
||||
{
|
||||
delete p_;
|
||||
}
|
||||
|
||||
// Access.
|
||||
T* get() const
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
// Access.
|
||||
T* operator->()
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
// Dereference.
|
||||
T& operator*()
|
||||
{
|
||||
return *p_;
|
||||
}
|
||||
|
||||
// Reset pointer.
|
||||
void reset(T* p = 0)
|
||||
{
|
||||
delete p_;
|
||||
p_ = p;
|
||||
}
|
||||
|
||||
// Release pointer.
|
||||
T* release()
|
||||
{
|
||||
T* p = p_;
|
||||
p_ = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
scoped_ptr(const scoped_ptr&);
|
||||
scoped_ptr& operator=(const scoped_ptr&);
|
||||
|
||||
T* p_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_DETAIL_SCOPED_PTR_HPP
|
594
thirdparty/urdl-2013-08-15/include/urdl/http.hpp
vendored
594
thirdparty/urdl-2013-08-15/include/urdl/http.hpp
vendored
@ -1,594 +0,0 @@
|
||||
//
|
||||
// http.hpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_HTTP_HPP
|
||||
#define URDL_HTTP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include "urdl/detail/config.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace http {
|
||||
|
||||
/// Gets the error category for HTTP errors.
|
||||
/**
|
||||
* @returns The @c boost::system::error_category used for HTTP errors.
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
URDL_DECL const boost::system::error_category& error_category();
|
||||
|
||||
/// Option to specify the HTTP request method.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The default request method is "GET".
|
||||
*
|
||||
* @par Example
|
||||
* To set the request method for an object of class @c urdl::istream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::request_method("HEAD"));
|
||||
* is.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* To set the request method for an object of class @c urdl::read_stream:
|
||||
* @code
|
||||
* urdl::read_stream stream;
|
||||
* stream.set_option(urdl::http::request_method("HEAD"));
|
||||
* stream.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
class request_method
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c request_method.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == "GET"</tt>.
|
||||
*/
|
||||
request_method()
|
||||
: value_("GET")
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c request_method.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
explicit request_method(const std::string& v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Gets the value of the option.
|
||||
/**
|
||||
* @returns The value of the option.
|
||||
*/
|
||||
std::string value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Sets the value of the option.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
void value(const std::string& v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
/// Option to specify content to accompany an HTTP request.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The default is for no content to be sent.
|
||||
*
|
||||
* @par Example
|
||||
* To add content to the HTTP request using an object of class @c urdl::istream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::request_method("POST"));
|
||||
* is.set_option(urdl::http::request_content("Hello, world!"));
|
||||
* is.set_option(urdl::http::request_content_type("text/plain"));
|
||||
* is.open("http://host/path");
|
||||
* @endcode
|
||||
*
|
||||
* To add content to the HTTP request using an object of class
|
||||
* @c urdl::read_stream:
|
||||
* @code
|
||||
* urdl::read_stream stream;
|
||||
* stream.set_option(urdl::http::request_method("POST"));
|
||||
* stream.set_option(urdl::http::request_content("Hello, world!"));
|
||||
* stream.set_option(urdl::http::request_content_type("text/plain"));
|
||||
* stream.open("http://host/path");
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
class request_content
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c request_content.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == ""</tt>.
|
||||
*/
|
||||
request_content()
|
||||
: value_("")
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c request_content.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
explicit request_content(const std::string& v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Gets the value of the option.
|
||||
/**
|
||||
* @returns The value of the option.
|
||||
*/
|
||||
std::string value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Sets the value of the option.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
void value(const std::string& v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
/// Option to specify the type of the content that accompanies an HTTP request.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The default is for no content type to be specified in the request.
|
||||
*
|
||||
* @par Example
|
||||
* To add content to the HTTP request using an object of class @c urdl::istream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::request_method("POST"));
|
||||
* is.set_option(urdl::http::request_content("Hello, world!"));
|
||||
* is.set_option(urdl::http::request_content_type("text/plain"));
|
||||
* is.open("http://host/path");
|
||||
* @endcode
|
||||
*
|
||||
* To add content to the HTTP request using an object of class
|
||||
* @c urdl::read_stream:
|
||||
* @code
|
||||
* urdl::read_stream stream;
|
||||
* stream.set_option(urdl::http::request_method("POST"));
|
||||
* stream.set_option(urdl::http::request_content("Hello, world!"));
|
||||
* stream.set_option(urdl::http::request_content_type("text/plain"));
|
||||
* stream.open("http://host/path");
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
class request_content_type
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c request_content_type.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == ""</tt>.
|
||||
*/
|
||||
request_content_type()
|
||||
: value_("")
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c request_content_type.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
explicit request_content_type(const std::string& v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Gets the value of the option.
|
||||
/**
|
||||
* @returns The value of the option.
|
||||
*/
|
||||
std::string value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Sets the value of the option.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
void value(const std::string& v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
/// Option to specify the maximum number of allowed HTTP redirects.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The default value is for there to be no limit on the number of allowed
|
||||
* redirects. Set the option to 0 to disable HTTP redirects.
|
||||
*
|
||||
* @par Example
|
||||
* To set maximum number of redirects for an object of class @c urdl::istream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::max_redirects(1));
|
||||
* is.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* To set maximum number of redirects for an object of class
|
||||
* @c urdl::read_stream:
|
||||
* @code
|
||||
* urdl::read_stream stream;
|
||||
* stream.set_option(urdl::http::max_redirects(1));
|
||||
* stream.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
class max_redirects
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c max_redirects.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == std::numeric_limits<std::size_t>::max()</tt>.
|
||||
*/
|
||||
max_redirects()
|
||||
: value_(~std::size_t(0))
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c max_redirects.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
explicit max_redirects(std::size_t v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Gets the value of the option.
|
||||
/**
|
||||
* @returns The value of the option.
|
||||
*/
|
||||
std::size_t value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Sets the value of the option.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
void value(std::size_t v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t value_;
|
||||
};
|
||||
|
||||
/// Option to specify the user agent identifier.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The default is to not specify the user agent.
|
||||
*
|
||||
* @par Example
|
||||
* To set the user agent for an object of class @c urdl::istream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::user_agent("Urdl"));
|
||||
* is.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* To set the user agent for an object of class @c urdl::read_stream:
|
||||
* @code
|
||||
* urdl::read_stream stream;
|
||||
* stream.set_option(urdl::http::user_agent("Urdl"));
|
||||
* stream.open("http://www.boost.org");
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
class user_agent
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c user_agent.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == ""</tt>.
|
||||
*/
|
||||
user_agent()
|
||||
: value_("")
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c user_agent.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
explicit user_agent(const std::string& v)
|
||||
: value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Gets the value of the option.
|
||||
/**
|
||||
* @returns The value of the option.
|
||||
*/
|
||||
std::string value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
/// Sets the value of the option.
|
||||
/**
|
||||
* @param v The desired value for the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Postcondition: <tt>value() == v</tt>
|
||||
*/
|
||||
void value(const std::string& v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
namespace errc {
|
||||
|
||||
/// HTTP error codes.
|
||||
/**
|
||||
* The enumerators of type @c errc_t are implicitly convertible to objects of
|
||||
* type @c boost::system::error_code.
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
enum errc_t
|
||||
{
|
||||
// Client-generated errors.
|
||||
|
||||
/// The response's status line was malformed.
|
||||
malformed_status_line = 1,
|
||||
|
||||
/// The response's headers were malformed.
|
||||
malformed_response_headers = 2,
|
||||
|
||||
// Server-generated status codes.
|
||||
|
||||
/// The server-generated status code "100 Continue".
|
||||
continue_request = 100,
|
||||
|
||||
/// The server-generated status code "101 Switching Protocols".
|
||||
switching_protocols = 101,
|
||||
|
||||
/// The server-generated status code "200 OK".
|
||||
ok = 200,
|
||||
|
||||
/// The server-generated status code "201 Created".
|
||||
created = 201,
|
||||
|
||||
/// The server-generated status code "202 Accepted".
|
||||
accepted = 202,
|
||||
|
||||
/// The server-generated status code "203 Non-Authoritative Information".
|
||||
non_authoritative_information = 203,
|
||||
|
||||
/// The server-generated status code "204 No Content".
|
||||
no_content = 204,
|
||||
|
||||
/// The server-generated status code "205 Reset Content".
|
||||
reset_content = 205,
|
||||
|
||||
/// The server-generated status code "206 Partial Content".
|
||||
partial_content = 206,
|
||||
|
||||
/// The server-generated status code "300 Multiple Choices".
|
||||
multiple_choices = 300,
|
||||
|
||||
/// The server-generated status code "301 Moved Permanently".
|
||||
moved_permanently = 301,
|
||||
|
||||
/// The server-generated status code "302 Found".
|
||||
found = 302,
|
||||
|
||||
/// The server-generated status code "303 See Other".
|
||||
see_other = 303,
|
||||
|
||||
/// The server-generated status code "304 Not Modified".
|
||||
not_modified = 304,
|
||||
|
||||
/// The server-generated status code "305 Use Proxy".
|
||||
use_proxy = 305,
|
||||
|
||||
/// The server-generated status code "307 Temporary Redirect".
|
||||
temporary_redirect = 307,
|
||||
|
||||
/// The server-generated status code "400 Bad Request".
|
||||
bad_request = 400,
|
||||
|
||||
/// The server-generated status code "401 Unauthorized".
|
||||
unauthorized = 401,
|
||||
|
||||
/// The server-generated status code "402 Payment Required".
|
||||
payment_required = 402,
|
||||
|
||||
/// The server-generated status code "403 Forbidden".
|
||||
forbidden = 403,
|
||||
|
||||
/// The server-generated status code "404 Not Found".
|
||||
not_found = 404,
|
||||
|
||||
/// The server-generated status code "405 Method Not Allowed".
|
||||
method_not_allowed = 405,
|
||||
|
||||
/// The server-generated status code "406 Not Acceptable".
|
||||
not_acceptable = 406,
|
||||
|
||||
/// The server-generated status code "407 Proxy Authentication Required".
|
||||
proxy_authentication_required = 407,
|
||||
|
||||
/// The server-generated status code "408 Request Time-out".
|
||||
request_timeout = 408,
|
||||
|
||||
/// The server-generated status code "409 Conflict".
|
||||
conflict = 409,
|
||||
|
||||
/// The server-generated status code "410 Gone".
|
||||
gone = 410,
|
||||
|
||||
/// The server-generated status code "411 Length Required".
|
||||
length_required = 411,
|
||||
|
||||
/// The server-generated status code "412 Precondition Failed".
|
||||
precondition_failed = 412,
|
||||
|
||||
/// The server-generated status code "413 Request Entity Too Large".
|
||||
request_entity_too_large = 413,
|
||||
|
||||
/// The server-generated status code "414 Request URI Too Large".
|
||||
request_uri_too_large = 414,
|
||||
|
||||
/// The server-generated status code "415 Unsupported Media Type".
|
||||
unsupported_media_type = 415,
|
||||
|
||||
/// The server-generated status code "416 Requested Range Not Satisfiable".
|
||||
requested_range_not_satisfiable = 416,
|
||||
|
||||
/// The server-generated status code "417 Expectation Failed".
|
||||
expectation_failed = 417,
|
||||
|
||||
/// The server-generated status code "500 Internal Server Error".
|
||||
internal_server_error = 500,
|
||||
|
||||
/// The server-generated status code "501 Not Implemented".
|
||||
not_implemented = 501,
|
||||
|
||||
/// The server-generated status code "502 Bad Gateway".
|
||||
bad_gateway = 502,
|
||||
|
||||
/// The server-generated status code "503 Service Unavailable".
|
||||
service_unavailable = 503,
|
||||
|
||||
/// The server-generated status code "504 Gateway Timeout".
|
||||
gateway_timeout = 504,
|
||||
|
||||
/// The server-generated status code "505 HTTP Version Not Supported".
|
||||
version_not_supported = 505
|
||||
};
|
||||
|
||||
/// Converts a value of type @c errc_t to a corresponding object of type
|
||||
/// @c boost::system::error_code.
|
||||
/**
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/http.hpp> @n
|
||||
* @e Namespace: @c urdl::http
|
||||
*/
|
||||
inline boost::system::error_code make_error_code(errc_t e)
|
||||
{
|
||||
return boost::system::error_code(
|
||||
static_cast<int>(e), http::error_category());
|
||||
}
|
||||
|
||||
} // namespace errc
|
||||
} // namespace http
|
||||
} // namespace urdl
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
|
||||
template <>
|
||||
struct is_error_code_enum<urdl::http::errc::errc_t>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace boost
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# include "urdl/impl/http.ipp"
|
||||
#endif
|
||||
|
||||
#endif // URDL_HTTP_HPP
|
@ -1,158 +0,0 @@
|
||||
//
|
||||
// http.ipp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_HTTP_IPP
|
||||
#define URDL_HTTP_IPP
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
class error_category_impl
|
||||
: public boost::system::error_category
|
||||
{
|
||||
virtual const char* name() const URDL_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "HTTP";
|
||||
}
|
||||
|
||||
virtual std::string message(int e) const
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case http::errc::malformed_status_line:
|
||||
return "Malformed status line";
|
||||
case http::errc::malformed_response_headers:
|
||||
return "Malformed response headers";
|
||||
case http::errc::continue_request:
|
||||
return "Continue";
|
||||
case http::errc::switching_protocols:
|
||||
return "Switching protocols";
|
||||
case http::errc::ok:
|
||||
return "OK";
|
||||
case http::errc::created:
|
||||
return "Created";
|
||||
case http::errc::accepted:
|
||||
return "Accepted";
|
||||
case http::errc::non_authoritative_information:
|
||||
return "Non-authoritative information";
|
||||
case http::errc::no_content:
|
||||
return "No content";
|
||||
case http::errc::reset_content:
|
||||
return "Reset content";
|
||||
case http::errc::partial_content:
|
||||
return "Partial content";
|
||||
case http::errc::multiple_choices:
|
||||
return "Multiple choices";
|
||||
case http::errc::moved_permanently:
|
||||
return "Moved permanently";
|
||||
case http::errc::found:
|
||||
return "Found";
|
||||
case http::errc::see_other:
|
||||
return "See other";
|
||||
case http::errc::not_modified:
|
||||
return "Not modified";
|
||||
case http::errc::use_proxy:
|
||||
return "Use proxy";
|
||||
case http::errc::temporary_redirect:
|
||||
return "Temporary redirect";
|
||||
case http::errc::bad_request:
|
||||
return "Bad request";
|
||||
case http::errc::unauthorized:
|
||||
return "Unauthorized";
|
||||
case http::errc::payment_required:
|
||||
return "Payment required";
|
||||
case http::errc::forbidden:
|
||||
return "Forbidden";
|
||||
case http::errc::not_found:
|
||||
return "Not found";
|
||||
case http::errc::method_not_allowed:
|
||||
return "Method not allowed";
|
||||
case http::errc::not_acceptable:
|
||||
return "Not acceptable";
|
||||
case http::errc::proxy_authentication_required:
|
||||
return "Proxy authentication required";
|
||||
case http::errc::request_timeout:
|
||||
return "Request time-out";
|
||||
case http::errc::conflict:
|
||||
return "Conflict";
|
||||
case http::errc::gone:
|
||||
return "Gone";
|
||||
case http::errc::length_required:
|
||||
return "Length required";
|
||||
case http::errc::precondition_failed:
|
||||
return "Precondition failed";
|
||||
case http::errc::request_entity_too_large:
|
||||
return "Request entity too large";
|
||||
case http::errc::request_uri_too_large:
|
||||
return "Request URI too large";
|
||||
case http::errc::unsupported_media_type:
|
||||
return "Unsupported media type";
|
||||
case http::errc::requested_range_not_satisfiable:
|
||||
return "Requested range not satisfiable";
|
||||
case http::errc::expectation_failed:
|
||||
return "Expectation failed";
|
||||
case http::errc::internal_server_error:
|
||||
return "Internal server error";
|
||||
case http::errc::not_implemented:
|
||||
return "Not implemented";
|
||||
case http::errc::bad_gateway:
|
||||
return "Bad gateway";
|
||||
case http::errc::service_unavailable:
|
||||
return "Service unavailable";
|
||||
case http::errc::gateway_timeout:
|
||||
return "Gateway time-out";
|
||||
case http::errc::version_not_supported:
|
||||
return "HTTP version not supported";
|
||||
default:
|
||||
return "Unknown HTTP error";
|
||||
}
|
||||
}
|
||||
|
||||
virtual boost::system::error_condition default_error_condition(
|
||||
int e) const URDL_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case http::errc::unauthorized:
|
||||
case http::errc::forbidden:
|
||||
return boost::system::errc::permission_denied;
|
||||
case http::errc::not_found:
|
||||
return boost::system::errc::no_such_file_or_directory;
|
||||
default:
|
||||
return boost::system::error_condition(e, *this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
const boost::system::error_category& error_category()
|
||||
{
|
||||
static detail::error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
static const boost::system::error_category& category_instance
|
||||
= error_category();
|
||||
|
||||
} // namespace detail
|
||||
} // namespace http
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_HTTP_IPP
|
@ -1,251 +0,0 @@
|
||||
//
|
||||
// istreambuf.ipp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_IMPL_ISTREAMBUF_IPP
|
||||
#define URDL_IMPL_ISTREAMBUF_IPP
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "urdl/read_stream.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
struct istreambuf::body
|
||||
{
|
||||
enum { putback_max = 8 };
|
||||
enum { buffer_size = 512 };
|
||||
|
||||
body()
|
||||
: read_stream_(io_service_),
|
||||
timer_(io_service_),
|
||||
open_timeout_(300 * 1000),
|
||||
read_timeout_(300 * 1000)
|
||||
{
|
||||
}
|
||||
|
||||
boost::array<char, buffer_size> get_buffer_;
|
||||
boost::asio::io_service io_service_;
|
||||
boost::system::error_code error_;
|
||||
read_stream read_stream_;
|
||||
boost::asio::deadline_timer timer_;
|
||||
std::size_t open_timeout_;
|
||||
std::size_t read_timeout_;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct istreambuf_open_handler
|
||||
{
|
||||
boost::system::error_code& error_;
|
||||
boost::asio::deadline_timer& timer_;
|
||||
void operator()(boost::system::error_code ec)
|
||||
{
|
||||
error_ = ec;
|
||||
timer_.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
struct istreambuf_read_handler
|
||||
{
|
||||
boost::system::error_code& error_;
|
||||
std::size_t& bytes_transferred_;
|
||||
boost::asio::deadline_timer& timer_;
|
||||
void operator()(boost::system::error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
error_ = ec;
|
||||
bytes_transferred_ = bytes_transferred;
|
||||
timer_.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
struct istreambuf_timeout_handler
|
||||
{
|
||||
read_stream& read_stream_;
|
||||
void operator()(boost::system::error_code ec)
|
||||
{
|
||||
if (ec != boost::asio::error::operation_aborted)
|
||||
read_stream_.close(ec);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
istreambuf::istreambuf()
|
||||
: body_(new body)
|
||||
{
|
||||
init_buffers();
|
||||
}
|
||||
|
||||
istreambuf::~istreambuf()
|
||||
{
|
||||
try
|
||||
{
|
||||
delete body_;
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// Swallow the exception.
|
||||
}
|
||||
}
|
||||
|
||||
void istreambuf::set_options(const option_set& options)
|
||||
{
|
||||
body_->read_stream_.set_options(options);
|
||||
}
|
||||
|
||||
option_set istreambuf::get_options() const
|
||||
{
|
||||
return body_->read_stream_.get_options();
|
||||
}
|
||||
|
||||
istreambuf* istreambuf::open(const url& u)
|
||||
{
|
||||
if (is_open())
|
||||
return 0;
|
||||
|
||||
init_buffers();
|
||||
body_->read_stream_.close(body_->error_);
|
||||
|
||||
detail::istreambuf_open_handler oh = { body_->error_, body_->timer_ };
|
||||
body_->read_stream_.async_open(u, oh);
|
||||
|
||||
detail::istreambuf_timeout_handler th = { body_->read_stream_ };
|
||||
body_->timer_.expires_from_now(
|
||||
boost::posix_time::milliseconds(body_->open_timeout_));
|
||||
body_->timer_.async_wait(th);
|
||||
|
||||
body_->io_service_.reset();
|
||||
body_->io_service_.run();
|
||||
|
||||
if (!body_->read_stream_.is_open())
|
||||
body_->error_ = make_error_code(boost::system::errc::timed_out);
|
||||
|
||||
return !body_->error_ ? this : 0;
|
||||
}
|
||||
|
||||
bool istreambuf::is_open() const
|
||||
{
|
||||
return body_->read_stream_.is_open();
|
||||
}
|
||||
|
||||
istreambuf* istreambuf::close()
|
||||
{
|
||||
if (!is_open())
|
||||
return 0;
|
||||
|
||||
body_->read_stream_.close(body_->error_);
|
||||
if (!body_->error_)
|
||||
init_buffers();
|
||||
return !body_->error_ ? this : 0;
|
||||
}
|
||||
|
||||
const boost::system::error_code& istreambuf::puberror() const
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
std::size_t istreambuf::open_timeout() const
|
||||
{
|
||||
return body_->open_timeout_;
|
||||
}
|
||||
|
||||
void istreambuf::open_timeout(std::size_t milliseconds)
|
||||
{
|
||||
body_->open_timeout_ = milliseconds;
|
||||
}
|
||||
|
||||
std::size_t istreambuf::read_timeout() const
|
||||
{
|
||||
return body_->read_timeout_;
|
||||
}
|
||||
|
||||
void istreambuf::read_timeout(std::size_t milliseconds)
|
||||
{
|
||||
body_->read_timeout_ = milliseconds;
|
||||
}
|
||||
|
||||
std::string istreambuf::content_type() const
|
||||
{
|
||||
return body_->read_stream_.content_type();
|
||||
}
|
||||
|
||||
std::size_t istreambuf::content_length() const
|
||||
{
|
||||
return body_->read_stream_.content_length();
|
||||
}
|
||||
|
||||
std::string istreambuf::headers() const
|
||||
{
|
||||
return body_->read_stream_.headers();
|
||||
}
|
||||
|
||||
std::streambuf::int_type istreambuf::underflow()
|
||||
{
|
||||
if (gptr() == egptr())
|
||||
{
|
||||
std::size_t bytes_transferred = 0;
|
||||
detail::istreambuf_read_handler rh
|
||||
= { body_->error_, bytes_transferred, body_->timer_ };
|
||||
body_->read_stream_.async_read_some(boost::asio::buffer(
|
||||
boost::asio::buffer(body_->get_buffer_) + body::putback_max), rh);
|
||||
|
||||
detail::istreambuf_timeout_handler th = { body_->read_stream_ };
|
||||
body_->timer_.expires_from_now(
|
||||
boost::posix_time::milliseconds(body_->read_timeout_));
|
||||
body_->timer_.async_wait(th);
|
||||
|
||||
body_->io_service_.reset();
|
||||
body_->io_service_.run();
|
||||
|
||||
if (!body_->read_stream_.is_open())
|
||||
body_->error_ = make_error_code(boost::system::errc::timed_out);
|
||||
|
||||
if (body_->error_)
|
||||
{
|
||||
if (body_->error_ == boost::asio::error::eof)
|
||||
{
|
||||
body_->error_ = boost::system::error_code();
|
||||
return traits_type::eof();
|
||||
}
|
||||
boost::throw_exception(boost::system::system_error(body_->error_));
|
||||
}
|
||||
|
||||
setg(body_->get_buffer_.begin(),
|
||||
body_->get_buffer_.begin() + body::putback_max,
|
||||
body_->get_buffer_.begin() + body::putback_max + bytes_transferred);
|
||||
return traits_type::to_int_type(*gptr());
|
||||
}
|
||||
else
|
||||
{
|
||||
return traits_type::eof();
|
||||
}
|
||||
}
|
||||
|
||||
const boost::system::error_code& istreambuf::error() const
|
||||
{
|
||||
return body_->error_;
|
||||
}
|
||||
|
||||
void istreambuf::init_buffers()
|
||||
{
|
||||
setg(body_->get_buffer_.begin(),
|
||||
body_->get_buffer_.begin() + body::putback_max,
|
||||
body_->get_buffer_.begin() + body::putback_max);
|
||||
}
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_IMPL_ISTREAMBUF_IPP
|
@ -1,106 +0,0 @@
|
||||
//
|
||||
// option_set.ipp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_OPTION_SET_IPP
|
||||
#define URDL_OPTION_SET_IPP
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
option_set::option_set()
|
||||
{
|
||||
}
|
||||
|
||||
option_set::option_set(const option_set& other)
|
||||
{
|
||||
detail::scoped_ptr<option_wrapper_base>* prev_link = &head_;
|
||||
option_wrapper_base* node = other.head_.get();
|
||||
while (node)
|
||||
{
|
||||
prev_link->reset(node->clone());
|
||||
prev_link = &prev_link->get()->next;
|
||||
node = node->next.get();
|
||||
}
|
||||
}
|
||||
|
||||
option_set::~option_set()
|
||||
{
|
||||
}
|
||||
|
||||
option_set& option_set::operator=(const option_set& other)
|
||||
{
|
||||
option_set tmp(other);
|
||||
head_.reset(tmp.head_.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void option_set::set_options(const option_set& other)
|
||||
{
|
||||
option_wrapper_base* node = other.head_.get();
|
||||
while (node)
|
||||
{
|
||||
set_option_wrapper_base(node->clone());
|
||||
node = node->next.get();
|
||||
}
|
||||
}
|
||||
|
||||
void option_set::set_option_wrapper_base(option_set::option_wrapper_base* o)
|
||||
{
|
||||
detail::scoped_ptr<option_wrapper_base>* prev_link = &head_;
|
||||
option_wrapper_base* node = head_.get();
|
||||
while (node)
|
||||
{
|
||||
if (o->type_info() == node->type_info())
|
||||
{
|
||||
o->next.reset(node->next.release());
|
||||
prev_link->reset(o);
|
||||
return;
|
||||
}
|
||||
prev_link = &node->next;
|
||||
node = node->next.get();
|
||||
}
|
||||
prev_link->reset(o);
|
||||
}
|
||||
|
||||
option_set::option_wrapper_base* option_set::get_option_wrapper_base(
|
||||
const std::type_info& ti) const
|
||||
{
|
||||
option_wrapper_base* node = head_.get();
|
||||
while (node)
|
||||
{
|
||||
if (ti == node->type_info())
|
||||
return node;
|
||||
node = node->next.get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void option_set::clear_option_wrapper_base(const std::type_info& ti)
|
||||
{
|
||||
detail::scoped_ptr<option_wrapper_base>* prev_link = &head_;
|
||||
option_wrapper_base* node = head_.get();
|
||||
while (node)
|
||||
{
|
||||
if (ti == node->type_info())
|
||||
{
|
||||
prev_link->reset(node->next.release());
|
||||
return;
|
||||
}
|
||||
prev_link = &node->next;
|
||||
node = node->next.get();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_OPTION_SET_IPP
|
348
thirdparty/urdl-2013-08-15/include/urdl/impl/url.ipp
vendored
348
thirdparty/urdl-2013-08-15/include/urdl/impl/url.ipp
vendored
@ -1,348 +0,0 @@
|
||||
//
|
||||
// url.ipp
|
||||
// ~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_URL_IPP
|
||||
#define URDL_URL_IPP
|
||||
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
unsigned short url::port() const
|
||||
{
|
||||
if (!port_.empty())
|
||||
return std::atoi(port_.c_str());
|
||||
if (protocol_ == "http")
|
||||
return 80;
|
||||
if (protocol_ == "https")
|
||||
return 443;
|
||||
if (protocol_ == "ftp")
|
||||
return 21;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string url::path() const
|
||||
{
|
||||
std::string tmp_path;
|
||||
unescape_path(path_, tmp_path);
|
||||
return tmp_path;
|
||||
}
|
||||
|
||||
std::string url::to_string(int components) const
|
||||
{
|
||||
std::string s;
|
||||
|
||||
if ((components & protocol_component) != 0 && !protocol_.empty())
|
||||
{
|
||||
s = protocol_;
|
||||
s += "://";
|
||||
}
|
||||
|
||||
if ((components & user_info_component) != 0 && !user_info_.empty())
|
||||
{
|
||||
s += user_info_;
|
||||
s += "@";
|
||||
}
|
||||
|
||||
if ((components & host_component) != 0)
|
||||
{
|
||||
if (ipv6_host_)
|
||||
s += "[";
|
||||
s += host_;
|
||||
if (ipv6_host_)
|
||||
s += "]";
|
||||
}
|
||||
|
||||
if ((components & port_component) != 0 && !port_.empty())
|
||||
{
|
||||
s += ":";
|
||||
s += port_;
|
||||
}
|
||||
|
||||
if ((components & path_component) != 0 && !path_.empty())
|
||||
{
|
||||
s += path_;
|
||||
}
|
||||
|
||||
if ((components & query_component) != 0 && !query_.empty())
|
||||
{
|
||||
s += "?";
|
||||
s += query_;
|
||||
}
|
||||
|
||||
if ((components & fragment_component) != 0 && !fragment_.empty())
|
||||
{
|
||||
s += "#";
|
||||
s += fragment_;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
url url::from_string(const char* s, boost::system::error_code& ec)
|
||||
{
|
||||
url new_url;
|
||||
|
||||
// Protocol.
|
||||
std::size_t length = std::strcspn(s, ":");
|
||||
new_url.protocol_.assign(s, s + length);
|
||||
for (std::size_t i = 0; i < new_url.protocol_.length(); ++i)
|
||||
new_url.protocol_[i] = std::tolower(new_url.protocol_[i]);
|
||||
s += length;
|
||||
|
||||
// "://".
|
||||
if (*s++ != ':')
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
if (*s++ != '/')
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
if (*s++ != '/')
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
|
||||
// UserInfo.
|
||||
length = std::strcspn(s, "@:[/?#");
|
||||
if (s[length] == '@')
|
||||
{
|
||||
new_url.user_info_.assign(s, s + length);
|
||||
s += length + 1;
|
||||
}
|
||||
else if (s[length] == ':')
|
||||
{
|
||||
std::size_t length2 = std::strcspn(s + length, "@/?#");
|
||||
if (s[length + length2] == '@')
|
||||
{
|
||||
new_url.user_info_.assign(s, s + length + length2);
|
||||
s += length + length2 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Host.
|
||||
if (*s == '[')
|
||||
{
|
||||
length = std::strcspn(++s, "]");
|
||||
if (s[length] != ']')
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
new_url.host_.assign(s, s + length);
|
||||
new_url.ipv6_host_ = true;
|
||||
s += length + 1;
|
||||
if (std::strcspn(s, ":/?#") != 0)
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
length = std::strcspn(s, ":/?#");
|
||||
new_url.host_.assign(s, s + length);
|
||||
s += length;
|
||||
}
|
||||
|
||||
// Port.
|
||||
if (*s == ':')
|
||||
{
|
||||
length = std::strcspn(++s, "/?#");
|
||||
if (length == 0)
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
new_url.port_.assign(s, s + length);
|
||||
for (std::size_t i = 0; i < new_url.port_.length(); ++i)
|
||||
{
|
||||
if (!std::isdigit(new_url.port_[i]))
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
}
|
||||
s += length;
|
||||
}
|
||||
|
||||
// Path.
|
||||
if (*s == '/')
|
||||
{
|
||||
length = std::strcspn(s, "?#");
|
||||
new_url.path_.assign(s, s + length);
|
||||
std::string tmp_path;
|
||||
if (!unescape_path(new_url.path_, tmp_path))
|
||||
{
|
||||
ec = make_error_code(boost::system::errc::invalid_argument);
|
||||
return url();
|
||||
}
|
||||
s += length;
|
||||
}
|
||||
else
|
||||
new_url.path_ = "/";
|
||||
|
||||
// Query.
|
||||
if (*s == '?')
|
||||
{
|
||||
length = std::strcspn(++s, "#");
|
||||
new_url.query_.assign(s, s + length);
|
||||
s += length;
|
||||
}
|
||||
|
||||
// Fragment.
|
||||
if (*s == '#')
|
||||
new_url.fragment_.assign(++s);
|
||||
|
||||
ec = boost::system::error_code();
|
||||
return new_url;
|
||||
}
|
||||
|
||||
url url::from_string(const char* s)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
url new_url(from_string(s, ec));
|
||||
if (ec)
|
||||
{
|
||||
boost::system::system_error ex(ec);
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
return new_url;
|
||||
}
|
||||
|
||||
url url::from_string(const std::string& s, boost::system::error_code& ec)
|
||||
{
|
||||
return from_string(s.c_str(), ec);
|
||||
}
|
||||
|
||||
url url::from_string(const std::string& s)
|
||||
{
|
||||
return from_string(s.c_str());
|
||||
}
|
||||
|
||||
bool url::unescape_path(const std::string& in, std::string& out)
|
||||
{
|
||||
out.clear();
|
||||
out.reserve(in.size());
|
||||
for (std::size_t i = 0; i < in.size(); ++i)
|
||||
{
|
||||
switch (in[i])
|
||||
{
|
||||
case '%':
|
||||
if (i + 3 <= in.size())
|
||||
{
|
||||
unsigned int value = 0;
|
||||
for (std::size_t j = i + 1; j < i + 3; ++j)
|
||||
{
|
||||
switch (in[j])
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
value += in[j] - '0';
|
||||
break;
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
value += in[j] - 'a' + 10;
|
||||
break;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
value += in[j] - 'A' + 10;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (j == i + 1)
|
||||
value <<= 4;
|
||||
}
|
||||
out += static_cast<char>(value);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case '-': case '_': case '.': case '!': case '~': case '*':
|
||||
case '\'': case '(': case ')': case ':': case '@': case '&':
|
||||
case '=': case '+': case '$': case ',': case '/': case ';':
|
||||
out += in[i];
|
||||
break;
|
||||
default:
|
||||
if (!std::isalnum(in[i]))
|
||||
return false;
|
||||
out += in[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const url& a, const url& b)
|
||||
{
|
||||
return a.protocol_ == b.protocol_
|
||||
&& a.user_info_ == b.user_info_
|
||||
&& a.host_ == b.host_
|
||||
&& a.port_ == b.port_
|
||||
&& a.path_ == b.path_
|
||||
&& a.query_ == b.query_
|
||||
&& a.fragment_ == b.fragment_;
|
||||
}
|
||||
|
||||
bool operator!=(const url& a, const url& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
bool operator<(const url& a, const url& b)
|
||||
{
|
||||
if (a.protocol_ < b.protocol_)
|
||||
return true;
|
||||
if (b.protocol_ < a.protocol_)
|
||||
return false;
|
||||
|
||||
if (a.user_info_ < b.user_info_)
|
||||
return true;
|
||||
if (b.user_info_ < a.user_info_)
|
||||
return false;
|
||||
|
||||
if (a.host_ < b.host_)
|
||||
return true;
|
||||
if (b.host_ < a.host_)
|
||||
return false;
|
||||
|
||||
if (a.port_ < b.port_)
|
||||
return true;
|
||||
if (b.port_ < a.port_)
|
||||
return false;
|
||||
|
||||
if (a.path_ < b.path_)
|
||||
return true;
|
||||
if (b.path_ < a.path_)
|
||||
return false;
|
||||
|
||||
if (a.query_ < b.query_)
|
||||
return true;
|
||||
if (b.query_ < a.query_)
|
||||
return false;
|
||||
|
||||
return a.fragment_ < b.fragment_;
|
||||
}
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_URL_IPP
|
379
thirdparty/urdl-2013-08-15/include/urdl/istream.hpp
vendored
379
thirdparty/urdl-2013-08-15/include/urdl/istream.hpp
vendored
@ -1,379 +0,0 @@
|
||||
//
|
||||
// istream.hpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_ISTREAM_HPP
|
||||
#define URDL_ISTREAM_HPP
|
||||
|
||||
#include <istream>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include "urdl/istreambuf.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
/// The class @c istream supports reading content from a specified URL.
|
||||
/**
|
||||
* @par Remarks
|
||||
* The class stores an object of class @c istreambuf.
|
||||
*
|
||||
* Currently supported URL protocols are @c http, @c https and @c file.
|
||||
*
|
||||
* @par Example
|
||||
* To read the entire content of a resource located by a URL into a string:
|
||||
* @code
|
||||
* urdl::istream is("http://www.boost.org/LICENSE_1_0.txt");
|
||||
* if (is)
|
||||
* {
|
||||
* std::string content;
|
||||
* if (std::getline(is, content, std::char_traits<char>::eof()))
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/istream.hpp> @n
|
||||
* @e Namespace: @c urdl
|
||||
*/
|
||||
class istream
|
||||
: private boost::base_from_member<istreambuf>,
|
||||
public std::basic_istream<char>
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c istream.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Initializes the base class with @c std::basic_istream<char>(sb),
|
||||
* where sb is an object of class @c istreambuf stored within the class.
|
||||
*/
|
||||
istream()
|
||||
: std::basic_istream<char>(
|
||||
&this->boost::base_from_member<istreambuf>::member)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c istream.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @par Remarks
|
||||
* Initializes the base class with @c std::basic_istream<char>(sb),
|
||||
* where @c sb is an object of class @c istreambuf stored within the class. It
|
||||
* also opens @c sb by performing @c sb.open(u) and, if that fails (returns a
|
||||
* null pointer), calls @c setstate(failbit).
|
||||
*/
|
||||
explicit istream(const url& u)
|
||||
: std::basic_istream<char>(
|
||||
&this->boost::base_from_member<istreambuf>::member)
|
||||
{
|
||||
if (rdbuf()->open(u) == 0)
|
||||
setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c istream.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @param options The options to be set on the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Initializes the base class with @c std::basic_istream<char>(sb), where
|
||||
* @c sb is an object of class @c istreambuf stored within the class. It also
|
||||
* performs @c rdbuf()->set_options(options), then opens @c sb by performing
|
||||
* @c sb.open(u) and, if that fails (returns a null pointer), calls
|
||||
* @c setstate(failbit).
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::option_set options;
|
||||
* options.set_option(urdl::http::max_redirects(1));
|
||||
* urdl::istream is("http://www.boost.org", options);
|
||||
* @endcode
|
||||
*/
|
||||
explicit istream(const url& u, const option_set& options)
|
||||
: std::basic_istream<char>(
|
||||
&this->boost::base_from_member<istreambuf>::member)
|
||||
{
|
||||
rdbuf()->set_options(options);
|
||||
if (rdbuf()->open(u) == 0)
|
||||
setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
/// Sets an option to control the behaviour of the stream.
|
||||
/**
|
||||
* @param option The option to be set on the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Performs @c rdbuf()->set_option(option). Options are uniquely identified by
|
||||
* type.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* is.set_option(urdl::http::max_redirects(1));
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Option>
|
||||
void set_option(const Option& option)
|
||||
{
|
||||
rdbuf()->set_option(option);
|
||||
}
|
||||
|
||||
/// Sets options to control the behaviour of the stream.
|
||||
/**
|
||||
* @param options The options to be set on the stream. The options in the set
|
||||
* are added on top of any options already set on the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Performs @c rdbuf()->set_options(options).
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* urdl::option_set options;
|
||||
* options.set_option(urdl::http::max_redirects(1));
|
||||
* options.set_option(urdl::ssl::verify_peer(false));
|
||||
* stream.set_options(options);
|
||||
* @endcode
|
||||
*/
|
||||
void set_options(const option_set& options)
|
||||
{
|
||||
rdbuf()->set_options(options);
|
||||
}
|
||||
|
||||
/// Gets the current value of an option that controls the behaviour of the
|
||||
/// stream.
|
||||
/**
|
||||
* @returns The current value of the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->get_option<Option>(). Options are uniquely identified
|
||||
* by type.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* urdl::http::max_redirects option
|
||||
* = is.get_option<urdl::http::max_redirects>();
|
||||
* std::size_t value = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Option>
|
||||
Option get_option() const
|
||||
{
|
||||
return rdbuf()->get_option<Option>();
|
||||
}
|
||||
|
||||
/// Gets the values of all options set on the stream.
|
||||
/**
|
||||
* @returns An option set containing all options from the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->get_options().
|
||||
*
|
||||
* @par Example
|
||||
* To get the options that have been set on the stream:
|
||||
* @code
|
||||
* urdl::istream is;
|
||||
* ...
|
||||
* urdl::option_set options(is.get_options());
|
||||
* urdl::http::max_redirects option
|
||||
* = options.get_option<urdl::http::max_redirects>();
|
||||
* std::size_t value = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
option_set get_options() const
|
||||
{
|
||||
return rdbuf()->get_options();
|
||||
}
|
||||
|
||||
/// Determines whether the stream is open.
|
||||
/**
|
||||
* @returns @c true if the stream is open, @c false otherwise.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->is_open().
|
||||
*/
|
||||
bool is_open() const
|
||||
{
|
||||
return rdbuf()->is_open();
|
||||
}
|
||||
|
||||
/// Opens the specified URL.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @par Remarks
|
||||
* Calls @c rdbuf()->open(u). If that function does not return a null
|
||||
* pointer, calls @c clear(). Otherwise calls @c setstate(failbit) (which may
|
||||
* throw @c ios_base::failure).
|
||||
*/
|
||||
void open(const url& u)
|
||||
{
|
||||
if (rdbuf()->open(u) == 0)
|
||||
setstate(std::ios_base::failbit);
|
||||
else
|
||||
clear();
|
||||
}
|
||||
|
||||
/// Closes the stream.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Calls @c rdbuf()->close() and, if that function returns a null
|
||||
* pointer, calls @c setstate(failbit) (which may throw @c ios_base::failure).
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
if (rdbuf()->close() == 0)
|
||||
setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
/// Gets the underlying stream buffer.
|
||||
/**
|
||||
* @returns A pointer to the stream buffer contained within the class.
|
||||
*/
|
||||
istreambuf* rdbuf() const
|
||||
{
|
||||
return const_cast<istreambuf*>(
|
||||
&this->boost::base_from_member<istreambuf>::member);
|
||||
}
|
||||
|
||||
/// Gets the last error associated with the stream.
|
||||
/**
|
||||
* @returns An @c error_code corresponding to the last error from the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns a reference to an @c error_code object representing the last
|
||||
* failure reported by an @c istreambuf function. The set of possible
|
||||
* @c error_code values and categories depends on the protocol of the URL
|
||||
* used to open the stream.
|
||||
*
|
||||
* @par Example
|
||||
* To take action given a specific error:
|
||||
* @code
|
||||
* urdl::istream is("http://somesite/page");
|
||||
* if (!is)
|
||||
* {
|
||||
* if (is.error() == urdl::http::errc::forbidden)
|
||||
* {
|
||||
* std::cout << "Computer says no" << std::endl;
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
const boost::system::error_code& error() const
|
||||
{
|
||||
return rdbuf()->puberror();
|
||||
}
|
||||
|
||||
/// Gets the open timeout of the stream.
|
||||
/**
|
||||
* @returns The timeout, in milliseconds, used when opening a URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->open_timeout().
|
||||
*/
|
||||
std::size_t open_timeout() const
|
||||
{
|
||||
return rdbuf()->open_timeout();
|
||||
}
|
||||
|
||||
/// Sets the open timeout of the stream.
|
||||
/**
|
||||
* @param milliseconds The timeout, in milliseconds, to be used when opening
|
||||
* a URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* Performs @c rdbuf()->open_timeout(milliseconds).
|
||||
*/
|
||||
void open_timeout(std::size_t milliseconds)
|
||||
{
|
||||
rdbuf()->open_timeout(milliseconds);
|
||||
}
|
||||
|
||||
/// Gets the read timeout of the stream.
|
||||
/**
|
||||
* @returns The timeout, in milliseconds, used for individual read operations
|
||||
* on the underlying transport.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->read_timeout().
|
||||
*/
|
||||
std::size_t read_timeout() const
|
||||
{
|
||||
return rdbuf()->read_timeout();
|
||||
}
|
||||
|
||||
/// Sets the read timeout of the stream.
|
||||
/**
|
||||
* @param milliseconds The timeout, in milliseconds, to be used for individual
|
||||
* read operations on the underlying transport.
|
||||
*
|
||||
* @par Remarks
|
||||
* Performs @c rdbuf()->read_timeout(milliseconds).
|
||||
*/
|
||||
void read_timeout(std::size_t milliseconds)
|
||||
{
|
||||
rdbuf()->read_timeout(milliseconds);
|
||||
}
|
||||
|
||||
/// Gets the MIME type of the content obtained from the URL.
|
||||
/**
|
||||
* @returns A string specifying the MIME type. Examples of possible return
|
||||
* values include @c text/plain, @c text/html and @c image/png.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->content_type().
|
||||
*
|
||||
* Not all URL protocols support a content type. For these protocols, this
|
||||
* function returns an empty string.
|
||||
*/
|
||||
std::string content_type() const
|
||||
{
|
||||
return rdbuf()->content_type();
|
||||
}
|
||||
|
||||
/// Gets the length of the content obtained from the URL.
|
||||
/**
|
||||
* @returns The length, in bytes, of the content. If the content associated
|
||||
* with the URL does not specify a length,
|
||||
* @c std::numeric_limits<std::size_t>::max().
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->content_length().
|
||||
*/
|
||||
std::size_t content_length() const
|
||||
{
|
||||
return rdbuf()->content_length();
|
||||
}
|
||||
|
||||
/// Gets the protocol-specific headers obtained from the URL.
|
||||
/**
|
||||
* @returns A string containing the headers returned with the content from the
|
||||
* URL. The format and interpretation of these headers is specific to the
|
||||
* protocol associated with the URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c rdbuf()->headers().
|
||||
*/
|
||||
std::string headers() const
|
||||
{
|
||||
return rdbuf()->headers();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_ISTREAM_HPP
|
@ -1,216 +0,0 @@
|
||||
//
|
||||
// istreambuf.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_ISTREAMBUF_HPP
|
||||
#define URDL_ISTREAMBUF_HPP
|
||||
|
||||
#include <streambuf>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include "urdl/detail/config.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "urdl/url.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
/// The class @c istreambuf associates the input sequence with the content from
|
||||
/// a specified URL.
|
||||
/**
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/istreambuf.hpp> @n
|
||||
* @e Namespace: @c urdl
|
||||
*/
|
||||
class istreambuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c istreambuf.
|
||||
URDL_DECL istreambuf();
|
||||
|
||||
/// Destroys an object of class @c istreambuf.
|
||||
URDL_DECL ~istreambuf();
|
||||
|
||||
/// Sets an option to control the behaviour of the stream buffer.
|
||||
/**
|
||||
* @param option The option to be set on the stream buffer.
|
||||
*
|
||||
* @par Remarks
|
||||
* Options are uniquely identified by type.
|
||||
*/
|
||||
template <typename Option>
|
||||
void set_option(const Option& option)
|
||||
{
|
||||
option_set options;
|
||||
options.set_option(option);
|
||||
set_options(options);
|
||||
}
|
||||
|
||||
/// Sets options to control the behaviour of the stream buffer.
|
||||
/**
|
||||
* @param options The options to be set on the stream buffer.
|
||||
*/
|
||||
URDL_DECL void set_options(const option_set& options);
|
||||
|
||||
/// Gets the current value of an option that controls the behaviour of the
|
||||
/// stream buffer.
|
||||
/**
|
||||
* @returns The current value of the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Options are uniquely identified by type.
|
||||
*/
|
||||
template <typename Option>
|
||||
Option get_option() const
|
||||
{
|
||||
option_set options(get_options());
|
||||
return options.get_option<Option>();
|
||||
}
|
||||
|
||||
/// Gets the values of all options set on the stream.
|
||||
/**
|
||||
* @returns An option set containing all options from the stream buffer.
|
||||
*/
|
||||
URDL_DECL option_set get_options() const;
|
||||
|
||||
/// Determines whether the stream buffer is open.
|
||||
/**
|
||||
* @returns @c true if the stream buffer is open, @c false otherwise.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c true if a previous call to @c open succeeded (returned a
|
||||
* non-null value) and there has been no intervening call to @c close.
|
||||
*/
|
||||
URDL_DECL bool is_open() const;
|
||||
|
||||
/// Opens the specified URL.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @returns @c this on success, a null pointer otherwise.
|
||||
*
|
||||
* @par Remarks
|
||||
* If <tt>is_open() != false</tt>, returns a null pointer. Otherwise,
|
||||
* initializes the @c istreambuf as required.
|
||||
*/
|
||||
URDL_DECL istreambuf* open(const url& u);
|
||||
|
||||
/// Closes the stream buffer.
|
||||
/**
|
||||
* @returns @c this on success, a null pointer otherwise.
|
||||
*
|
||||
* @par Remarks
|
||||
* If <tt>is_open() == false</tt>, returns a null pointer. Otherwise, closes
|
||||
* the underlying transport's resources as required. If any of those
|
||||
* operations fail, @c close fails by returning a null pointer.
|
||||
*/
|
||||
URDL_DECL istreambuf* close();
|
||||
|
||||
/// Gets the last error associated with the stream buffer.
|
||||
/**
|
||||
* @returns An @c error_code corresponding to the last error from the stream
|
||||
* buffer.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns @c error().
|
||||
*/
|
||||
URDL_DECL const boost::system::error_code& puberror() const;
|
||||
|
||||
/// Gets the open timeout of the stream buffer.
|
||||
/**
|
||||
* @returns The timeout, in milliseconds, used when opening a URL.
|
||||
*/
|
||||
URDL_DECL std::size_t open_timeout() const;
|
||||
|
||||
/// Sets the open timeout of the stream buffer.
|
||||
/**
|
||||
* @param milliseconds The timeout, in milliseconds, to be used when opening
|
||||
* a URL.
|
||||
*/
|
||||
URDL_DECL void open_timeout(std::size_t milliseconds);
|
||||
|
||||
/// Gets the read timeout of the stream buffer.
|
||||
/**
|
||||
* @returns The timeout, in milliseconds, used for individual read operations
|
||||
* on the underlying transport, when downloading the URL's content.
|
||||
*/
|
||||
URDL_DECL std::size_t read_timeout() const;
|
||||
|
||||
/// Sets the read timeout of the stream buffer.
|
||||
/**
|
||||
* @param milliseconds The timeout, in milliseconds, to be used for individual
|
||||
* read operations on the underlying transport, when downloading the URL's
|
||||
* content.
|
||||
*/
|
||||
URDL_DECL void read_timeout(std::size_t milliseconds);
|
||||
|
||||
/// Gets the MIME type of the content obtained from the URL.
|
||||
/**
|
||||
* @returns A string specifying the MIME type. Examples of possible return
|
||||
* values include @c text/plain, @c text/html and @c image/png.
|
||||
*
|
||||
* @par Remarks
|
||||
* Not all URL protocols support a content type. For these protocols, this
|
||||
* function returns an empty string.
|
||||
*/
|
||||
URDL_DECL std::string content_type() const;
|
||||
|
||||
/// Gets the length of the content obtained from the URL.
|
||||
/**
|
||||
* @returns The length, in bytes, of the content. If the content associated
|
||||
* with the URL does not specify a length,
|
||||
* @c std::numeric_limits<std::size_t>::max().
|
||||
*/
|
||||
URDL_DECL std::size_t content_length() const;
|
||||
|
||||
/// Gets the protocol-specific headers obtained from the URL.
|
||||
/**
|
||||
* @returns A string containing the headers returned with the content from the
|
||||
* URL. The format and interpretation of these headers is specific to the
|
||||
* protocol associated with the URL.
|
||||
*/
|
||||
URDL_DECL std::string headers() const;
|
||||
|
||||
protected:
|
||||
/// Overrides @c std::streambuf behaviour.
|
||||
/**
|
||||
* par Remarks
|
||||
* Behaves according to the specification of @c std::streambuf::underflow().
|
||||
*/
|
||||
URDL_DECL int_type underflow();
|
||||
|
||||
/// Gets the last error associated with the stream.
|
||||
/**
|
||||
* @returns An @c error_code corresponding to the last error from the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Returns a reference to an @c error_code object representing the last
|
||||
* failure reported by an @c istreambuf function. The set of possible
|
||||
* @c error_code values and categories depends on the protocol of the URL
|
||||
* used to open the stream buffer.
|
||||
*/
|
||||
URDL_DECL virtual const boost::system::error_code& error() const;
|
||||
|
||||
private:
|
||||
URDL_DECL void init_buffers();
|
||||
|
||||
struct body;
|
||||
body* body_;
|
||||
};
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# include "urdl/impl/istreambuf.ipp"
|
||||
#endif
|
||||
|
||||
#endif // URDL_ISTREAMBUF_HPP
|
@ -1,151 +0,0 @@
|
||||
//
|
||||
// option_set.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// path LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_OPTION_SET_HPP
|
||||
#define URDL_OPTION_SET_HPP
|
||||
|
||||
#include <typeinfo>
|
||||
#include "urdl/detail/config.hpp"
|
||||
#include "urdl/detail/scoped_ptr.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
/// The class @c option_set maintains a collection of options.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Options are uniquely identified by type, so the @c option_set class is a
|
||||
* collection of objects of differing types, indexed by type.
|
||||
*
|
||||
* The option types stored in the set must meet the type requirements for
|
||||
* CopyConstructible.
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/option_set.hpp> @n
|
||||
* @e Namespace: @c urdl
|
||||
*/
|
||||
class option_set
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c option_set.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Creates an empty set. Any option queried using the @c get_option member
|
||||
* function will return the default value of the option.
|
||||
*/
|
||||
URDL_DECL option_set();
|
||||
|
||||
/// Constructs an object of class @c option_set.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Creates an identical copy of another set. Any option queried using the
|
||||
* @c get_option member function will return the same value for both sets.
|
||||
*/
|
||||
URDL_DECL option_set(const option_set& other);
|
||||
|
||||
/// Destroys an object of class @c option_set.
|
||||
URDL_DECL ~option_set();
|
||||
|
||||
/// Assignment operator.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Creates an identical copy of another set. Any option queried using the
|
||||
* @c get_option member function will return the same value for both sets.
|
||||
*/
|
||||
URDL_DECL option_set& operator=(const option_set& other);
|
||||
|
||||
/// Sets the value of an option in the set.
|
||||
/**
|
||||
* @param o The option to be set.
|
||||
*
|
||||
* @par Remarks
|
||||
* If the type @c Option is already present in the set, first removes that
|
||||
* element. Adds the option to the set.
|
||||
*/
|
||||
template <typename Option>
|
||||
void set_option(const Option& o)
|
||||
{
|
||||
set_option_wrapper_base(new option_wrapper<Option>(o));
|
||||
}
|
||||
|
||||
/// Sets multiple options in a set from another set.
|
||||
/**
|
||||
* @param other An option set containing all options to be set in the target.
|
||||
*
|
||||
* @par Remarks
|
||||
* Performs a deep copy of all option values from the object @c other into
|
||||
* the target set.
|
||||
*/
|
||||
URDL_DECL void set_options(const option_set& other);
|
||||
|
||||
/// Gets an option from the set.
|
||||
/**
|
||||
* @returns If the option is present in the set, an object containing the
|
||||
* value of the option. Otherwise, returns a default-constructed option.
|
||||
*/
|
||||
template <typename Option>
|
||||
Option get_option() const
|
||||
{
|
||||
if (option_wrapper_base* o
|
||||
= get_option_wrapper_base(typeid(option_wrapper<Option>)))
|
||||
return static_cast<option_wrapper<Option>*>(o)->value;
|
||||
return Option();
|
||||
}
|
||||
|
||||
/// Removes an option from the set.
|
||||
/**
|
||||
* @par Remarks
|
||||
* If the option is queried using the @c get_option member function, it will
|
||||
* return the default value of the option.
|
||||
*/
|
||||
template <typename Option>
|
||||
void clear_option()
|
||||
{
|
||||
clear_option_wrapper_base(typeid(option_wrapper<Option>));
|
||||
}
|
||||
|
||||
private:
|
||||
struct option_wrapper_base
|
||||
{
|
||||
virtual ~option_wrapper_base() {}
|
||||
virtual const std::type_info& type_info() const = 0;
|
||||
virtual option_wrapper_base* clone() const = 0;
|
||||
detail::scoped_ptr<option_wrapper_base> next;
|
||||
};
|
||||
|
||||
template <typename Option>
|
||||
struct option_wrapper : option_wrapper_base
|
||||
{
|
||||
option_wrapper(const Option& o) : value(o) {}
|
||||
const std::type_info& type_info() const
|
||||
{ return typeid(option_wrapper<Option>); }
|
||||
option_wrapper_base* clone() const
|
||||
{ return new option_wrapper<Option>(value); }
|
||||
Option value;
|
||||
};
|
||||
|
||||
URDL_DECL void set_option_wrapper_base(option_wrapper_base* o);
|
||||
URDL_DECL option_wrapper_base* get_option_wrapper_base(
|
||||
const std::type_info& ti) const;
|
||||
URDL_DECL void clear_option_wrapper_base(const std::type_info& ti);
|
||||
|
||||
detail::scoped_ptr<option_wrapper_base> head_;
|
||||
};
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# include "urdl/impl/option_set.ipp"
|
||||
#endif
|
||||
|
||||
#endif // URDL_OPTION_SET_HPP
|
@ -1,807 +0,0 @@
|
||||
//
|
||||
// read_stream.hpp
|
||||
// ~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_READ_STREAM_HPP
|
||||
#define URDL_READ_STREAM_HPP
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "urdl/http.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "urdl/url.hpp"
|
||||
#include "urdl/detail/coroutine.hpp"
|
||||
#include "urdl/detail/file_read_stream.hpp"
|
||||
#include "urdl/detail/http_read_stream.hpp"
|
||||
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
# include <boost/asio/ssl.hpp>
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
/// The class @c read_stream supports reading content from a specified URL
|
||||
/// using synchronous or asynchronous operations.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Currently supported URL protocols are @c http, @c https and @c file.
|
||||
*
|
||||
* The class @c read_stream meets the type requirements for @c SyncReadStream
|
||||
* and @c AsyncReadStream, as defined in the Boost.Asio documentation. This
|
||||
* allows objects of class @c read_stream to be used with the functions
|
||||
* @c boost::asio::read, @c boost::asio::async_read, @c boost::asio::read_until
|
||||
* and @c boost::asio::async_read_until.
|
||||
*
|
||||
* @par Example
|
||||
* To synchronously open the URL, read the content and write it to standard
|
||||
* output:
|
||||
* @code
|
||||
* try
|
||||
* {
|
||||
* boost::asio::io_service io_service;
|
||||
* urdl::read_stream read_stream(io_service);
|
||||
* read_stream.open("http://www.boost.org/LICENSE_1_0.txt");
|
||||
* for (;;)
|
||||
* {
|
||||
* char data[1024];
|
||||
* boost::system::error_code ec;
|
||||
* std::size_t length = stream.read_some(boost::asio::buffer(data), ec);
|
||||
* if (ec == boost::asio::error::eof)
|
||||
* break;
|
||||
* if (ec)
|
||||
* throw boost::system::system_error(ec);
|
||||
* os.write(data, length);
|
||||
* }
|
||||
* }
|
||||
* catch (std::exception& e)
|
||||
* {
|
||||
* std::cerr << "Exception: " << e.what() << std::endl;
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* To asynchronously open the URL, read the content and write it to standard
|
||||
* output:
|
||||
* @code
|
||||
* boost::asio::io_service io_service;
|
||||
* urdl::read_stream read_stream(io_service)
|
||||
* char data[1024];
|
||||
* ...
|
||||
* read_stream.async_open("http://www.boost.org/LICENSE_1_0.txt", open_handler);
|
||||
* ...
|
||||
* void open_handler(const boost::system::error_code& ec)
|
||||
* {
|
||||
* if (!ec)
|
||||
* {
|
||||
* read_stream.async_read_some(boost::asio::buffer(data), read_handler);
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
* void read_handler(const boost::system::error_code& ec, std::size_t length)
|
||||
* {
|
||||
* if (!ec)
|
||||
* {
|
||||
* std::cout.write(data, length);
|
||||
* read_stream.async_read_some(boost::asio::buffer(data), read_handler);
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/read_stream.hpp> @n
|
||||
* @e Namespace: @c urdl
|
||||
*/
|
||||
class read_stream
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c read_stream.
|
||||
/**
|
||||
* @param io_service The @c io_service object that the stream will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the stream.
|
||||
*/
|
||||
explicit read_stream(boost::asio::io_service& io_service)
|
||||
: io_service_(io_service),
|
||||
file_(io_service, options_),
|
||||
http_(io_service, options_),
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
ssl_context_(io_service, boost::asio::ssl::context::sslv23),
|
||||
https_(io_service, options_, ssl_context_),
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
protocol_(unknown)
|
||||
{
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::context::verify_peer);
|
||||
SSL_CTX_set_default_verify_paths(ssl_context_.impl());
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
}
|
||||
|
||||
/// Gets the @c io_service associated with the stream.
|
||||
/**
|
||||
* @returns A reference to the @c io_service object that the stream will use
|
||||
* to dispatch handlers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
boost::asio::io_service& get_io_service()
|
||||
{
|
||||
return io_service_;
|
||||
}
|
||||
|
||||
/// Sets an option to control the behaviour of the stream.
|
||||
/**
|
||||
* @param option The option to be set on the stream.
|
||||
*
|
||||
* @par Remarks
|
||||
* Options are uniquely identified by type.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream stream(io_service);
|
||||
* stream.set_option(urdl::http::max_redirects(1));
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Option>
|
||||
void set_option(const Option& option)
|
||||
{
|
||||
options_.set_option(option);
|
||||
}
|
||||
|
||||
/// Sets options to control the behaviour of the stream.
|
||||
/**
|
||||
* @param options The options to be set on the stream. The options in the set
|
||||
* are added on top of any options already set on the stream.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream stream(io_service);
|
||||
* urdl::option_set options;
|
||||
* options.set_option(urdl::http::max_redirects(1));
|
||||
* options.set_option(urdl::ssl::verify_peer(false));
|
||||
* stream.set_options(options);
|
||||
* @endcode
|
||||
*/
|
||||
void set_options(const option_set& options)
|
||||
{
|
||||
options_.set_options(options);
|
||||
}
|
||||
|
||||
/// Gets the current value of an option that controls the behaviour of the
|
||||
/// stream.
|
||||
/**
|
||||
* @returns The current value of the option.
|
||||
*
|
||||
* @par Remarks
|
||||
* Options are uniquely identified by type.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream stream(io_service);
|
||||
* urdl::http::max_redirects option
|
||||
* = stream.get_option<urdl::http::max_redirects>();
|
||||
* std::size_t value = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Option>
|
||||
Option get_option() const
|
||||
{
|
||||
return options_.get_option<Option>();
|
||||
}
|
||||
|
||||
/// Gets the values of all options set on the stream.
|
||||
/**
|
||||
* @returns An option set containing all options from the stream.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream stream(io_service);
|
||||
* ...
|
||||
* urdl::option_set options(stream.get_options());
|
||||
* urdl::http::max_redirects option
|
||||
* = options.get_option<urdl::http::max_redirects>();
|
||||
* std::size_t value = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
option_set get_options() const
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
/// Determines whether the stream is open.
|
||||
/**
|
||||
* @returns @c true if the stream is open, @c false otherwise.
|
||||
*/
|
||||
bool is_open() const
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return file_.is_open();
|
||||
case http:
|
||||
return http_.is_open();
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.is_open();
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens the specified URL.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream read_stream(io_service);
|
||||
*
|
||||
* try
|
||||
* {
|
||||
* read_stream.open("http://www.boost.org");
|
||||
* }
|
||||
* catch (boost::system::error_code& e)
|
||||
* {
|
||||
* std::cerr << e.what() << std::endl;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
void open(const url& u)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (open(u, ec))
|
||||
{
|
||||
boost::system::system_error ex(ec);
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens the specified URL.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns @c ec.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* urdl::read_stream read_stream(io_service);
|
||||
*
|
||||
* boost::system::error_code ec;
|
||||
* read_stream.open("http://www.boost.org", ec);
|
||||
* if (ec)
|
||||
* {
|
||||
* std::cerr << ec.message() << std::endl;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
boost::system::error_code open(const url& u, boost::system::error_code& ec)
|
||||
{
|
||||
url tmp_url = u;
|
||||
std::size_t redirects = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (tmp_url.protocol() == "file")
|
||||
{
|
||||
protocol_ = file;
|
||||
return file_.open(tmp_url, ec);
|
||||
}
|
||||
else if (tmp_url.protocol() == "http")
|
||||
{
|
||||
protocol_ = http;
|
||||
http_.open(tmp_url, ec);
|
||||
if (ec == http::errc::moved_permanently || ec == http::errc::found)
|
||||
{
|
||||
std::size_t max_redirects = options_.get_option<
|
||||
urdl::http::max_redirects>().value();
|
||||
if (redirects < max_redirects)
|
||||
{
|
||||
++redirects;
|
||||
tmp_url = http_.location();
|
||||
http_.close(ec);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
else if (tmp_url.protocol() == "https")
|
||||
{
|
||||
protocol_ = https;
|
||||
https_.open(tmp_url, ec);
|
||||
if (ec == http::errc::moved_permanently || ec == http::errc::found)
|
||||
{
|
||||
std::size_t max_redirects = options_.get_option<
|
||||
urdl::http::max_redirects>().value();
|
||||
if (redirects < max_redirects)
|
||||
{
|
||||
++redirects;
|
||||
tmp_url = https_.location();
|
||||
https_.close(ec);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
else
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Asynchronously opens the specified URL.
|
||||
/**
|
||||
* @param u The URL to open.
|
||||
*
|
||||
* @param handler The handler to be called when the open operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code
|
||||
* void handler(
|
||||
* const boost::system::error_code& ec // Result of operation.
|
||||
* );
|
||||
* @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* @c boost::asio::io_service::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* void open_handler(const boost::system::error_code& ec)
|
||||
* {
|
||||
* if (!ec)
|
||||
* {
|
||||
* // Open succeeded.
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
* urdl::read_stream read_stream(io_service);
|
||||
* read_stream.async_open("http://www.boost.org/", open_handler);
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Handler>
|
||||
URDL_INITFN_RESULT_TYPE(Handler,
|
||||
void (boost::system::error_code))
|
||||
async_open(const url& u, Handler handler)
|
||||
{
|
||||
#if (BOOST_VERSION >= 105400)
|
||||
typedef typename boost::asio::handler_type<Handler,
|
||||
void (boost::system::error_code)>::type real_handler_type;
|
||||
real_handler_type real_handler(handler);
|
||||
boost::asio::async_result<real_handler_type> result(real_handler);
|
||||
#else // (BOOST_VERSION >= 105400)
|
||||
typedef Handler real_handler_type;
|
||||
Handler real_handler(handler);
|
||||
#endif // (BOOST_VERSION >= 105400)
|
||||
|
||||
open_coro<real_handler_type>(this, u, real_handler)(
|
||||
boost::system::error_code());
|
||||
|
||||
#if (BOOST_VERSION >= 105400)
|
||||
return result.get();
|
||||
#endif // (BOOST_VERSION >= 105400)
|
||||
}
|
||||
|
||||
/// Closes the stream.
|
||||
/**
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @par Remarks
|
||||
* Any asynchronous open or read operations will be cancelled, and will
|
||||
* complete with the @c boost::asio::error::operation_aborted error.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (close(ec))
|
||||
{
|
||||
boost::system::system_error ex(ec);
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// Closes the stream.
|
||||
/**
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns @c ec.
|
||||
*
|
||||
* @par Remarks
|
||||
* Any asynchronous open or read operations will be cancelled, and will
|
||||
* complete with the @c boost::asio::error::operation_aborted error.
|
||||
*/
|
||||
boost::system::error_code close(boost::system::error_code& ec)
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return file_.close(ec);
|
||||
case http:
|
||||
return http_.close(ec);
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.close(ec);
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
ec = boost::system::error_code();
|
||||
break;
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
/// Gets the MIME type of the content obtained from the URL.
|
||||
/**
|
||||
* @returns A string specifying the MIME type. Examples of possible return
|
||||
* values include @c text/plain, @c text/html and @c image/png.
|
||||
*
|
||||
* @par Remarks
|
||||
* Not all URL protocols support a content type. For these protocols, this
|
||||
* function returns an empty string.
|
||||
*/
|
||||
std::string content_type() const
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return std::string();
|
||||
case http:
|
||||
return http_.content_type();
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.content_type();
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the length of the content obtained from the URL.
|
||||
/**
|
||||
* @returns The length, in bytes, of the content. If the content associated
|
||||
* with the URL does not specify a length,
|
||||
* @c std::numeric_limits<std::size_t>::max().
|
||||
*/
|
||||
std::size_t content_length() const
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return ~std::size_t(0);
|
||||
case http:
|
||||
return http_.content_length();
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.content_length();
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
return ~std::size_t(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the protocol-specific headers obtained from the URL.
|
||||
/**
|
||||
* @returns A string containing the headers returned with the content from the
|
||||
* URL. The format and interpretation of these headers is specific to the
|
||||
* protocol associated with the URL.
|
||||
*/
|
||||
std::string headers() const
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return std::string();
|
||||
case http:
|
||||
return http_.headers();
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.headers();
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads some data from the stream.
|
||||
/**
|
||||
* @param buffers One or more buffers into which the data will be read. The
|
||||
* type must meet the requirements for @c MutableBufferSequence, as defined in
|
||||
* the Boost.Asio documentation.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown on failure. An error code of
|
||||
* @c boost::asio::error::eof indicates that the end of the URL content has
|
||||
* been reached.
|
||||
*
|
||||
* @par Remarks
|
||||
* The function call will block until one or more bytes of data has been read
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* The @c read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @c boost::asio::read function if you need to
|
||||
* ensure that the requested amount of data is read before the blocking
|
||||
* operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @c boost::asio::buffer function
|
||||
* as follows:
|
||||
* @code
|
||||
* read_stream.read_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the documentation for the @c boost::asio::buffer function for
|
||||
* information on reading into multiple buffers in one go, and how to use it
|
||||
* with arrays, @c boost::array or @c std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::size_t bytes_transferred = read_some(buffers, ec);
|
||||
if (ec)
|
||||
{
|
||||
boost::system::system_error ex(ec);
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
/// Reads some data from the stream.
|
||||
/**
|
||||
* @param buffers One or more buffers into which the data will be read. The
|
||||
* type must meet the requirements for @c MutableBufferSequence, as defined in
|
||||
* the Boost.Asio documentation.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. An error code of
|
||||
* @c boost::asio::error::eof indicates that the end of the URL content has
|
||||
* been reached.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @par Remarks
|
||||
* This function is used to read data from the stream. The function call will
|
||||
* block until one or more bytes of data has been read successfully, or until
|
||||
* an error occurs.
|
||||
*
|
||||
* The @c read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @c boost::asio::read function if you need to
|
||||
* ensure that the requested amount of data is read before the blocking
|
||||
* operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @c boost::asio::buffer function
|
||||
* as follows:
|
||||
* @code
|
||||
* read_stream.read_some(boost::asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the documentation for the @c boost::asio::buffer function for
|
||||
* information on reading into multiple buffers in one go, and how to use it
|
||||
* with arrays, @c boost::array or @c std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
return file_.read_some(buffers, ec);
|
||||
case http:
|
||||
return http_.read_some(buffers, ec);
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
return https_.read_some(buffers, ec);
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Asynchronously reads some data from the stream.
|
||||
/**
|
||||
* @param buffers One or more buffers into which the data will be read. The
|
||||
* type must meet the requirements for @c MutableBufferSequence, as defined in
|
||||
* the Boost.Asio documentation. Although the buffers object may be copied as
|
||||
* necessary, ownership of the underlying memory blocks is retained by the
|
||||
* caller, which must guarantee that they remain valid until the handler is
|
||||
* called.
|
||||
*
|
||||
* @param handler The handler to be called when the read operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code
|
||||
* void handler(
|
||||
* const boost::system::error_code& ec, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* );
|
||||
* @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* @c boost::asio::io_service::post().
|
||||
*
|
||||
* @par Remarks
|
||||
* The asynchronous operation will continue until one or more bytes of data
|
||||
* has been read successfully, or until an error occurs.
|
||||
*
|
||||
* The @c async_read_some operation may not read all of the requested number
|
||||
* of bytes. Consider using the @c boost::asio::async_read function if you
|
||||
* need to ensure that the requested amount of data is read before the
|
||||
* asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @c boost::asio::buffer function
|
||||
* as follows:
|
||||
* @code
|
||||
* read_stream.async_read_some(boost::asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the documentation for the @c boost::asio::buffer function for
|
||||
* information on reading into multiple buffers in one go, and how to use it
|
||||
* with arrays, @c boost::array or @c std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
URDL_INITFN_RESULT_TYPE(Handler,
|
||||
void (boost::system::error_code, std::size_t))
|
||||
async_read_some(const MutableBufferSequence& buffers, Handler handler)
|
||||
{
|
||||
#if (BOOST_VERSION >= 105400)
|
||||
typedef typename boost::asio::handler_type<Handler,
|
||||
void (boost::system::error_code, std::size_t)>::type real_handler_type;
|
||||
real_handler_type real_handler(handler);
|
||||
boost::asio::async_result<real_handler_type> result(real_handler);
|
||||
#else // (BOOST_VERSION >= 105400)
|
||||
Handler real_handler(handler);
|
||||
#endif // (BOOST_VERSION >= 105400)
|
||||
|
||||
switch (protocol_)
|
||||
{
|
||||
case file:
|
||||
file_.async_read_some(buffers, real_handler);
|
||||
break;
|
||||
case http:
|
||||
http_.async_read_some(buffers, real_handler);
|
||||
break;
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
case https:
|
||||
https_.async_read_some(buffers, real_handler);
|
||||
break;
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
default:
|
||||
boost::system::error_code ec
|
||||
= boost::asio::error::operation_not_supported;
|
||||
io_service_.post(boost::asio::detail::bind_handler(real_handler, ec, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
#if (BOOST_VERSION >= 105400)
|
||||
return result.get();
|
||||
#endif // (BOOST_VERSION >= 105400)
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Handler>
|
||||
class open_coro : detail::coroutine
|
||||
{
|
||||
public:
|
||||
open_coro(read_stream* this_ptr, const url& u, Handler handler)
|
||||
: this_(this_ptr),
|
||||
url_(u),
|
||||
handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(boost::system::error_code ec)
|
||||
{
|
||||
URDL_CORO_BEGIN;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (url_.protocol() == "file")
|
||||
{
|
||||
this_->protocol_ = file;
|
||||
URDL_CORO_YIELD(this_->file_.async_open(url_, *this));
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
else if (url_.protocol() == "http")
|
||||
{
|
||||
this_->protocol_ = http;
|
||||
URDL_CORO_YIELD(this_->http_.async_open(url_, *this));
|
||||
if (ec == http::errc::moved_permanently || ec == http::errc::found)
|
||||
{
|
||||
url_ = this_->http_.location();
|
||||
this_->http_.close(ec);
|
||||
continue;
|
||||
}
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
else if (url_.protocol() == "https")
|
||||
{
|
||||
this_->protocol_ = https;
|
||||
URDL_CORO_YIELD(this_->https_.async_open(url_, *this));
|
||||
if (ec == http::errc::moved_permanently || ec == http::errc::found)
|
||||
{
|
||||
url_ = this_->https_.location();
|
||||
this_->https_.close(ec);
|
||||
continue;
|
||||
}
|
||||
handler_(ec);
|
||||
return;
|
||||
}
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
else
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
this_->io_service_.post(
|
||||
boost::asio::detail::bind_handler(handler_, ec));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
URDL_CORO_END;
|
||||
}
|
||||
|
||||
friend void* asio_handler_allocate(std::size_t size,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
friend void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(pointer, size, &this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke(const Function& function,
|
||||
open_coro<Handler>* this_handler)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, &this_handler->handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
read_stream* this_;
|
||||
url url_;
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
template <typename Handler> friend class open_coro;
|
||||
|
||||
boost::asio::io_service& io_service_;
|
||||
option_set options_;
|
||||
detail::file_read_stream file_;
|
||||
detail::http_read_stream<boost::asio::ip::tcp::socket> http_;
|
||||
#if !defined(URDL_DISABLE_SSL)
|
||||
boost::asio::ssl::context ssl_context_;
|
||||
detail::http_read_stream<
|
||||
boost::asio::ssl::stream<
|
||||
boost::asio::ip::tcp::socket> > https_;
|
||||
#endif // !defined(URDL_DISABLE_SSL)
|
||||
enum { unknown, file, http, https } protocol_;
|
||||
};
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#endif // URDL_READ_STREAM_HPP
|
269
thirdparty/urdl-2013-08-15/include/urdl/url.hpp
vendored
269
thirdparty/urdl-2013-08-15/include/urdl/url.hpp
vendored
@ -1,269 +0,0 @@
|
||||
//
|
||||
// url.hpp
|
||||
// ~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// path LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef URDL_URL_HPP
|
||||
#define URDL_URL_HPP
|
||||
|
||||
#include <string>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include "urdl/detail/config.hpp"
|
||||
|
||||
#include "urdl/detail/abi_prefix.hpp"
|
||||
|
||||
namespace urdl {
|
||||
|
||||
/// The class @c url enables parsing and accessing the components of URLs.
|
||||
/**
|
||||
* @par Example
|
||||
* To extract the components of a URL:
|
||||
* @code
|
||||
* urdl::url url("http://user:pass@host:1234/dir/page?param=0#anchor");
|
||||
* std::cout << "Protocol: " << url.protocol() << std::endl;
|
||||
* std::cout << "User Info: " << url.user_info() << std::endl;
|
||||
* std::cout << "Host: " << url.host() << std::endl;
|
||||
* std::cout << "Port: " << url.port() << std::endl;
|
||||
* std::cout << "Path: " << url.path() << std::endl;
|
||||
* std::cout << "Query: " << url.query() << std::endl;
|
||||
* std::cout << "Fragment: " << url.fragment() << std::endl;
|
||||
* @endcode
|
||||
* The above code will print:
|
||||
* @code
|
||||
* Protocol: http
|
||||
* User Info: user:pass
|
||||
* Host: host
|
||||
* Port: 1234
|
||||
* Path: /dir/page
|
||||
* Query: param=0
|
||||
* Fragment: anchor
|
||||
* @endcode
|
||||
*
|
||||
* @par Requirements
|
||||
* @e Header: @c <urdl/url.hpp> @n
|
||||
* @e Namespace: @c urdl
|
||||
*/
|
||||
class url
|
||||
{
|
||||
public:
|
||||
/// Constructs an object of class @c url.
|
||||
/**
|
||||
* @par Remarks
|
||||
* Postconditions: @c protocol(), @c user_info(), @c host(), @c path(),
|
||||
* @c query(), @c fragment() all return an empty string, and @c port() returns
|
||||
* 0.
|
||||
*/
|
||||
url()
|
||||
: ipv6_host_(false)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown when the URL string is invalid.
|
||||
*/
|
||||
url(const char* s)
|
||||
: ipv6_host_(false)
|
||||
{
|
||||
*this = from_string(s);
|
||||
}
|
||||
|
||||
/// Constructs an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown when the URL string is invalid.
|
||||
*/
|
||||
url(const std::string& s)
|
||||
: ipv6_host_(false)
|
||||
{
|
||||
*this = from_string(s);
|
||||
}
|
||||
|
||||
/// Gets the protocol component of the URL.
|
||||
/**
|
||||
* @returns A string specifying the protocol of the URL. Examples include
|
||||
* @c http, @c https or @c file.
|
||||
*/
|
||||
std::string protocol() const
|
||||
{
|
||||
return protocol_;
|
||||
}
|
||||
|
||||
/// Gets the user info component of the URL.
|
||||
/**
|
||||
* @returns A string containing the user info of the URL. Typically in the
|
||||
* format <tt>user:password</tt>, but depends on the protocol.
|
||||
*/
|
||||
std::string user_info() const
|
||||
{
|
||||
return user_info_;
|
||||
}
|
||||
|
||||
/// Gets the host component of the URL.
|
||||
/**
|
||||
* @returns A string containing the host name of the URL.
|
||||
*/
|
||||
std::string host() const
|
||||
{
|
||||
return host_;
|
||||
}
|
||||
|
||||
/// Gets the port component of the URL.
|
||||
/**
|
||||
* @returns The port number of the URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* If the URL string did not specify a port, and the protocol is one of @c
|
||||
* http, @c https or @c ftp, an appropriate default port number is returned.
|
||||
*/
|
||||
URDL_DECL unsigned short port() const;
|
||||
|
||||
/// Gets the path component of the URL.
|
||||
/**
|
||||
* @returns A string containing the path of the URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* The path string is unescaped. To obtain the path in escaped form, use
|
||||
* @c to_string(url::path_component).
|
||||
*/
|
||||
URDL_DECL std::string path() const;
|
||||
|
||||
/// Gets the query component of the URL.
|
||||
/**
|
||||
* @returns A string containing the query string of the URL.
|
||||
*
|
||||
* @par Remarks
|
||||
* The query string is not unescaped, but is returned in whatever form it
|
||||
* takes in the original URL string.
|
||||
*/
|
||||
std::string query() const
|
||||
{
|
||||
return query_;
|
||||
}
|
||||
|
||||
/// Gets the fragment component of the URL.
|
||||
/**
|
||||
* @returns A string containing the fragment of the URL.
|
||||
*/
|
||||
std::string fragment() const
|
||||
{
|
||||
return fragment_;
|
||||
}
|
||||
|
||||
/// Components of the URL, used with @c from_string.
|
||||
enum components_type
|
||||
{
|
||||
protocol_component = 1,
|
||||
user_info_component = 2,
|
||||
host_component = 4,
|
||||
port_component = 8,
|
||||
path_component = 16,
|
||||
query_component = 32,
|
||||
fragment_component = 64,
|
||||
all_components = protocol_component | user_info_component | host_component
|
||||
| port_component | path_component | query_component | fragment_component
|
||||
};
|
||||
|
||||
/// Converts an object of class @c url to a string representation.
|
||||
/**
|
||||
* @param components A bitmask specifying which components of the URL should
|
||||
* be included in the string. See the @c url::components_type enumeration for
|
||||
* possible values.
|
||||
*
|
||||
* @returns A string representation of the URL.
|
||||
*
|
||||
* @par Examples
|
||||
* To convert the entire URL to a string:
|
||||
* @code
|
||||
* std::string s = url.to_string();
|
||||
* @endcode
|
||||
* To convert only the host and port number into a string:
|
||||
* @code
|
||||
* std::string s = url.to_string(
|
||||
* urdl::url::host_component
|
||||
* | urdl::url::port_component);
|
||||
* @endcode
|
||||
*/
|
||||
URDL_DECL std::string to_string(int components = all_components) const;
|
||||
|
||||
/// Converts a string representation of a URL into an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @returns A @c url object corresponding to the specified string.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown when the URL string is invalid.
|
||||
*/
|
||||
URDL_DECL static url from_string(const char* s);
|
||||
|
||||
/// Converts a string representation of a URL into an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @param ec Error code set to indicate the reason for failure, if any.
|
||||
*
|
||||
* @returns A @c url object corresponding to the specified string.
|
||||
*/
|
||||
URDL_DECL static url from_string(const char* s,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
/// Converts a string representation of a URL into an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @returns A @c url object corresponding to the specified string.
|
||||
*
|
||||
* @throws boost::system::system_error Thrown when the URL string is invalid.
|
||||
*/
|
||||
URDL_DECL static url from_string(const std::string& s);
|
||||
|
||||
/// Converts a string representation of a URL into an object of class @c url.
|
||||
/**
|
||||
* @param s URL string to be parsed into its components.
|
||||
*
|
||||
* @param ec Error code set to indicate the reason for failure, if any.
|
||||
*
|
||||
* @returns A @c url object corresponding to the specified string.
|
||||
*/
|
||||
URDL_DECL static url from_string(const std::string& s,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
/// Compares two @c url objects for equality.
|
||||
friend URDL_DECL bool operator==(const url& a, const url& b);
|
||||
|
||||
/// Compares two @c url objects for inequality.
|
||||
friend URDL_DECL bool operator!=(const url& a, const url& b);
|
||||
|
||||
/// Compares two @c url objects for ordering.
|
||||
friend URDL_DECL bool operator<(const url& a, const url& b);
|
||||
|
||||
private:
|
||||
URDL_DECL static bool unescape_path(const std::string& in, std::string& out);
|
||||
|
||||
std::string protocol_;
|
||||
std::string user_info_;
|
||||
std::string host_;
|
||||
std::string port_;
|
||||
std::string path_;
|
||||
std::string query_;
|
||||
std::string fragment_;
|
||||
bool ipv6_host_;
|
||||
};
|
||||
|
||||
} // namespace urdl
|
||||
|
||||
#include "urdl/detail/abi_suffix.hpp"
|
||||
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# include "urdl/impl/url.ipp"
|
||||
#endif
|
||||
|
||||
#endif // URDL_URL_HPP
|
17
thirdparty/urdl-2013-08-15/src/urdl.cpp
vendored
17
thirdparty/urdl-2013-08-15/src/urdl.cpp
vendored
@ -1,17 +0,0 @@
|
||||
#if defined(URDL_HEADER_ONLY)
|
||||
# error Do not compile Urdl library source with URDL_HEADER_ONLY defined
|
||||
#endif
|
||||
|
||||
#define URDL_SOURCE
|
||||
|
||||
#include "urdl/istreambuf.hpp"
|
||||
#include "urdl/impl/istreambuf.ipp"
|
||||
|
||||
#include "urdl/http.hpp"
|
||||
#include "urdl/impl/http.ipp"
|
||||
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "urdl/impl/option_set.ipp"
|
||||
|
||||
#include "urdl/url.hpp"
|
||||
#include "urdl/impl/url.ipp"
|
27
thirdparty/urdl-2013-08-15/test/Jamfile
vendored
27
thirdparty/urdl-2013-08-15/test/Jamfile
vendored
@ -1,27 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
project
|
||||
:
|
||||
requirements
|
||||
<library>../build//urdl
|
||||
<library>/boost/thread//boost_thread
|
||||
:
|
||||
default-build
|
||||
debug
|
||||
<threading>multi
|
||||
<link>shared
|
||||
<runtime-link>shared
|
||||
;
|
||||
|
||||
test-suite "urdl" :
|
||||
[ run istream.cpp ]
|
||||
[ run istreambuf.cpp ]
|
||||
[ run option_set.cpp ]
|
||||
[ run read_stream.cpp ]
|
||||
[ run url.cpp ]
|
||||
;
|
118
thirdparty/urdl-2013-08-15/test/http_server.hpp
vendored
118
thirdparty/urdl-2013-08-15/test/http_server.hpp
vendored
@ -1,118 +0,0 @@
|
||||
//
|
||||
// http_server.hpp
|
||||
// ~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef HTTP_SERVER_HPP
|
||||
#define HTTP_SERVER_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/read_until.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
// Helper class to test HTTP client functionality.
|
||||
class http_server
|
||||
{
|
||||
public:
|
||||
typedef boost::asio::ip::tcp tcp;
|
||||
|
||||
http_server()
|
||||
: acceptor_(io_service_, tcp::endpoint(
|
||||
boost::asio::ip::address_v4::loopback(), 0)),
|
||||
socket_(io_service_),
|
||||
response_delay_(0),
|
||||
content_delay_(0),
|
||||
success_(false)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned short port() const
|
||||
{
|
||||
return acceptor_.local_endpoint().port();
|
||||
}
|
||||
|
||||
void start(const std::string& expected_request,
|
||||
std::size_t response_delay, const std::string& response,
|
||||
std::size_t content_delay, const std::string& content)
|
||||
{
|
||||
success_ = false;
|
||||
expected_request_ = expected_request;
|
||||
response_delay_ = response_delay;
|
||||
response_ = response;
|
||||
content_delay_ = content_delay;
|
||||
content_ = content;
|
||||
thread_.reset(new boost::thread(boost::bind(&http_server::worker, this)));
|
||||
}
|
||||
|
||||
bool stop()
|
||||
{
|
||||
thread_->join();
|
||||
thread_.reset();
|
||||
return success_;
|
||||
}
|
||||
|
||||
private:
|
||||
void worker()
|
||||
{
|
||||
try
|
||||
{
|
||||
acceptor_.accept(socket_);
|
||||
|
||||
// Wait for request.
|
||||
boost::asio::streambuf buffer;
|
||||
std::size_t size = boost::asio::read_until(socket_, buffer, "\r\n\r\n");
|
||||
std::string request(size, 0);
|
||||
buffer.sgetn(&request[0], size);
|
||||
success_ = (request == expected_request_);
|
||||
|
||||
// Introduce a delay before sending the response.
|
||||
boost::asio::deadline_timer timer(io_service_);
|
||||
timer.expires_from_now(boost::posix_time::milliseconds(response_delay_));
|
||||
timer.wait();
|
||||
|
||||
// Send response headers.
|
||||
boost::system::error_code ec;
|
||||
boost::asio::write(socket_, boost::asio::buffer(response_));
|
||||
|
||||
// Introduce a delay before sending the content.
|
||||
timer.expires_from_now(boost::posix_time::milliseconds(content_delay_));
|
||||
timer.wait();
|
||||
|
||||
// Now we can write the content.
|
||||
boost::asio::write(socket_, boost::asio::buffer(content_));
|
||||
|
||||
// We're done. Shut down the connection.
|
||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||
socket_.close(ec);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::io_service io_service_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::string expected_request_;
|
||||
std::size_t response_delay_;
|
||||
std::string response_;
|
||||
std::size_t content_delay_;
|
||||
std::string content_;
|
||||
boost::scoped_ptr<boost::thread> thread_;
|
||||
bool success_;
|
||||
};
|
||||
|
||||
#endif // HTTP_SERVER_HPP
|
215
thirdparty/urdl-2013-08-15/test/istream.cpp
vendored
215
thirdparty/urdl-2013-08-15/test/istream.cpp
vendored
@ -1,215 +0,0 @@
|
||||
//
|
||||
// istream.cpp
|
||||
// ~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "urdl/istream.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
#include "urdl/http.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "http_server.hpp"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
// Ensure all functions compile correctly.
|
||||
void istream_compile_test()
|
||||
{
|
||||
// Constructors
|
||||
|
||||
urdl::istream istream1;
|
||||
urdl::istream istream2("file://foobar");
|
||||
urdl::istream istream3(urdl::url("file://foobar"));
|
||||
urdl::istream istream4("file://foobar", urdl::option_set());
|
||||
urdl::istream istream5(urdl::url("file://foobar"), urdl::option_set());
|
||||
|
||||
// set_option()
|
||||
|
||||
istream1.set_option(0);
|
||||
istream1.set_option<char>(0);
|
||||
|
||||
// set_options()
|
||||
|
||||
istream1.set_options(urdl::option_set());
|
||||
|
||||
// get_option()
|
||||
|
||||
const urdl::istream& const_istream1 = istream1;
|
||||
want<int>(const_istream1.get_option<int>());
|
||||
want<char>(const_istream1.get_option<char>());
|
||||
|
||||
// get_options()
|
||||
|
||||
want<urdl::option_set>(const_istream1.get_options());
|
||||
|
||||
// is_open()
|
||||
|
||||
want<bool>(const_istream1.is_open());
|
||||
|
||||
// open()
|
||||
|
||||
istream1.open("file://foobar");
|
||||
istream1.open(urdl::url("file://foobar"));
|
||||
|
||||
// close()
|
||||
|
||||
istream1.close();
|
||||
|
||||
// rdbuf()
|
||||
|
||||
want<urdl::istreambuf*>(const_istream1.rdbuf());
|
||||
|
||||
// error()
|
||||
|
||||
want<boost::system::error_code>(const_istream1.error());
|
||||
|
||||
// read_timeout()
|
||||
|
||||
want<std::size_t>(const_istream1.read_timeout());
|
||||
istream1.read_timeout(std::size_t(123));
|
||||
|
||||
// content_type()
|
||||
|
||||
want<std::string>(const_istream1.content_type());
|
||||
|
||||
// content_length()
|
||||
|
||||
want<std::size_t>(const_istream1.content_length());
|
||||
|
||||
// headers()
|
||||
|
||||
want<std::string>(const_istream1.headers());
|
||||
}
|
||||
|
||||
// Test HTTP.
|
||||
void istream_http_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 13\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Hello, World!";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
urdl::istream istream1("http://localhost:" + port + "/");
|
||||
std::string returned_content;
|
||||
std::getline(istream1, returned_content);
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(istream1.content_type() == "text/plain");
|
||||
BOOST_CHECK(istream1.content_length() == 13);
|
||||
BOOST_CHECK(returned_content == content);
|
||||
}
|
||||
|
||||
// Test HTTP with an error status returned by the server.
|
||||
void istream_http_not_found_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 404 Not Found\r\n"
|
||||
"Content-Length: 9\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Not Found";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
urdl::istream istream1("http://localhost:" + port + "/");
|
||||
std::string returned_content;
|
||||
std::getline(istream1, returned_content);
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(istream1.error() == urdl::http::errc::not_found);
|
||||
}
|
||||
|
||||
// Test HTTP with an open timeout.
|
||||
void istream_http_open_timeout_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 13\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Hello, World!";
|
||||
|
||||
server.start(request, 1500, response, 0, content);
|
||||
urdl::istream istream1;
|
||||
istream1.open_timeout(1000);
|
||||
istream1.open("http://localhost:" + port + "/");
|
||||
server.stop();
|
||||
|
||||
BOOST_CHECK(istream1.error() == boost::system::errc::timed_out);
|
||||
}
|
||||
|
||||
// Test HTTP with a read timeout.
|
||||
void istream_http_read_timeout_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 13\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Hello, World!";
|
||||
|
||||
server.start(request, 0, response, 1500, content);
|
||||
urdl::istream istream1;
|
||||
istream1.open("http://localhost:" + port + "/");
|
||||
istream1.read_timeout(1000);
|
||||
std::string returned_content;
|
||||
std::getline(istream1, returned_content);
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(istream1.error() == boost::system::errc::timed_out);
|
||||
}
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("istream");
|
||||
test->add(BOOST_TEST_CASE(&istream_compile_test));
|
||||
test->add(BOOST_TEST_CASE(&istream_http_test));
|
||||
test->add(BOOST_TEST_CASE(&istream_http_not_found_test));
|
||||
test->add(BOOST_TEST_CASE(&istream_http_open_timeout_test));
|
||||
test->add(BOOST_TEST_CASE(&istream_http_read_timeout_test));
|
||||
return test;
|
||||
}
|
88
thirdparty/urdl-2013-08-15/test/istreambuf.cpp
vendored
88
thirdparty/urdl-2013-08-15/test/istreambuf.cpp
vendored
@ -1,88 +0,0 @@
|
||||
//
|
||||
// istreambuf.cpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "urdl/istreambuf.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
|
||||
// Ensure all functions compile correctly.
|
||||
void istreambuf_compile_test()
|
||||
{
|
||||
// Constructors
|
||||
|
||||
urdl::istreambuf istreambuf1;
|
||||
|
||||
// set_option()
|
||||
|
||||
istreambuf1.set_option(0);
|
||||
istreambuf1.set_option<char>(0);
|
||||
|
||||
// set_options()
|
||||
|
||||
istreambuf1.set_options(urdl::option_set());
|
||||
|
||||
// get_option()
|
||||
|
||||
const urdl::istreambuf& const_istreambuf1 = istreambuf1;
|
||||
want<int>(const_istreambuf1.get_option<int>());
|
||||
want<char>(const_istreambuf1.get_option<char>());
|
||||
|
||||
// get_options()
|
||||
|
||||
want<urdl::option_set>(const_istreambuf1.get_options());
|
||||
|
||||
// is_open()
|
||||
|
||||
want<bool>(const_istreambuf1.is_open());
|
||||
|
||||
// open()
|
||||
|
||||
want<urdl::istreambuf*>(istreambuf1.open("file://foobar"));
|
||||
want<urdl::istreambuf*>(istreambuf1.open(urdl::url("file://foobar")));
|
||||
|
||||
// close()
|
||||
|
||||
want<urdl::istreambuf*>(istreambuf1.close());
|
||||
|
||||
// puberror()
|
||||
|
||||
want<boost::system::error_code>(const_istreambuf1.puberror());
|
||||
|
||||
// read_timeout()
|
||||
|
||||
want<std::size_t>(const_istreambuf1.read_timeout());
|
||||
istreambuf1.read_timeout(std::size_t(123));
|
||||
|
||||
// content_type()
|
||||
|
||||
want<std::string>(const_istreambuf1.content_type());
|
||||
|
||||
// content_length()
|
||||
|
||||
want<std::size_t>(const_istreambuf1.content_length());
|
||||
|
||||
// headers()
|
||||
|
||||
want<std::string>(const_istreambuf1.headers());
|
||||
}
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("istreambuf");
|
||||
test->add(BOOST_TEST_CASE(&istreambuf_compile_test));
|
||||
return test;
|
||||
}
|
99
thirdparty/urdl-2013-08-15/test/option_set.cpp
vendored
99
thirdparty/urdl-2013-08-15/test/option_set.cpp
vendored
@ -1,99 +0,0 @@
|
||||
//
|
||||
// option_set.cpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "urdl/option_set.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
|
||||
// Ensure all functions compile correctly.
|
||||
void option_set_compile_test()
|
||||
{
|
||||
// Constructors
|
||||
|
||||
urdl::option_set set1;
|
||||
urdl::option_set set2(set1);
|
||||
|
||||
// operator=
|
||||
|
||||
set1 = set2;
|
||||
|
||||
// set_option()
|
||||
|
||||
set1.set_option(0);
|
||||
set1.set_option<char>(0);
|
||||
|
||||
// set_options()
|
||||
|
||||
const urdl::option_set& const_set1 = set1;
|
||||
set2.set_options(const_set1);
|
||||
|
||||
// get_option()
|
||||
|
||||
want<int>(const_set1.get_option<int>());
|
||||
want<char>(const_set1.get_option<char>());
|
||||
|
||||
// clear_option()
|
||||
|
||||
set1.clear_option<int>();
|
||||
set1.clear_option<char>();
|
||||
}
|
||||
|
||||
// Test option_set runtime behaviour.
|
||||
void option_set_runtime_test()
|
||||
{
|
||||
urdl::option_set set1;
|
||||
set1.set_option(std::string("foobar"));
|
||||
set1.set_option(int(123));
|
||||
|
||||
urdl::option_set set2(set1);
|
||||
BOOST_CHECK(set2.get_option<std::string>() == set1.get_option<std::string>());
|
||||
BOOST_CHECK(set2.get_option<int>() == set1.get_option<int>());
|
||||
|
||||
urdl::option_set set3;
|
||||
set3 = set2;
|
||||
BOOST_CHECK(set3.get_option<std::string>() == set1.get_option<std::string>());
|
||||
BOOST_CHECK(set3.get_option<int>() == set1.get_option<int>());
|
||||
|
||||
urdl::option_set set4;
|
||||
set4.set_option(char('A'));
|
||||
set4.set_options(set3);
|
||||
BOOST_CHECK(set4.get_option<char>() == 'A');
|
||||
BOOST_CHECK(set4.get_option<std::string>() == set1.get_option<std::string>());
|
||||
BOOST_CHECK(set4.get_option<int>() == set1.get_option<int>());
|
||||
|
||||
set4.clear_option<std::string>();
|
||||
BOOST_CHECK(set4.get_option<char>() == 'A');
|
||||
BOOST_CHECK(set4.get_option<std::string>() == "");
|
||||
BOOST_CHECK(set4.get_option<int>() == set1.get_option<int>());
|
||||
|
||||
set4.set_option(int(321));
|
||||
BOOST_CHECK(set4.get_option<char>() == 'A');
|
||||
BOOST_CHECK(set4.get_option<std::string>() == "");
|
||||
BOOST_CHECK(set4.get_option<int>() == 321);
|
||||
|
||||
set4.set_options(set1);
|
||||
BOOST_CHECK(set4.get_option<char>() == 'A');
|
||||
BOOST_CHECK(set4.get_option<std::string>() == set1.get_option<std::string>());
|
||||
BOOST_CHECK(set4.get_option<int>() == set1.get_option<int>());
|
||||
}
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("option_set");
|
||||
test->add(BOOST_TEST_CASE(&option_set_compile_test));
|
||||
test->add(BOOST_TEST_CASE(&option_set_runtime_test));
|
||||
return test;
|
||||
}
|
280
thirdparty/urdl-2013-08-15/test/read_stream.cpp
vendored
280
thirdparty/urdl-2013-08-15/test/read_stream.cpp
vendored
@ -1,280 +0,0 @@
|
||||
//
|
||||
// read_stream.cpp
|
||||
// ~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "urdl/read_stream.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
#include "urdl/option_set.hpp"
|
||||
#include "http_server.hpp"
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
|
||||
void open_handler(const boost::system::error_code&) {}
|
||||
void read_handler(const boost::system::error_code&, std::size_t) {}
|
||||
|
||||
// Ensure all functions compile correctly.
|
||||
void read_stream_compile_test()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::asio::io_service io_service;
|
||||
boost::system::error_code ec;
|
||||
char buffer[1024];
|
||||
|
||||
// Constructors
|
||||
|
||||
urdl::read_stream stream1(io_service);
|
||||
|
||||
// get_io_service()
|
||||
|
||||
want<boost::asio::io_service>(stream1.get_io_service());
|
||||
|
||||
// set_option()
|
||||
|
||||
stream1.set_option(0);
|
||||
stream1.set_option<char>(0);
|
||||
|
||||
// set_options()
|
||||
|
||||
stream1.set_options(urdl::option_set());
|
||||
|
||||
// get_option()
|
||||
|
||||
const urdl::read_stream& const_stream1 = stream1;
|
||||
want<int>(const_stream1.get_option<int>());
|
||||
want<char>(const_stream1.get_option<char>());
|
||||
|
||||
// get_options()
|
||||
|
||||
want<urdl::option_set>(const_stream1.get_options());
|
||||
|
||||
// is_open()
|
||||
|
||||
want<bool>(const_stream1.is_open());
|
||||
|
||||
// open()
|
||||
|
||||
stream1.open("file://xyz");
|
||||
stream1.open(urdl::url("file://xyz"));
|
||||
want<boost::system::error_code>(stream1.open("file://xyz", ec));
|
||||
want<boost::system::error_code>(stream1.open(urdl::url("file://xyz"), ec));
|
||||
|
||||
// async_open()
|
||||
|
||||
stream1.async_open("file://xyz", open_handler);
|
||||
stream1.async_open(urdl::url("file://xyz"), open_handler);
|
||||
|
||||
// close()
|
||||
|
||||
stream1.close();
|
||||
want<boost::system::error_code>(stream1.close(ec));
|
||||
|
||||
// content_type()
|
||||
|
||||
want<std::string>(const_stream1.content_type());
|
||||
|
||||
// content_length()
|
||||
|
||||
want<std::size_t>(const_stream1.content_length());
|
||||
|
||||
// headers()
|
||||
|
||||
want<std::string>(const_stream1.headers());
|
||||
|
||||
// read_some()
|
||||
|
||||
want<std::size_t>(stream1.read_some(boost::asio::buffer(buffer)));
|
||||
want<std::size_t>(stream1.read_some(boost::asio::buffer(buffer), ec));
|
||||
|
||||
// async_read_some()
|
||||
|
||||
stream1.async_read_some(boost::asio::buffer(buffer), read_handler);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// Test synchronous HTTP.
|
||||
void read_stream_synchronous_http_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 13\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Hello, World!";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
urdl::read_stream stream1(io_service);
|
||||
|
||||
stream1.open("http://localhost:" + port + "/");
|
||||
|
||||
std::string returned_content(stream1.content_length(), 0);
|
||||
boost::asio::read(stream1, boost::asio::buffer(
|
||||
&returned_content[0], returned_content.size()));
|
||||
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(stream1.content_type() == "text/plain");
|
||||
BOOST_CHECK(stream1.content_length() == 13);
|
||||
BOOST_CHECK(returned_content == content);
|
||||
}
|
||||
|
||||
// Test synchronous HTTP with an error status returned by the server.
|
||||
void read_stream_synchronous_http_not_found_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 404 Not Found\r\n"
|
||||
"Content-Length: 9\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Not Found";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
urdl::read_stream stream1(io_service);
|
||||
|
||||
boost::system::error_code ec;
|
||||
stream1.open("http://localhost:" + port + "/", ec);
|
||||
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(ec == urdl::http::errc::not_found);
|
||||
}
|
||||
|
||||
struct handler
|
||||
{
|
||||
boost::system::error_code& ec_;
|
||||
std::size_t& size_;
|
||||
void operator()(const boost::system::error_code& ec, std::size_t size = 0)
|
||||
{
|
||||
ec_ = ec;
|
||||
size_ = size;
|
||||
}
|
||||
};
|
||||
|
||||
// Test asynchronous HTTP.
|
||||
void read_stream_asynchronous_http_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 13\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Hello, World!";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
urdl::read_stream stream1(io_service);
|
||||
|
||||
boost::system::error_code ec;
|
||||
std::size_t bytes_transferred = 0;
|
||||
handler h = { ec, bytes_transferred };
|
||||
|
||||
stream1.async_open("http://localhost:" + port + "/", h);
|
||||
io_service.run();
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
std::string returned_content(stream1.content_length(), 0);
|
||||
boost::asio::async_read(stream1, boost::asio::buffer(
|
||||
&returned_content[0], returned_content.size()), h);
|
||||
io_service.reset();
|
||||
io_service.run();
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(bytes_transferred == returned_content.size());
|
||||
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(stream1.content_type() == "text/plain");
|
||||
BOOST_CHECK(stream1.content_length() == 13);
|
||||
BOOST_CHECK(returned_content == content);
|
||||
}
|
||||
|
||||
// Test asynchronous HTTP with an error status returned by the server.
|
||||
void read_stream_asynchronous_http_not_found_test()
|
||||
{
|
||||
http_server server;
|
||||
std::string port = boost::lexical_cast<std::string>(server.port());
|
||||
|
||||
std::string request =
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"Host: localhost:" + port + "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n";
|
||||
std::string response =
|
||||
"HTTP/1.0 404 Not Found\r\n"
|
||||
"Content-Length: 9\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n";
|
||||
std::string content = "Not Found";
|
||||
|
||||
server.start(request, 0, response, 0, content);
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
urdl::read_stream stream1(io_service);
|
||||
|
||||
boost::system::error_code ec;
|
||||
std::size_t bytes_transferred = 0;
|
||||
handler h = { ec, bytes_transferred };
|
||||
|
||||
stream1.async_open("http://localhost:" + port + "/", h);
|
||||
io_service.run();
|
||||
|
||||
bool request_matched = server.stop();
|
||||
|
||||
BOOST_CHECK(request_matched);
|
||||
BOOST_CHECK(ec == urdl::http::errc::not_found);
|
||||
}
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("read_stream");
|
||||
test->add(BOOST_TEST_CASE(&read_stream_compile_test));
|
||||
test->add(BOOST_TEST_CASE(&read_stream_synchronous_http_test));
|
||||
test->add(BOOST_TEST_CASE(&read_stream_synchronous_http_not_found_test));
|
||||
test->add(BOOST_TEST_CASE(&read_stream_asynchronous_http_test));
|
||||
test->add(BOOST_TEST_CASE(&read_stream_asynchronous_http_not_found_test));
|
||||
return test;
|
||||
}
|
39
thirdparty/urdl-2013-08-15/test/unit_test.hpp
vendored
39
thirdparty/urdl-2013-08-15/test/unit_test.hpp
vendored
@ -1,39 +0,0 @@
|
||||
//
|
||||
// unit_test.hpp
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef UNIT_TEST_HPP
|
||||
#define UNIT_TEST_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable:4244)
|
||||
# pragma warning (disable:4535)
|
||||
# pragma warning (disable:4702)
|
||||
# pragma warning (disable:4996)
|
||||
#endif // defined(BOOST_MSVC)
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/included/unit_test_framework.hpp>
|
||||
using boost::unit_test::test_suite;
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning (pop)
|
||||
# pragma warning (disable:4996) // Leave this disabled for the unit tests.
|
||||
#endif // defined(BOOST_MSVC)
|
||||
|
||||
// Helper function to check the return type of a function.
|
||||
template <typename T>
|
||||
void want(const T&)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // UNIT_TEST_HPP
|
311
thirdparty/urdl-2013-08-15/test/url.cpp
vendored
311
thirdparty/urdl-2013-08-15/test/url.cpp
vendored
@ -1,311 +0,0 @@
|
||||
//
|
||||
// url.cpp
|
||||
// ~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2009-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Disable autolinking for unit tests.
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
#endif // !defined(BOOST_ALL_NO_LIB)
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include "urdl/url.hpp"
|
||||
|
||||
#include "unit_test.hpp"
|
||||
|
||||
// Ensure all functions compile correctly.
|
||||
void url_compile_test()
|
||||
{
|
||||
// Constructors
|
||||
|
||||
urdl::url url1;
|
||||
urdl::url url2("http://foo/bar");
|
||||
urdl::url url3(std::string("http://foo/bar"));
|
||||
urdl::url url4(url1);
|
||||
urdl::url url5 = url1;
|
||||
|
||||
// operator=
|
||||
|
||||
url5 = url2;
|
||||
|
||||
// protocol()
|
||||
|
||||
const urdl::url& const_url1 = url1;
|
||||
want<std::string>(const_url1.protocol());
|
||||
|
||||
// user_info()
|
||||
|
||||
want<std::string>(const_url1.user_info());
|
||||
|
||||
// host()
|
||||
|
||||
want<std::string>(const_url1.host());
|
||||
|
||||
// port()
|
||||
|
||||
want<unsigned short>(const_url1.port());
|
||||
|
||||
// path()
|
||||
|
||||
want<std::string>(const_url1.path());
|
||||
|
||||
// query()
|
||||
|
||||
want<std::string>(const_url1.query());
|
||||
|
||||
// fragment()
|
||||
|
||||
want<std::string>(const_url1.fragment());
|
||||
|
||||
// to_string()
|
||||
|
||||
want<std::string>(const_url1.to_string());
|
||||
want<std::string>(const_url1.to_string(urdl::url::protocol_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::user_info_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::host_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::port_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::path_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::query_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::fragment_component));
|
||||
want<std::string>(const_url1.to_string(urdl::url::all_components));
|
||||
|
||||
// from_string()
|
||||
|
||||
boost::system::error_code ec;
|
||||
want<urdl::url>(urdl::url::from_string("http://foo/bar"));
|
||||
want<urdl::url>(urdl::url::from_string("http://foo/bar", ec));
|
||||
want<urdl::url>(urdl::url::from_string(std::string("http://foo/bar")));
|
||||
want<urdl::url>(urdl::url::from_string(std::string("http://foo/bar"), ec));
|
||||
|
||||
// operator==
|
||||
|
||||
const urdl::url& const_url2 = url2;
|
||||
want<bool>(const_url1 == const_url2);
|
||||
|
||||
// operator!=
|
||||
|
||||
want<bool>(const_url1 != const_url2);
|
||||
|
||||
// operator<
|
||||
|
||||
want<bool>(const_url1 < const_url2);
|
||||
}
|
||||
|
||||
// Test URL parsing.
|
||||
void url_from_string_test()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
urdl::url url = urdl::url::from_string("http://host", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("HTTP://host", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host:123", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://user@host", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "user");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://user@host:123", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "user");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://user:pass@host", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "user:pass");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://user:pass@host:123", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "user:pass");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host/path", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host:123/path", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host?query", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host:123?query", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host/path?query", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "");
|
||||
|
||||
url = urdl::url::from_string("http://host#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://host:123#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://host/path#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://host?query#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://host/path?query#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 80);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://host:123/path?query#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://user@host:123/path?query#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "user");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
|
||||
url = urdl::url::from_string("http://u:p@host:123/path?query#fragment", ec);
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK(url.protocol() == "http");
|
||||
BOOST_CHECK(url.user_info() == "u:p");
|
||||
BOOST_CHECK(url.host() == "host");
|
||||
BOOST_CHECK(url.port() == 123);
|
||||
BOOST_CHECK(url.path() == "/path");
|
||||
BOOST_CHECK(url.query() == "query");
|
||||
BOOST_CHECK(url.fragment() == "fragment");
|
||||
}
|
||||
|
||||
test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
test_suite* test = BOOST_TEST_SUITE("url");
|
||||
test->add(BOOST_TEST_CASE(&url_compile_test));
|
||||
test->add(BOOST_TEST_CASE(&url_from_string_test));
|
||||
return test;
|
||||
}
|
Loading…
Reference in New Issue
Block a user