Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
gaby committed Dec 15, 2024
1 parent 39efc15 commit 3d23da2
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 236 deletions.
72 changes: 49 additions & 23 deletions docs/client/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,35 @@
id: hooks
title: 🎣 Hooks
description: >-
Hooks are used to manipulate request/response process of Fiber client.
Hooks are used to manipulate the request/response process of the Fiber client.
sidebar_position: 4
---

With hooks, you can manipulate the client on before request/after response stages or more complex logging/tracing cases.
Hooks allow you to intercept and modify the request or response flow of the Fiber client. They are particularly useful for:

There are 2 kinds of hooks:
- Changing request parameters (e.g., URL, headers) before sending the request.
- Logging request and response details.
- Integrating complex tracing or monitoring tools.
- Handling authentication, retries, or other custom logic.

There are two kinds of hooks:

## Request Hooks

They are called before the HTTP request has been sent. You can use them make changes on Request object.
**Request hooks** are functions executed before the HTTP request is sent. They follow the signature:

```go
type RequestHook func(*Client, *Request) error
```

A request hook receives both the `Client` and the `Request` objects, allowing you to modify the request before it leaves your application. For example, you could:

You need to use `RequestHook func(*Client, *Request) error` function signature while creating the hooks. You can use request hooks to change host URL, log request properties etc. Here is an example about how to create request hooks:
- Change the host URL.
- Log request details (method, URL, headers).
- Add or modify headers or query parameters.
- Intercept and apply custom authentication logic.

**Example:**

