Aiohttp官方文档翻译-服务端-开始

快速开始

启动服务

from aiohttp import web

# 创建应用
app  = web.Application()
# 运行应用
web.run_app(app=app)

视图

request

ge t

async def handle_greeting(self, request):
    name = request.match_info.get('name', "Anonymous")
    txt = "Hello, {}".format(name)
    return web.Response(text=txt)

post

async def do_login(request):
    data = await request.post()
    login = data['login']
    password = data['password']

response

字符串

from aiohttp import web

async def hello(request):
    return web.Response(text="Hello, world")

json

async def handler(request):
    data = {'some': 'data'}
    return web.json_response(data)

重定向

# 绝对路径/相对路径
raise web.HTTPFound('/redirect')

# 使用name
async def handler(request):
    location = request.app.router['login'].url_for()
    raise web.HTTPFound(location=location)

router.add_get('/handler', handler)
router.add_get('/login', login_handler, name='login')

路由

注册

直接调用

async def handle_get(request):
    ...

async def handle_post(request):
    ...


app.router.add_get("/get", handle_get)
app.router.add_post("/post", handle_post)

django样式:表单

async def handle_get(request):
    ...

async def handle_post(request):
    ...

app.router.add_routes([
    web.get('/get', handle_get),
    web.post('/post', handle_post)])

flask样式:装饰器

routes = web.RouteTableDef()

@routes.get('/', [name='xxx'])
async def hello(request):
    pass

app.add_routes(routes)

反转

# 查询
app.add_routes([web.get('/root', handler, name='root')])
# 反转
url == request.app.router['root'].url_for().with_query({"a": "b", "c": "d"})
assert url == URL('/root?a=b&c=d')

# 有参数
app.router.add_get('/{user}/info', poll, name='user-info')
# 反转
url = request.app.router['user-info'].url_for(user='john_doe')
url_with_qs = url.with_query("a=b")
assert url_with_qs == '/john_doe/info?a=b'

查看

for resource in app.router.resources():
    print(resource)
# 带name
for name, resource in app.router.named_resources().items():
    print(name, resource)

基于类的视图路由

视图

class MyView(web.View):
    async def get(self):
        return await get_resp(self.request)

    async def post(self):
        return await post_resp(self.request)

路由

# 方法一
web.view('/path/to', MyView)
# 方法二
@routes.view('/path/to')
class MyView(web.View):
    ...

Session

aiohttp.web没有内置的session内容,第三方包aiohttp_sessionsession支持

import asyncio
import time
import base64
from cryptography import fernet
from aiohttp import web
from aiohttp_session import setup, get_session, session_middleware
from aiohttp_session.cookie_storage import EncryptedCookieStorage

async def handler(request):
    session = await get_session(request)
    last_visit = session['last_visit'] if 'last_visit' in session else None
    text = 'Last visited: {}'.format(last_visit)
    return web.Response(text=text)

async def make_app():
    app = web.Application()
    # secret_key must be 32 url-safe base64-encoded bytes
    fernet_key = fernet.Fernet.generate_key()
    secret_key = base64.urlsafe_b64decode(fernet_key)
    setup(app, EncryptedCookieStorage(secret_key))
    app.add_routes([web.get('/', handler)])
    return app

web.run_app(make_app())

webSocket

视图

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    async for msg in ws:
        if msg.type == aiohttp.WSMsgType.TEXT:
            if msg.data == 'close':
                await ws.close()
            else:
                await ws.send_str(msg.data + '/answer')
        elif msg.type == aiohttp.WSMsgType.ERROR:
            print('ws connection closed with exception %s' %
                  ws.exception())

    print('websocket connection closed')

    return ws

路由

app.add_routes([web.get('/ws', websocket_handler)])

异常

from aiohttp import web

async def handler(request): 
    raise web.HTTPNotFound(text=str(e))  # 404

所有HTTP异常有同样的构造函数

HTTPNotFound(*, headers=None, reason=None,
             body=None, text=None, content_type=None)

HTTPMultipleChoices, HTTPMovedPermanently, HTTPFound, HTTPSeeOther, HTTPUseProxy, HTTPTemporaryRedirect

HTTPFound(location, *, headers=None, reason=None,
          body=None, text=None, content_type=None)

HTTPMethodNotAllowed

HTTPMethodNotAllowed(method, allowed_methods, *,
                     headers=None, reason=None,
                     body=None, text=None, content_type=None)

异常类速览

