socketify.py/docs/basics.md

197 wiersze
6.5 KiB
Markdown
Czysty Zwykły widok Historia

## All Basic Stuff
This section is to show the basics of `AppResponse` and `AppRequest`
### Writing data
`res.write(message)` were message can be String, bytes or an Object that can be converted to json, send the message to the response without ending.
`res.cork_end(message, end_connection=False)` or `res.end(message, end_connection=False)` were message can be String, bytes or an Object that can be converted to json, send the message to the response and end the response.
The above `res.end()` or `res.cork_end()` call will actually call three separate send functions; res.write_status, res.write_header and whatever it does itself. By wrapping the call in `res.cork` or `res.cork_end` you make sure these three send functions are efficient and only result in one single send syscall and one single SSL block if using SSL.
Using `res.write_continue()` writes HTTP/1.1 100 Continue as response
`res.write_offset(offset)` sets the offset for writing data
`res.get_write_offset()` gets the current write offset
`res.pause()` and `res.resume()` pause and resume the response
```python
def send_in_parts(res, req):
# write and end accepts bytes and str or its try to dumps to an json
res.write("I can")
res.write(" send ")
res.write("messages")
res.end(" in parts!")
```
### Ending without body
```python
def empty(res, req):
res.end_without_body()
```
## Check if already responded
`res.has_responded()` returns True if the response is already done.
### Redirecting
```python
def redirect(res, req):
# status code is optional default is 302
res.redirect("/redirected", 302)
```
### Writing Status
```python
def not_found(res, req):
res.write_status(404).end("Not Found")
def ok(res, req):
res.write_status("200 OK").end("Not Found")
```
### Check the URL or Method
`req.get_full_url()` will return the path with query string
`req.get_url()` will return the path without query string
`req.get_method()` will return the HTTP Method (is case sensitive)
### Parameters
You can use `req.get_parameters(index)` to get the parametervalue as String or use `req.get_parameters()` to get an list of parameters
```python
def user(res, req):
if int(req.get_parameter(0)) == 1:
return res.end("Hello user with id 1!")
params = req.get_parameters()
print('All params', params)
app.get("/user/:id", user)
```
### Headers
You can use `req.get_header(lowercase_header_name)` to get the header string value as String or use `req.get_headers()` to get as a dict, `req.for_each_header()` if you just want to iterate in the headers.
You can also set the header using `res.write_header(name, value)`.
```python
def home(res, req):
auth = req.get_header("authorization")
headers = req.get_headers()
print("All headers", headers)
def custom_header(res, req):
res.write_header("Content-Type", "application/octet-stream")
res.write_header("Content-Disposition", 'attachment; filename="message.txt"')
res.end("Downloaded this ;)")
def list_headers(res, req):
req.for_each_header(lambda key, value: print("Header %s: %s" % (key, value)))
```
### Query String
You can use `req.get_query(parameter_name)` to get the query string value as String or use `req.get_queries()` to get as a dict.
```python
def home(res, req):
search = req.get_query("search")
queries = req.get_queries()
print("All queries", queries)
```
### Cookies
We also have an `req.get_cookie(cookie_name)` to get a cookie value as String and `res.set_cookie(name, value, options=None)` to set a cookie.
```python
def cookies(res, req):
# cookies are writen after end
res.set_cookie(
"session_id",
"1234567890",
{
# expires
# path
# comment
# domain
# max-age
# secure
# version
# httponly
# samesite
"path": "/",
# "domain": "*.test.com",
"httponly": True,
"samesite": "None",
"secure": True,
"expires": datetime.utcnow() + timedelta(minutes=30),
},
)
res.end("Your session_id cookie is: %s" % req.get_cookie("session_id"))
```
## Getting remote address
You can get the remote address by using get_remote_address_bytes, get_remote_address and the proxied address using get_proxied_remote_address_bytes or get_proxied_remote_address
```python
def home(res, req):
res.write("<html><h1>")
res.write("Your proxied IP is: %s" % res.get_proxied_remote_address())
res.write("</h1><h1>")
res.write("Your IP as seen by the origin server is: %s" % res.get_remote_address())
res.end("</h1></html>")
```
> The difference between the _bytes() version an non bytes is that one returns an String an the other the raw bytes
## App Pub/Sub
`app.num_subscribers(topic)` will return the number of subscribers at the topic.
`app.publish(topic, message, opcode=OpCode.BINARY, compress=False)` will send a message for everyone subscribed in the topic.
## Check if is aborted
If the connection aborted you can check `res.aborted` that will return True or False. You can also grab the abort handler, when using an async route, socketify will always auto grab the abort handler
```python
def home(res, req):
def on_abort(res):
res.aborted = True
print("aborted!")
res.on_aborted(on_abort)
```
## Running async from sync route
If you wanna to optimize a lot and don't use async without need you can use `res.run_async() or app.run_async()` to execute an coroutine
```python
from socketify import App, sendfile
def route_handler(res, req):
if in_memory_text:
res.end(in_memory_text)
else:
# grab the abort handler adding it to res.aborted if aborted
res.grab_aborted_handler()
res.run_async(sendfile(res, req, "my_text"))
```
## Raw socket pointer
If for some reason you need the raw socket pointer you can use `res.get_native_handle()` and will get an CFFI handler.
## Raw event loop pointer
If you need to access the raw pointer of `libuv` you can use `app.get_native_handle()` and will get an CFFI handler.
## Preserve data for use after await
HttpRequest object being stack-allocated and only valid in one single callback invocation so only valid in the first "segment" before the first await.
2022-11-17 22:01:15 +00:00
If you just want to preserve headers, url, method, cookies and query string you can use `req.preserve()` to copy all data and keep it in the request object, but will be some performance penality.
### Next [Upload and Post](upload-post.md)