## 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. 
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)