Exception
  HTTPException
    HTTPSuccessful
      * 200 - HTTPOk
      * 201 - HTTPCreated
      * 202 - HTTPAccepted
      * 203 - HTTPNonAuthoritativeInformation
      * 204 - HTTPNoContent
      * 205 - HTTPResetContent
      * 206 - HTTPPartialContent
    HTTPRedirection
      * 300 - HTTPMultipleChoices
      * 301 - HTTPMovedPermanently
      * 302 - HTTPFound
      * 303 - HTTPSeeOther
      * 304 - HTTPNotModified
      * 305 - HTTPUseProxy
      * 307 - HTTPTemporaryRedirect
      * 308 - HTTPPermanentRedirect
    HTTPError
      HTTPClientError
        * 400 - HTTPBadRequest
        * 401 - HTTPUnauthorized
        * 402 - HTTPPaymentRequired
        * 403 - HTTPForbidden
        * 404 - HTTPNotFound
        * 405 - HTTPMethodNotAllowed
        * 406 - HTTPNotAcceptable
        * 407 - HTTPProxyAuthenticationRequired
        * 408 - HTTPRequestTimeout
        * 409 - HTTPConflict
        * 410 - HTTPGone
        * 411 - HTTPLengthRequired
        * 412 - HTTPPreconditionFailed
        * 413 - HTTPRequestEntityTooLarge
        * 414 - HTTPRequestURITooLong
        * 415 - HTTPUnsupportedMediaType
        * 416 - HTTPRequestRangeNotSatisfiable
        * 417 - HTTPExpectationFailed
        * 421 - HTTPMisdirectedRequest
        * 422 - HTTPUnprocessableEntity
        * 424 - HTTPFailedDependency
        * 426 - HTTPUpgradeRequired
        * 428 - HTTPPreconditionRequired
        * 429 - HTTPTooManyRequests
        * 431 - HTTPRequestHeaderFieldsTooLarge
        * 451 - HTTPUnavailableForLegalReasons
      HTTPServerError
        * 500 - HTTPInternalServerError
        * 501 - HTTPNotImplemented
        * 502 - HTTPBadGateway
        * 503 - HTTPServiceUnavailable
        * 504 - HTTPGatewayTimeout
        * 505 - HTTPVersionNotSupported
        * 506 - HTTPVariantAlsoNegotiates
        * 507 - HTTPInsufficientStorage
        * 510 - HTTPNotExtended
        * 511 - HTTPNetworkAuthenticationRequired

日志

aiohttp使用标准日志记录来跟踪库活动

'aiohttp.access'
'aiohttp.client'
'aiohttp.internal'
'aiohttp.server'
'aiohttp.web'
'aiohttp.websocket'

使用日志时的配置

import logging
from aiohttp import web

app = web.Application()
logging.basicConfig(level=logging.DEBUG)
web.run_app(app, port=5000)
  • 访问日志

访问日志默认情况下处于启用状态。如果设置了debug标志,并且使用了默认的记录器aiohttp.access,则如果未附加任何处理程序,则访问日志将输出到stderr。此外,如果默认记录器未设置日志级别,则日志级别将设置为logging.DEBUG

此日志记录可以由aiohttp.web.AppRunner()aiohttp.web.run_app()控制。

要覆盖默认记录器,请传递一个logging.Logger实例以覆盖默认记录器。

禁用访问日志

web.run_app(app, access_log=None)
  • 错误日志

aiohttp.web使用名为aiohttp.server的记录器来存储在Web请求处理中给出的错误。

默认情况下启用此日志。

要使用其他记录器名称,请将logger=logging.Logger()传递给aiohttp.web.AppRunner()构造函数。

  • 日志格式

默认格式

'%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"'

默认访问记录器的直接替换示例

from aiohttp.abc import AbstractAccessLogger

class AccessLogger(AbstractAccessLogger):

    def log(self, request, response, time):
        self.logger.info(f'{request.remote} '
                         f'"{request.method} {request.path} '
                         f'done in {time}s: {response.status}')

格式速览

Option Meaning
%% The percent sign
%a Remote IP-address (IP-address of proxy if using reverse proxy)
%t Time when the request was started to process
%P The process ID of the child that serviced the request
%r First line of request
%s Response status code
%b Size of response in bytes, including HTTP headers
%T The time taken to serve the request, in seconds
%Tf The time taken to serve the request, in seconds with fraction in %.06f format
%D The time taken to serve the request, in microseconds
%{FOO}i request.headers['FOO']
%{FOO}o response.headers['FOO']
原文地址:https://www.cnblogs.com/fhkankan/p/13522940.html