```go
type Repository struct {
Expand All @@ -31,9 +47,9 @@ type Repository struct {
func main() {
cc := client.New()

// Add a request hook that modifies the request URL before sending.
cc.AddRequestHook(func(c *client.Client, r *client.Request) error {
r.SetURL("https://api.github.com/" + r.URL())

return nil
})

Expand All @@ -48,7 +64,6 @@ func main() {
}

fmt.Printf("Status code: %d\n", resp.StatusCode())

fmt.Printf("Repository: %s\n", repo.FullName)
fmt.Printf("Description: %s\n", repo.Description)
fmt.Printf("Homepage: %s\n", repo.Homepage)
Expand All @@ -73,17 +88,17 @@ Full Name: gofiber/fiber

</details>

There are also some builtin request hooks provide some functionalities for Fiber client. Here is a list of them:
### Built-in Request Hooks

- [parserRequestURL](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L62): parserRequestURL customizes the URL according to the path params and query params. It's necessary for `PathParam` and `QueryParam` methods.
Fiber provides some built-in request hooks:

- [parserRequestHeader](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L113): parserRequestHeader sets request headers, cookies, body type, referer, user agent according to client and request properties. It's necessary to make request header and cookiejar methods functional.
- **parserRequestURL**: Normalizes and customizes the URL based on path and query parameters. Required for `PathParam` and `QueryParam` methods.
- **parserRequestHeader**: Sets request headers, cookies, content type, referer, and user agent based on client and request properties.
- **parserRequestBody**: Automatically serializes the request body (JSON, XML, form, file uploads, etc.).

- [parserRequestBody](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L178): parserRequestBody serializes the body automatically. It is useful for XML, JSON, form, file bodies.
If any request hook returns an error, the request is interrupted and the error is returned immediately.

:::info
If any error returns from request hook execution, it will interrupt the request and return the error.
:::
**Example with Multiple Hooks:**

```go
func main() {
Expand Down Expand Up @@ -123,9 +138,15 @@ exit status 2

## Response Hooks

They are called after the HTTP response has been completed. You can use them to get some information about response and request.
**Response hooks** are functions executed after the HTTP response is received. They follow the signature:

You need to use `ResponseHook func(*Client, *Response, *Request) error` function signature while creating the hooks. You can use response hook for logging, tracing etc. Here is an example about how to create response hooks:
```go
type ResponseHook func(*Client, *Response, *Request) error
```

A response hook receives the `Client`, `Response`, and `Request` objects, allowing you to inspect and modify the response or perform additional actions such as logging, tracing, or processing response data.

**Example:**

```go
func main() {
Expand Down Expand Up @@ -173,16 +194,19 @@ X-Cache: HIT

</details>

There are also some builtin request hooks provide some functionalities for Fiber client. Here is a list of them:
### Built-in Response Hooks

- [parserResponseCookie](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L293): parserResponseCookie parses cookies and saves into the response objects and cookiejar if it's exists.
Fiber provides built-in response hooks:

- [logger](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L319): logger prints some RawRequest and RawResponse information. It uses [log.CommonLogger](https://github.com/gofiber/fiber/blob/main/log/log.go#L49) interface for logging.
- **parserResponseCookie**: Parses cookies from the response and stores them in the response object and cookie jar if available.
- **logger**: Logs information about the raw request and response. It uses the `log.CommonLogger` interface.

:::info
If any error is returned from executing the response hook, it will return the error without executing other response hooks.
If a response hook returns an error, it stops executing any further hooks and returns the error.
:::

**Example with Multiple Response Hooks:**

```go
func main() {
cc := client.New()
Expand Down Expand Up @@ -225,9 +249,11 @@ exit status 2

</details>

:::info
Hooks work as FIFO (first-in-first-out). You need to check the order while adding the hooks.
:::
## Hook Execution Order

Hooks run in FIFO order (First-In-First-Out). That means hooks are executed in the order they were added. Keep this in mind when adding multiple hooks, as the order can affect the outcome.

**Example:**

```go
func main() {
Expand Down
73 changes: 38 additions & 35 deletions docs/client/response.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,59 @@ description: >-
sidebar_position: 3
---

The `Response` structure in Gofiber's HTTP client represents the server's response to an HTTP request. It contains all the necessary information received from the server. This includes:
The `Response` structure in Gofiber's HTTP client represents the server's response to an HTTP request. It includes:

- **Status Code**: The HTTP status code returned by the server (e.g., 200 OK, 404 Not Found).
- **Headers**: HTTP headers received from the server that provide additional information about the response.
- **Body**: The data received from the server, typically in the form of a JSON, XML, or plain text format.
- **Cookies**: Any cookies sent by the server along with the response.
- **Status Code**: The HTTP status code returned by the server (e.g., `200 OK`, `404 Not Found`).
- **Headers**: All HTTP headers returned by the server, providing additional response-related information.
- **Body**: The response body content, which can be JSON, XML, plain text, or other formats.
- **Cookies**: Any cookies the server sent along with the response.

This structure allows users to easily access and manage the data returned by the server, facilitating efficient handling of HTTP responses.
This structure makes it easy to inspect and handle the data sent back by the server.

```go
type Response struct {
client *Client
request *Request
cookie []*fasthttp.Cookie

client *Client
request *Request
cookie []*fasthttp.Cookie
RawResponse *fasthttp.Response
}
```

## AcquireResponse

AcquireResponse returns an empty response object from the pool.
The returned response may be returned to the pool with ReleaseResponse when no longer needed.
This allows reducing GC load.
**AcquireResponse** returns a new (pooled) `Response` object. When finished, release it using `ReleaseResponse` to reduce GC overhead.

```go title="Signature"
func AcquireResponse() *Response
```

## ReleaseResponse

ReleaseResponse returns the object acquired via AcquireResponse to the pool.
Do not access the released Response object; otherwise, data races may occur.
**ReleaseResponse** returns the `Response` object to the pool. Avoid using the response after releasing it to prevent data races.

```go title="Signature"
func ReleaseResponse(resp *Response)
```

## Status

Status method returns the HTTP status string for the executed request.
**Status** returns the HTTP status message (e.g., `OK`, `Not Found`) associated with the response.

```go title="Signature"
func (r *Response) Status() string
```

## StatusCode

StatusCode method returns the HTTP status code for the executed request.
**StatusCode** returns the numeric HTTP status code of the response.

```go title="Signature"
func (r *Response) StatusCode() int
```

## Protocol

Protocol method returns the HTTP response protocol used for the request.
**Protocol** returns the HTTP protocol used (e.g., `HTTP/1.1`, `HTTP/2`) for the response.

```go title="Signature"
func (r *Response) Protocol() string
Expand All @@ -80,6 +76,8 @@ if err != nil {
fmt.Println(resp.Protocol())
```

**Output:**

```text
HTTP/1.1
```
Expand All @@ -88,16 +86,15 @@ HTTP/1.1

## Header

Header method returns the response headers.
**Header** retrieves the value of a specific response header by key. If multiple values exist for the same header, this returns the first one.

```go title="Signature"
func (r *Response) Header(key string) string
```

## Headers

Headers returns all headers in the response using an iterator. You can use `maps.Collect()` to collect all headers into a map.
The returned value is valid until the response object is released. Any future calls to Headers method will return the modified value. Do not store references to returned value. Make copies instead.
**Headers** returns an iterator over all response headers. Use `maps.Collect()` to convert them into a map if desired. The returned values are only valid until the response is released, so make copies if needed.

```go title="Signature"
func (r *Response) Headers() iter.Seq2[string, []string]
Expand All @@ -117,6 +114,8 @@ for key, values := range resp.Headers() {
}
```

**Output:**

```text
Date => Wed, 04 Dec 2024 15:28:29 GMT
Connection => keep-alive
Expand All @@ -135,12 +134,14 @@ if err != nil {
panic(err)
}

headers := maps.Collect(resp.Headers()) // Collect all headers into a map
headers := maps.Collect(resp.Headers())
for key, values := range headers {
fmt.Printf("%s => %s\n", key, strings.Join(values, ", "))
}
```

**Output:**

```text
Date => Wed, 04 Dec 2024 15:28:29 GMT
Connection => keep-alive
Expand All @@ -152,8 +153,7 @@ Access-Control-Allow-Credentials => true

## Cookies

Cookies method to access all the response cookies.
The returned value is valid until the response object is released. Any future calls to Cookies method will return the modified value. Do not store references to returned value. Make copies instead.
**Cookies** returns a slice of all cookies set by the server in this response. The slice is only valid until the response is released.

```go title="Signature"
func (r *Response) Cookies() []*fasthttp.Cookie
Expand All @@ -174,6 +174,8 @@ for _, cookie := range cookies {
}
```

**Output:**

```text
go => fiber
```
Expand All @@ -182,23 +184,23 @@ go => fiber

## Body

Body method returns HTTP response as []byte array for the executed request.
**Body** returns the raw response body as a byte slice.

```go title="Signature"
func (r *Response) Body() []byte
```

## String

String method returns the body of the server response as String.
**String** returns the response body as a trimmed string.

```go title="Signature"
func (r *Response) String() string
```

## JSON

JSON method will unmarshal body to json.
**JSON** unmarshals the response body into the provided variable `v` using JSON. `v` should be a pointer to a struct or a type compatible with JSON unmarshalling.

```go title="Signature"
func (r *Response) JSON(v any) error
Expand All @@ -222,14 +224,15 @@ if err != nil {
panic(err)
}

err = resp.JSON(&out)
if err != nil {
if err = resp.JSON(&out); err != nil {
panic(err)
}

fmt.Printf("%+v\n", out)
```

**Output:**

```text
{Slideshow:{Author:Yours Truly Date:date of publication Title:Sample Slide Show}}
```
Expand All @@ -238,39 +241,39 @@ fmt.Printf("%+v\n", out)

## XML

XML method will unmarshal body to xml.
**XML** unmarshals the response body into the provided variable `v` using XML decoding.

```go title="Signature"
func (r *Response) XML(v any) error
```

## CBOR

CBOR method will unmarshal body to CBOR.
**CBOR** unmarshals the response body into `v` using CBOR decoding.

```go title="Signature"
func (r *Response) CBOR(v any) error
```

## Save

Save method will save the body to a file or io.Writer.
**Save** writes the response body to a file or an `io.Writer`. If `v` is a string, it interprets it as a file path, creates the file (and directories if needed), and writes the response to it. If `v` is an `io.Writer`, it writes directly to it.

```go title="Signature"
func (r *Response) Save(v any) error
```

## Reset

Reset clears the Response object.
**Reset** clears the `Response` object, making it ready for reuse by `ReleaseResponse`.

```go title="Signature"
func (r *Response) Reset()
func (r *Response) Reset()
```

## Close

Close method will release the Request and Response objects; after calling Close, please do not use these objects.
**Close** releases both the associated `Request` and `Response` objects back to their pools. After calling `Close`, do not use the request or response.

```go title="Signature"
func (r *Response) Close()
Expand Down
Loading

0 comments on commit 3d23da2

Please sign in to comment.