Skip to content

Commit

Permalink
Alpha release docs
Browse files Browse the repository at this point in the history
  • Loading branch information
tomchristie committed Feb 24, 2014
1 parent e188b5a commit b0920f0
Show file tree
Hide file tree
Showing 8 changed files with 530 additions and 0 deletions.
16 changes: 16 additions & 0 deletions docs/about/license.md
@@ -0,0 +1,16 @@
# License

This software is made available under the terms of a [BSD 2-Clause license][bsd-2-clause].

Copyright © 2014, Tom Christie
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

[bsd-2-clause]: http://opensource.org/licenses/BSD-2-Clause
3 changes: 3 additions & 0 deletions docs/about/release-notes.md
@@ -0,0 +1,3 @@
# Release Notes

This project is currently in alpha. It is funcational and well tested but you are advised to pay close attention to the release notes when upgrading to future versions.
114 changes: 114 additions & 0 deletions docs/api-guide/parsers.md
@@ -0,0 +1,114 @@
# Parsers

Parsers are responsible for taking the content of the request body as a bytestream, and transforming it into a native Python data representation.

Flask API includes a few built-in parser classes and also provides support for defining your own custom parsers.

## How the parser is determined

The set of valid parsers for a view is always defined as a list of classes. When any of the properties `request.data`, `request.form` or `request.files` are accessed, Flask API will examine the `Content-Type` header on the incoming request, and determine which parser to use to handle the request content.

---

**Note**: When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request.

If you don't set the content type, most clients will default to using `'application/x-www-form-urlencoded'`, which may not be what you wanted.

As an example, if you are sending `json` encoded data using jQuery with the [.ajax() method][jquery-ajax], you should make sure to include the `contentType: 'application/json'` setting.

---

## Setting the parsers

The default set of parsers may be set globally, using the `DEFAULT_PARSERS` configuration key. The default configuration will deal with parsing either JSON or form encoded requests.

app.config['DEFAULT_PARSERS'] = [
'flaskapi.parsers.JSONParser',
'flaskapi.parsers.URLEncodedParser',
'flaskapi.parsers.MultiPartParser'
]

You can also set the parsers used for an individual view, using the `set_parsers` decorator.

from flaskapi.decorators import set_parsers

...

@app.route('/example_view/')
@set_parsers(JSONParser, MyCustomXMLParser)
def example():
return {
'example': 'Setting renderers on a per-view basis',
'request data': request.data
}

---

# API Reference

## JSONParser

Parses `JSON` request content and populates `request.data`.

**media_type**: `application/json`

## FormParser

Parses HTML form content. `request.data` will be populated with a `MultiDict` of data.

You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data.

**media_type**: `application/x-www-form-urlencoded`

## MultiPartParser

Parses multipart HTML form content, which supports file uploads. Both `request.data` and `request.files` will be populated with a `MultiDict`.

You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data.

**media_type**: `multipart/form-data`

---

# Custom parsers

