diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/.gitignore | 2 | ||||
-rw-r--r-- | docs/Makefile | 20 | ||||
-rw-r--r-- | docs/backends/start_stop.rst | 17 | ||||
-rw-r--r-- | docs/backends/summary.rst | 18 | ||||
-rw-r--r-- | docs/conf.py | 171 | ||||
-rw-r--r-- | docs/goals.rst | 26 | ||||
-rw-r--r-- | docs/index.rst | 66 | ||||
-rw-r--r-- | docs/make.bat | 36 | ||||
-rw-r--r-- | docs/requests/basics.rst | 43 | ||||
-rw-r--r-- | docs/requests/uri.rst | 37 |
10 files changed, 436 insertions, 0 deletions
diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..7bb92e5 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +_build +_build_html
\ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..7f0a64e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = python -msphinx +SPHINXPROJ = sttp +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file diff --git a/docs/backends/start_stop.rst b/docs/backends/start_stop.rst new file mode 100644 index 0000000..6cd6f13 --- /dev/null +++ b/docs/backends/start_stop.rst @@ -0,0 +1,17 @@ +Starting & cleaning up +====================== + +In case of most backends, you should only instantiate a backend once per +application, as a backend typically allocates resources such as thread or +connection pools. + +When ending the application, make sure to call ``backend.close()``, which will +free up resources used by the backend (if any). The close process might be +asynchronous, that is it can complete after the ``close()`` method returns. + +Note that only resources allocated by the backends are freed. For example, +if you use the ``AkkaHttpBackend()`` the ``close()`` method will terminate the +underlying actor system. However, if you have provided an existing actor system +upon backend creation (``AkkaHttpBackend.usingActorSystem``), the ``close()`` +method will be a no-op. + diff --git a/docs/backends/summary.rst b/docs/backends/summary.rst new file mode 100644 index 0000000..6aa0446 --- /dev/null +++ b/docs/backends/summary.rst @@ -0,0 +1,18 @@ +Supported backends +================== + +================================ ============================ ================================================ +Class Result wrapper Supported stream type +================================ ============================ ================================================ +``HttpURLConnectionBackend`` None (``Id``) n/a +``AkkaHttpBackend`` ``scala.concurrent.Future`` ``akka.stream.scaladsl.Source[ByteString, Any]`` +``AsyncHttpClientFutureBackend`` ``scala.concurrent.Future`` n/a +``AsyncHttpClientScalazBackend`` ``scalaz.concurrent.Task`` n/a +``AsyncHttpClientMonixBackend`` ``monix.eval.Task`` ``monix.reactive.Observable[ByteBuffer]`` +``AsyncHttpClientCatsBackend`` ``F[_]: cats.effect.Async`` n/a +``AsyncHttpClientFs2Backend`` ``F[_]: cats.effect.Async`` ``fs2.Stream[F, ByteBuffer]`` +``OkHttpSyncBackend`` None (``Id``) n/a +``OkHttpFutureBackend`` ``scala.concurrent.Future`` n/a +``OkHttpMonixBackend`` ``monix.eval.Task`` ``monix.reactive.Observable[ByteBuffer]`` +================================ ============================ ================================================ + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..0acfcf7 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# +# sttp documentation build configuration file, created by +# sphinx-quickstart on Thu Oct 12 15:51:09 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'sttp' +copyright = u'2017, SoftwareMill' +author = u'SoftwareMill' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'1.0' +# The full version, including alpha/beta/rc tags. +release = u'1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + 'donate.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'sttpdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'sttp.tex', u'sttp Documentation', + u'Adam Warski', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'sttp', u'sttp Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'sttp', u'sttp Documentation', + author, 'sttp', 'One line description of project.', + 'Miscellaneous'), +] + +highlight_language = 'scala' + diff --git a/docs/goals.rst b/docs/goals.rst new file mode 100644 index 0000000..9b59991 --- /dev/null +++ b/docs/goals.rst @@ -0,0 +1,26 @@ +Goals of the project +==================== + +* provide a simple, discoverable, no-surprises, reasonably type-safe API for making HTTP requests and reading responses +* separate definition of a request from request execution +* provide immutable, easily modifiable data structures for requests and responses +* support multiple execution backends, both synchronous and asynchronous +* provide support for backend-specific request/response streaming +* minimum dependencies + +See also the `introduction to sttp <https://softwaremill.com/introducing-sttp-the-scala-http-client>`_ +and `sttp streaming & URI interpolators <https://softwaremill.com/sttp-streaming-uri-interpolator>`_ +blogs. + +Non-goals of the project +------------------------ + +* implement a full HTTP client. Instead, sttp wraps existing HTTP clients, providing a consistent, programmer-friendly API. All network-related concerns such as sending the requests, connection pooling, receiving responses are delegated to the chosen backend +* provide ultimate flexibility in defining the request. While it's possible to define *most* valid HTTP requests, e.g. some of the less common body chunking approaches aren't available + +How is sttp different from other libraries? +------------------------------------------- + +* immutable request builder which doesn't impose any order in which request parameters need to be specified. Such an approach allows defining partial requests with common cookies/headers/options, which can later be specialized using a specific URI and HTTP method. +* support for multiple backends, both synchronous and asynchronous, with backend-specific streaming support +* URI interpolator with context-aware escaping, optional parameters support and parameter collections diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..e78ae4b --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,66 @@ +sttp: the Scala HTTP client you always wanted! +============================================== + +`sttp <https://github.com/softwaremill/sttp>`_ is an open-source library which provides a clean, programmer-friendly API to define HTTP requests and execute them using one of the wrapped backends, such as `akka-http <https://doc.akka.io/docs/akka-http/current/scala/http/>`_, `async-http-client <https://github.com/AsyncHttpClient/async-http-client>`_ or `OkHttp <http://square.github.io/okhttp/>`_. + +First impressions +----------------- + +.. code-block:: scala + + import com.softwaremill.sttp._ + + val sort: Option[String] = None + val query = "http language:scala" + + // the `query` parameter is automatically url-encoded + // `sort` is removed, as the value is not defined + val request = sttp.get(uri"https://api.github.com/search/repositories?q=$query&sort=$sort") + + implicit val backend = HttpURLConnectionBackend() + val response = request.send() + + // response.header(...): Option[String] + println(response.header("Content-Length")) + + // response.unsafeBody: by default read into a String + println(response.unsafeBody) + + +Quickstart with Ammonite +------------------------ + +If you are an `Ammonite <http://ammonite.io>`_ user, you can quickly start +experimenting with sttp by copy-pasting the following:: + + import $ivy.`com.softwaremill.sttp::core:0.0.20` + import com.softwaremill.sttp._ + implicit val backend = HttpURLConnectionBackend() + sttp.get(uri"http://httpbin.org/ip").send() + +Adding sttp to your project +--------------------------- + +The basic dependency which provides the default, synchornous backend is:: + + "com.softwaremill.sttp" %% "core" % "0.0.20" + +``sttp`` is available for Scala 2.11 and 2.12, and requires Java 7 if using an ``OkHttp`` based backend, or Java 8 otherwise. The core module has no transitive dependencies. + +If you'd like to use an alternate backend, [see below](#supported-backends) for additional instructions. + +.. toctree:: + :maxdepth: 2 + + goals + requests/basics + requests/uri + backends/summary + backends/start_stop + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..1cba1ce --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=python -msphinx
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+set SPHINXPROJ=sttp
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The Sphinx module was not found. Make sure you have Sphinx installed,
+ echo.then set the SPHINXBUILD environment variable to point to the full
+ echo.path of the 'sphinx-build' executable. Alternatively you may add the
+ echo.Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
diff --git a/docs/requests/basics.rst b/docs/requests/basics.rst new file mode 100644 index 0000000..6a6202c --- /dev/null +++ b/docs/requests/basics.rst @@ -0,0 +1,43 @@ +Defining requests: basics +========================= + +To get easy access to the request definition API, add the following import:: + + import com.softwaremill.sttp._ + +This brings into scope ``sttp``, the starting request (it's an empty request +with the ``Accept-Encoding: gzip, defalte`` header added). This request can +be customised, each time yielding a new, immutable request description +(unless a mutable body is set on the request, such as a byte array). + +For example, we can set a cookie, string-body and specify that this should +be a ``POST`` request to a given URI:: + + val request = sttp + .cookie("login", "me") + .body("This is a test") + .post(uri"http://endpoint.com/secret") + +The request parameters (headers, cookies, body etc.) can be specified in any +order. There's a lot of ways in which you can customize a request: just +explore the API. + +You can create a request description without knowing how it will be sent. +But to send a request, you will need a backend. A default, synchronous backend +based on Java's ``HttpURLConnection`` is provided out-of-the box. An implicit +value of type ``SttpBackend`` needs to be in scope to invoke the ``send()`` on the +request:: + + implicit val backend = HttpURLConnectionBackend() + + val response: Response[String] = request.send() + +By default the response body is read into a utf-8 string. How the response body +is handled is also part of the request description. The body can be ignore +(``.response(ignore)``), read into a sequence of parameters +(``.response(asParams)``), mapped (``.mapResponse``) and more; some backends also +support request & response streaming. + +The default backend doesn't wrap the response into any container, but other +asynchronous backends might do so. The type parameter in the ``Response[_]`` +type specifies the type of the body. diff --git a/docs/requests/uri.rst b/docs/requests/uri.rst new file mode 100644 index 0000000..bcb7c88 --- /dev/null +++ b/docs/requests/uri.rst @@ -0,0 +1,37 @@ +Defining requests: URI Interpolator +=================================== + +Using the URI interpolator it's possible to conveniently create ``Uri` instances, which can then be used to specify request endpoints, for example:: + + import com.softwaremill.sttp._ + + val user = "Mary Smith" + val filter = "programming languages" + + val endpoint: Uri = uri"http://example.com/$user/skills?filter=$filter" + +Any values embedded in the URI will be URL-encoded, taking into account the +context (e.g., the whitespace in ``user`` will be %-encoded as ``%20D``, while the +whitespace in ``filter`` will be query-encoded as ``+``). + +The possibilities of the interpolator don't end here. Other supported features: + +* parameters can have optional values: if the value of a parameter is ``None``, it will be removed +* maps, sequences of tuples and sequences of values can be embedded in the query part. They will be expanded into query parameters. Maps and sequences of tuples can also contain optional values, for which mappings will be removed if ``None``. +* optional values in the host part will be expanded to a subdomain if ``Some``, removed if ``None`` +* sequences in the host part will be expanded to a subdomain sequence +* if a string containing the protocol is embedded *as the very beginning*, it will not be escaped, allowing to embed entire addresses as prefixes, e.g.: ``uri"$endpoint/login"``, where ``val endpoint = "http://example.com/api"``. + +A fully-featured example:: + + import com.softwaremill.sttp._ + val secure = true + val scheme = if (secure) "https" else "http" + val subdomains = List("sub1", "sub2") + val vx = Some("y z") + val params = Map("a" -> 1, "b" -> 2) + val jumpTo = Some("section2") + uri"$scheme://$subdomains.example.com?x=$vx&$params#$jumpTo" + + // generates: + // https://sub1.sub2.example.com?x=y+z&a=1&b=2#section2 |