请求
请求
请求
请求
介绍
当服务器首次启动时,将对Request类进行初始化,并在每个请求上对其进行修改。这意味着Request类充当单例,并且不会在每个请求上都重新初始化。这说明了在开发Masonite时的利弊。不必担心每次都会实例化一个新对象,这很好,但是缺点是某些属性需要在请求结束时重置。
首先将Request类加载到IOC容器中,以便任何服务提供者都可以访问它。 IOC容器允许IOC容器解析框架的所有部分,并自动注入所需的任何依赖项。
了解更多的 服务容器。
入门
第一次启动应用程序时,将Request类绑定到IOC容器中。这将由WSGI服务生成的WSGI环境变量作为参数。因此,我们在每个请求上重新加载WSGI值,但实际的Request对象不会更改。换句话说,Request对象的内存地址始终是相同的,但是每个请求的类属性都会改变。 Masonite框架本身已经为您完成了此操作。此Request类在AppProvider
服务提供者内部进行绑定和初始化。我们只需将Request
传入服务容器解析的任何内容(例如中间件,驱动程序和控制器方法)的参数中,即可获取此请求对象:
def show(self, request: Request):
request #== <masonite.request.Request>
Masonite 足够聪明,知道我们需要 Request
类,它已将 request() 注入到我们的方法中。
辅助函数
Masonite 附带了 HelpersProvider
服务提供程序,该服务提供程序添加了一些辅助函数。这些辅助函数之一是 request()
函数。该函数将返回请求对象。因此,这两段代码是相同的:
def show(self, request: Request):
request.input('username')
def show(self):
request().input('username')
注意,我们没有在文件顶部导入任何内容,也没有从 IOC 容器中检索任何对象。 Masonite 辅助函数的行为与其他任何内置Python函数一样。
学习更多相关 辅助函数 知识。
用法
Request
附加了几个辅助方法,以便与请求的各个方面进行交互。
为了获取当前请求的输入变量,例如 表单的POST
请求或 GET
请求期间的查询字符串,如下所示:
def show(self, request: Request):
request.input('username')
在获取输入数据时,任何HTTP方法 (GET,POST,PUT等) 之间没有区别。它们都可以通过此
.input()
方法检索的,因此,如果请求是GET
或POST
,则无需进行区分。
Method 选项
input
我们可以获取所有请求输入变量,例如来自表单请求的输入数据或来自查询字符串的 GET 数据。请注意,使用哪种 HTTP 方法都没有关系,input 方法将知道要获取的输入数据取决于当前的HTTP方法 (GET
,POST
,PUT
等 )
这将以字典形式返回该请求的所有可用请求输入变量。
# GET: /dashboard?user=Joe&status=1
def show(self, request: Request):
return request.all() # {'user': 'Joe', 'status': '1'}
此方法将获取所有请求输入变量,同时包括在框架内部处理的变量,例如 token 和 method 。您可以通过将 False 传入方法或显式指定它们来排除它们:
# GET: /dashboard?user=Joe&status=1&__token=837674634
def show(self, request: Request):
return request.all(internal_variables=False) # {'user': 'Joe', 'status': '1'}
要获取特定输入:
# GET: /dashboard?firstname=Joe
def show(self, request: Request):
return request.input('firstname') # Joe
Input Cleaning
输入数据将清除 HTML 标记和其他安全隐患。如果您期望获取 JSON 字符串之类的东西,则可能会导致不想要的返回值。如果要选择不清除输入,可以将其指定为关键字参数:
request.input('firstname', clean=False) # Joe
要检查是否存在某些请求输入数据:
# GET: /dashboard?firstname=Joe
def show(self, request: Request):
return request.has('firstname') # True
获取字典输入
如果您输入的是字典,则有两种选择方式来访问字典。您可以正常访问它:
request.input('payload')['user']['address'] # 123 Smith Rd
或者,您可以使用点表示法来获取值以简化操作:
request.input('payload.user.address') # 123 Smith Rd
您也可以使用 * 通配符从字典列表中获取所有值。请看以下代码示例:
"""
Payload:
"user": {
"id": 1,
"addresses": [
{"id": 1, 'street': "A Street"},
{"id": 2, 'street': "B Street"}
]
}
"""
request.input('user.addresses.*.id') # [1,2]
Only
如果您只想获取一组特定的参数,可以这样使用:
# GET: /dashboard?firstname=Joe&lastname=Mancuso&active=1
def show(self, request: Request):
return request.only('firstname', 'active') # {'firstname': 'Joe', 'active': '1'}
Without
我们可以排除输入的数据中特定的一组参数。例如:
# GET: /dashboard?firstname=Joe&lastname=Mancuso&active=1
def show(self, request: Request):
return request.without('lastname') # {'firstname': 'Joe', 'active': '1'}
请注意,它返回了除 lastname
之外的所有内容。
URL 参数
从URL中获取检索的请求参数。这类似于获取 / dashboard / @ firstname
中的变量。
# Route: /dashboard/@firstname
# GET: /dashboard/Joe
def show(self, request: Request):
return request.param('firstname') # Joe
JSON Payloads
有时您可能想处理传入的JSON请求,像 Github 的外部 API 那样 。
Masonite 将检测到传入请求是 JSON 请求,并将 JSON 转换为字典,然后将其加载到有效负载请求输入中。例如,如果您传入以下请求:
{
"name": "Joe",
"email": "Joe@email.com"
}
然后,我们可以使用常规的 input()
方法在控制器中获取此输入,如下所示:
def show(self, request: Request):
request.input('name') # Joe
Cookies
您也可以在浏览器中设置 Cookie,以下代码将设置一个cookie ,名为 key
值为 value
。
默认情况下,所有 cookie 均使用您的密钥加密,该密钥在您安装Masonite 时在
.env
文件中生成。这是一种安全措施,可确保恶意代码无法通过某种方式获取 cookie。所有 cookie 均使用 HTTP_ONLY 标志设置,这意味着 Javascript 无法读取它们,尽管您可以使用参数将其关闭。
创建
def show(self, request: Request):
return request.cookie('key', 'value')
取消加密
如果您选择不加密值并使用纯文本值创建 cookie,则可以传递第三个值 True
或 False
。如果您愿意,也可以更加明确:
def show(self, request: Request):
return request.cookie('key', 'value', encrypt=False)
到期时间
所有 cookie 都设置为会话 cookie 。这意味着,当用户完全关闭浏览器时,所有cookie都将被删除。
def show(self, request: Request):
return request.cookie('key', 'value', expires="5 minutes")
这将设置一个cookie,该cookie从当前时间起5分钟后过期。
HttpOnly
同样,作为安全措施,所有 cookie 都将自动使用 HttpOnly
标志进行设置,Javascript代码无法使用这些 cookie。您可以关闭此功能:
def show(self, request: Request):
return request.cookie('key', 'value', http_only=False)
现在,这将允许Javascript读取Cookie。
获取
您可以从浏览器中获取所有cookie集:
def show(self, request: Request):
return request.get_cookies()
您可以从浏览器中获取特定的 Cookie:
def show(self, request: Request):
return request.get_cookie('key')
同样,默认情况下,所有cookie都是加密的,因此,如果您设置了带有加密的 cookie,则此方法将解密该 cookie。如果您以纯文本设置 cookie,则应在此处传递 False
作为第二个参数,以告知 Masonite 不要解密您的纯文本cookie值。
def show(self, request: Request):
return request.get_cookie('key', decrypt=False)
这将返回cookie的纯文本版本。
如果 Masonite 尝试解密 Cookie ,但无法解密,则 Masonite 会假定对它进行加密的密钥已更改或 cookie 被篡改,并将完全删除 cookie 。
如果您的密钥已被盗用,则您可以随时更改密钥,并且将删除服务器上设置的所有cookie。
删除
你可能会删除cookie,将从浏览器端移除。
def show(self, request: Request):
return request.delete_cookie('key')
用户
您也可以从请求中获取当前用户。这需要用到 Masonite 中的 LoadUserMiddleware
中间件。这将返回当前用户的实例。
def show(self, request: Request):
return request.user()
路由
您还可以通过路由名称获取路由 URL。假设我们有这样一条路由:
Get('/dashboard').name('dashboard')
我们可以像这样通过路由名称获取 URL:
def show(self):
request().route('dashboard') # /dashboard
路由解析
如果我们有这样的路由参数:
Get('/dashboard/@user').name('dashboard.user')
然后我们可以传入字典:
def show(self, request: Request):
request.route('dashboard.user', {'user': 1}) # /dashboard/1
您还可以传递一个列表:
def show(self, request: Request):
request.route('dashboard.user', [1]) # /dashboard/1
这将按顺序为每个参数注入该值。例如,如果我们有以下路由:
Get('/dashboard/@user/@id/@slug').name('dashboard.user')
然后我们可以使用:
def show(self, request: Request):
request.route('dashboard.user', [1, 2, 'some-slug'])
# /dashboard/1/2/some-slug
包含
我们还可以检查路由是否包含特定模式:
# GET /dashboard/user/1
def show(self, request: Request):
request.contains('/dashboard/*/1') #== True
您也可以在模板中使用它,并传入 show
参数来返回字符串。如果要根据当前路由显示活动状态,这将很有用:
<a href=".." class="{{ request().contains('/dashboard/*/edit', show='active')">
<a href=".." class="{{ request().contains('/dashboard/*/create', show='active')">
当前链接
我们可以通过以下方式获取当前链接:
def show(self, request: Request):
return request.path #== /dashboard/user
重定向
您可以指定一个网址以重定向到另外一个地址:
def show(self, request: Request):
return request.redirect('/home')
如果网址包含 http
,则路由将重定向到外部网站。
def show(self, request: Request):
return request.redirect('http://google.com')
您可以重定向到已经命名的路由:
def show(self, request: Request):
return request.redirect_to('dashboard')
您还可以在 redirect 方法上使用name参数:
def show(self, request: Request):
return request.redirect(name="dashboard")
您还可以重定向到特定的控制器。这将找到附加到控制器方法的URL。
def show(self, request: Request):
return request.redirect(controller="WelcomeController@show")
有时您的路由需要传递参数给它,例如这个路由: /url/@firstname:string/@lastname:string
使用URL参数重定向到命名路由:
def show(self, request: Request):
return request.redirect_to('dashboard', {'firstname': 'Joseph', 'lastname': 'Mancuso'})
使用URL参数重定向到应用程序中的 url:
def show(self, request: Request):
return request.redirect('dashboard/@id', {'id': '1'})
返回
您将需要很多时间重定向回用户刚来自的位置。为了进行这项工作,我们需要指定需要返回的位置。我们可以使用back方法。
你可能经常会将用户重定向到刚才过来的链接,需要指定需要返回的位置,可以使用 back 方法。
表单重定向返回
Masonite 将检查 __ back
输入并重定向到该路由。我们可以使用 back()
视图辅助函数指定一个返回链接:
<form action="{{ route('dashboard.create') }}" method="POST">
{{ csrf_field }}
{{ back() }}
</form>
默认情况下,back
辅助函数将返回当前路径,因此您可以在提交表单后轻松返回上一页。
您还可以指定返回到的链接:
<form action="{{ route('dashboard.create') }}" method="POST">
{{ csrf_field }}
{{ back('/another/path') }}
</form>
重定向返回
提交表单后,您可以使用 back()
方法重定向到 back
模板方法指向的位置:
def show(self, request: Request):
...
return request.back()
这还将把当前输入刷新到 session 中。然后,您可以使用 {{old('key')}}
模板辅助函数获取输入:
<form>
<input type="text" name="email" value="{{ old ('email') }}">
...
</form>
携带错误信息重定向返回
您可以携带验证错误消息重定向返回,也可以携带输入值重定向返回:
def show(self, request: Request):
errors = request.validate(
required(['email', 'password'])
)
if errors:
return request.back().with_errors(errors)
携带输入数据重定向返回
重定向返回时,有时您希望将输入数据刷到 session 中。这样,您可以简单地使用back()
方法。如果您想有更多的控制权,可以使用 with_input()
方法。
def show(self, request: Request):
errors = request.validate(
required(['email', 'password'])
)
if errors:
return request.redirect('/dashboard/errors').with_input()
然后,您可以使用 {{old('key')}}
模板辅助函数获取输入:
<form>
<input type="text" name="email" value="{{ old ('email') }}">
...
</form>
默认返回链接
我们也可以指定默认路由,以防提交的表单没有使用辅助函数指定:
def show(self, request: Request):
return request.back(default='/hit/route')
这将检查 __ back
输入,如果不存在,它将使用此默认路由。如果您没使用 back()
辅助函数,达到的效果和这个一样。
加密密钥
您可以使用以下方法将特定密钥加载到请求中:
request.key(key)
这会将密钥加载到请求中,该密钥将贯穿整个 Masonite 项目中的加密。
请注意,默认情况下,密钥是从配置文件中提取的,因此您不需要提供密钥。但是如果需要出于测试和开发目的而对其进行更改,则可以使用该选项。
Header 头
您还可以获取并设置请求具有的所有 Header 头。
您可以打印所有 WSGI 信息:
def show(self, request: Request):
print(request.environ)
这将打印 WSGI 服务器的环境设置。将此用于开发调试。
您还可以获取特定的 header 头:
def show(self, request: Request):
request.header('AUTHORIZATION')
如果存在 HTTP_AUTHORIZATION
头,它将返回内容。如果不存在,则将返回None
。
我们还可以设置 header 头:
def show(self, request: Request):
request.header('AUTHORIZATION', 'Bearer some-secret-key')
Masonite 会自动将
HTTP
放在设置的 header 头字符串之前,因此将设置HTTP_AUTHORIZATION
标头。如果您不希望使用HTTP
前缀,请传递第三个参数:译者在测试的时候发现,默认不会将
HTTP_
添加到前缀。只有在第三个参数写 True的时候才会。request.header('AUTHORIZATION', 'Bearer some-secret-key')
这将设置 AUTHORIZATION
头,而不是 HTTP_AUTHORIZATION
头。
您还可以使用字典设置header 头:
request.header({
'AUTHORIZATION': 'Bearer some-secret-key',
'Content-Type': 'application/json'
})
状态码
Masonite 将在每个请求开始时将状态代码设置为 404 Not Found
。如果开发人员或者第三方包一直没有更改状态码,则生成输出的时候仍然为 404 Not Found
。您无需明确指定它,因为框架本身会处理状态码。如果路由匹配并且控制器方法即将被命中,则 Masonite 将设置 200 OK
。这使 Masonite 可以指定良好的状态代码,但您也可以在控制器方法中再次对其进行更改。
您可以通过服务提供者在任何控制器甚至第三方程序包中更改此状态代码。
例如,Masonite Entry 程序包在API端上的某些操作上设置了某些状态码。这些可能是 429太多请求
或 201创建的
, 必须在运行 StartProvider
之前设置这些状态码。因此,如果您具有设置状态码或header 头的第三方程序包,则需要将它们放此服务提供者的上方。
如果您没有在程序包中指定状态码,您可以在控制器中随意指定。您可以这样设置状态码:
request.status('429 Too Many Requests')
您还可以使用一个整数,该整数将为您找到正确的状态码:
request.status(429)
此代码段与上述基于字符串的代码段效果一样。
在将输出发送到浏览器之前,这将设置正确的状态码。您可以从在线资源中查找 HTTP 状态代码列表,并指定所需的内容。
获取请求方法类型:
您可以简单地获取请求方法:
# PUT: /dashboard
def show(self, request: Request):
return request.get_request_method() # 'PUT'
更改表单中的请求方法
通常,表单仅支持 GET
和 POST
。您可能需要更改诸如 PATCH
之类的提交方法。
例如:
<form action="/dashboard" method="POST">
<input type="hidden" name="request_method" value="PATCH">
</form>
或者,您可以使用辅助函数:
<form action="/dashboard" method="POST">
{{ request_method('PATCH') }}
</form>
提交表单后,它将作为 PUT 请求而不是 POST 请求处理。
路由需要这么设置才能命中:
from masonite.routes import Patch
ROUTES = [
Patch().route('/dashboard', 'DashboardController@update')
]
验证
验证请求的合法性有一种特别方便的辅助方法。您可以导入 Validator
类,并使用验证,如下所示:
from masonite.request import Request
from masonite.validation import Validator
def show(self, request: Request, validate: Validator):
errors = request.validate(
validate.required('user')
)
if errors:
return request.back().with_errors(errors)
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。