To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse(self, stream, media_type, **options)` method.

The method should return the data that will be used to populate the `request.data` property.

The arguments passed to `.parse()` are:

**`stream`**

A bytestream representing the body of the request.

**`media_type`**

An instance of MediaType indicating media type of the incoming request.

Depending on the request's `Content-Type:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"text/plain; charset=utf-8"`.

**`**options`**

Any additional contextual arguments that may be required in order to parse the request.
By default this includes a single keyword argument:

* `content_length` - An integer representing the length of the request body in bytes.

## Example

The following is an example plaintext parser that will populate the `request.data` property with a string representing the body of the request.

class PlainTextParser(BaseParser):
"""
Plain text parser.
"""
media_type = 'text/plain'

def parse(self, stream, media_type, **options):
"""
Simply return a string representing the body of the request.
"""
return stream.read().decode('utf8')

[jquery-ajax]: http://api.jquery.com/jQuery.ajax/
143 changes: 143 additions & 0 deletions docs/api-guide/renderers.md
@@ -0,0 +1,143 @@
# Renderers

Renderers are responsible for taking the response value from your view and transforming it into a string or bytestring that will be used as the response body.

Flask API includes a few built-in renderer classes and also provides support for defining your own custom renderers.

## Determining the renderer

The set of valid renderers for a view is always defined as a list of classes. When a view is entered Flask API will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request.

The basic process of content negotiation involves examining the request's `Accept` header, to determine which media types it expects in the response.

## Setting the renderers

The default set of renderers may be set globally, using the `DEFAULT_RENDERERS` configuration key. The default configuration will render to JSON as standard, or will render the browsable API if the client requests HTML.

app.config['DEFAULT_RENDERERS'] = [
'flaskapi.renderers.JSONRenderer',
'flaskapi.renderers.BrowsableAPIRenderer',
]

You can also set the renderers used for an individual view, using the `set_renderers` decorator.

from flaskapi.decorators import set_renderers

...

@app.route('/example_view/')
@set_renderers(JSONRenderer, MyCustomXMLRenderer)
def example():
return {'example': 'Setting renderers on a per-view basis'}

## Ordering of renderers

It's important when specifying the renderer classes for your API to think about what priority you want to assign to each media type. If a client underspecifies the representations it can accept, such as sending an `Accept: */*` header, or not including an `Accept` header at all, then Flask API will select the first renderer in the list to use for the response.

---

# API Reference

## JSONRenderer

Renders the request data into `JSON`.

The client may additionally include an `'indent'` media type parameter, in which case the returned `JSON` will be indented. For example `Accept: application/json; indent=4`.

{
"example": "indented JSON"
}

**`media_type`**: `application/json`

**`charset`**: `None`

## HTMLRenderer

A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.

An example of a view that uses `HTMLRenderer`:

@app.route('/hello-world/')
@set_renderers(HTMLRenderer)
def hello_world():
return '<html><body><h1>Hello, world</h1></body></html>'

You can use `HTMLRenderer` either to return regular HTML pages using Flask API, or to return both HTML and API responses from a single endpoint.

**`media_type`**: `text/html`

**`charset`**: `utf-8`

## BrowsableAPIRenderer

Renders data into HTML for the Browsable API. This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.

**`media_type`**: `text/html`

**`charset`**: `utf-8`

---

# Custom renderers

To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` property, and implement the `.render(self, data, media_type, **options)` method.

The method should return a string or bytestring, which will be used as the body of the HTTP response.

The arguments passed to the `.render()` method are:

**`data`**

The request data, returned by the view.

**`media_type`**

Optional. If provided, this is the accepted media type, as determined by the content negotiation stage.

Depending on the client's `Accept:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"application/json; api-version="0.1"`.

**`**options`**

Any additional contextual arguments that may be required in order to render the response.
By default this includes:

* `status` - A string representing the response status.
* `status_code` - An integer representing the response status code.
* `headers` - A dictionary containing the response headers.

## Example

The following is an custom renderer that returns YAML.

from flaskapi import renderers
import yaml


class YAMLRenderer(renderers.BaseRenderer):
media_type = 'application/yaml'
def render(self, data, media_type, **options):
return yaml.dump(data, encoding=self.charset)

<!--
TODO: This needs testing, and probably some more work.
## Setting the character set
By default renderer classes are assumed to be using the `UTF-8` encoding. To use a different encoding, set the `charset` attribute on the renderer.
class PlainTextRenderer(renderers.BaseRenderer):
media_type = 'text/plain'
charset = 'iso-8859-1'
def render(self, data, media_type, **options):
return data.encode(self.charset)
Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring, with the `charset` attribute set on the renderer used to determine the encoding.
If the renderer returns a bytestring representing raw binary content, you should set a charset value of `None`, which will ensure the `Content-Type` header of the response will not have a `charset` value set.
-->

[browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers
[rfc4627]: http://www.ietf.org/rfc/rfc4627.txt
113 changes: 113 additions & 0 deletions docs/api-guide/status-codes.md
@@ -0,0 +1,113 @@
# Status Codes

Flask API includes a set of named constants that you can use to make more code more obvious and readable.

from flaskapi import status

...

@app.route('/empty-view/')
def empty_view(self):
content = {'please move along': 'nothing to see here'}
return content, status.HTTP_404_NOT_FOUND

The full set of HTTP status codes included in the `status` module is listed below.

The module also includes a set of helper functions for testing if a status code is in a given range.

from flaskapi import status
import unittest

...

class ExampleTestCase(unittest.TestCase):
def test_success(self):
with app.test_client() as client:
response = client.get('/')
self.assertTrue(status.is_success(response.status_code))

For more information on proper usage of HTTP status codes see [RFC 2616][rfc2616]
and [RFC 6585][rfc6585].

## Informational - 1xx

This class of status code indicates a provisional response. There are no 1xx status codes used in REST framework by default.

HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS

## Successful - 2xx

This class of status code indicates that the client's request was successfully received, understood, and accepted.

HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT

## Redirection - 3xx

This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.

HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT

## Client Error - 4xx

The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.

HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE

## Server Error - 5xx

Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.

HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

## Helper functions

The following helper functions are available for identifying the category of the response code.

is_informational() # 1xx
is_success() # 2xx
is_redirect() # 3xx
is_client_error() # 4xx
is_server_error() # 5xx

[rfc2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
[rfc6585]: http://tools.ietf.org/html/rfc6585

0 comments on commit b0920f0

Please sign in to comment.