1
0
mirror of https://github.com/ggicci/httpin.git synced 2024-11-24 08:32:45 +02:00

Add runable examples

This commit is contained in:
Ggicci 2023-12-31 02:41:21 -05:00
parent d9e91d36ab
commit 1d9eff5f64
3 changed files with 164 additions and 10 deletions

View File

@ -123,6 +123,58 @@ input: &main.UpdateUserInput{
**body** will encode the corresponding field of the struct into the body of the response, in `BODY_TYPE` format.
### Runable Example
<GoPlay>
```go
package main
import (
"fmt"
"net/http/httputil"
"github.com/ggicci/httpin"
)
type UserPatch struct {
Display string `json:"display"`
Email string `json:"email"`
IsAdmin bool `json:"is_admin"`
}
type UpdateUserInput struct {
ID string `in:"path=id"`
Payload UserPatch `in:"body=json"`
}
func main() {
input := &UpdateUserInput{
ID: "ggicci",
Payload: UserPatch{
Display: "Ggicci",
Email: "secret_@xxx.com",
IsAdmin: true,
},
}
r, _ := httpin.NewRequest("PATCH", "/users/{id}", input)
data, _ := httputil.DumpRequest(r, true)
fmt.Printf("%s\n", data)
}
```
</GoPlay>
Output:
```text
PATCH /users/ggicci HTTP/1.1
Content-Type: application/json
{"display":"Ggicci","email":"secret_@xxx.com","is_admin":true}
```
## Custom Body Format
Call [`RegisterBodyFormat`](https://pkg.go.dev/github.com/ggicci/httpin#RegisterBodyFormat) to register a new body format/serializer to **httpin**.

View File

@ -2,6 +2,7 @@
sidebar_position: 98
---
import GoPlay from "../../src/components/GoPlay"
import InputOutputTable from "../../src/components/InputOutputTable"
import data from "./data/default"
@ -52,26 +53,119 @@ type ListTasksQuery struct {
></InputOutputTable>
### Runable Example
<GoPlay>
```go
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/ggicci/httpin"
"github.com/go-chi/chi/v5"
)
type ListTasksQuery struct {
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
StateList []string `in:"query=state;default=pending,running"`
}
func ListTasks(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListTasksQuery)
fmt.Printf("input: %#v\n", input)
}
func main() {
router := chi.NewRouter()
router.With(
httpin.NewInput(ListTasksQuery{}),
).Get("/tasks", ListTasks)
r, _ := http.NewRequest("GET", "/tasks?page=0", nil)
rw := httptest.NewRecorder()
router.ServeHTTP(rw, r)
}
```
</GoPlay>
Output:
```text
input: &main.ListTasksQuery{Page:0, PerPage:20, StateList:[]string{"pending", "running"}}
```
## Encoding
**default** will examine if the field is a zero value. If so, it will set the field to the given value.
:::caution
:::note
Since httpin runs the directives in the order of their appearance in the struct,
Since **httpin** runs the directives in the order of their appearance in the struct,
you should **always** define the order of the directives based on decoding
requirements, **default** should be placed after directives like
[query](/directives/query) and [path](/directives/path) that set the field
values. In order to make it also works for encoding, httpin will reorder the
directives internally while encoding. The **default** directive will be placed
at the beginning of the reordered directives. For example, the above struct will be reordered to:
values.
```
In order to make it works for encoding as well, **httpin** will reorder the
directives internally for encoding. The final order of directives will be:
1. [required](/directives/required)
2. [default](/directives/default)
3. other directives
For example, the above struct will be reordered to:
```go
type ListTasksQuery struct {
Page int `in:"default=1;query=page"`
PerPage int `in:"default=20;query=per_page"`
}
```
:::
:::
### Runable Example
<GoPlay>
```go
package main
import (
"fmt"
"net/http/httputil"
"github.com/ggicci/httpin"
)
type ListTasksQuery struct {
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
StateList []string `in:"query=state;default=pending,running"`
}
func main() {
input := &ListTasksQuery{Page: 3}
r, _ := httpin.NewRequest("GET", "/tasks", input)
data, _ := httputil.DumpRequest(r, true)
fmt.Printf("%s\n", data)
}
```
</GoPlay>
Output:
```text
GET /tasks?page=3&per_page=20&state=pending&state=running HTTP/1.1
```

View File

@ -8,11 +8,19 @@ sidebar_position: 5
:::danger
**httpin** doesn't provide a builtin **path** directive, because **httpin** doesn't provide routing functionality.
But **httpin** can be easily integrated with other packages that provide routing functionality, to decode path variables.
**httpin** has registered a **path** directive by default. However, it only
supports the encoding. An error will be returned if you try to decode some
structs with **path** directives.
Q: Why we don't support decoding of path variables by default?
A: Because the decoding of path variables relys on the routing functionality of the web framework you are using. It cannot be done by **httpin** alone.
Even though, **httpin** can be easily integrated with other packages that provide routing functionality, to decode path variables. See below for more details.
:::
You can quickly implement a **path** directive with the following code (routing package specific):
- go-chi/chi
@ -35,7 +43,7 @@ func init() {
}
```
Please visit the **Integrations** section on the left sidebar to find more details on how to integrate **httpin** with other packages.
See **Integrations** section on the menu left to learn more details and examples on how to integrate **httpin** with other packages.
If you can't find the package you wanted on the list, you could either open an issue on the [**Github**](https://github.com/ggicci/httpin/issues)
or visit [Custom 🔌](/directives/custom) to learn to implement a "path" directive of your own.