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:
parent
d9e91d36ab
commit
1d9eff5f64
@ -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**.
|
||||
|
@ -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,22 +53,78 @@ 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"`
|
||||
@ -75,3 +132,40 @@ type ListTasksQuery struct {
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
### 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
|
||||
```
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user