mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 20:52:33 +02:00
Update documentation for Docker labels and middlewares, now fields works for snake cases, camel cases, pascal cases
This commit is contained in:
parent
a935f200a3
commit
6f3a5ebe6e
7 changed files with 296 additions and 45 deletions
|
@ -62,10 +62,12 @@
|
||||||
|
|
||||||
## Labels
|
## Labels
|
||||||
|
|
||||||
|
**Parts surrounded by `[]` are optional**
|
||||||
|
|
||||||
### Syntax
|
### Syntax
|
||||||
|
|
||||||
| Label | Description | Example | Default | Accepted values |
|
| Label | Description | Example | Default | Accepted values |
|
||||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --------------------------- | ------------------------------------------------------------------------- |
|
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------------------- |
|
||||||
| `proxy.aliases` | comma separated aliases for subdomain and label matching | `gitlab,gitlab-reg,gitlab-ssh` | `container_name` | any |
|
| `proxy.aliases` | comma separated aliases for subdomain and label matching | `gitlab,gitlab-reg,gitlab-ssh` | `container_name` | any |
|
||||||
| `proxy.exclude` | to be excluded from `go-proxy` | | false | boolean |
|
| `proxy.exclude` | to be excluded from `go-proxy` | | false | boolean |
|
||||||
| `proxy.idle_timeout` | time for idle (no traffic) before put it into sleep **(http/s only)**<br> _**NOTE: idlewatcher will only be enabled containers that has non-empty `idle_timeout`**_ | `1h` | empty or `0` **(disabled)** | `number[unit]...`, e.g. `1m30s` |
|
| `proxy.idle_timeout` | time for idle (no traffic) before put it into sleep **(http/s only)**<br> _**NOTE: idlewatcher will only be enabled containers that has non-empty `idle_timeout`**_ | `1h` | empty or `0` **(disabled)** | `number[unit]...`, e.g. `1m30s` |
|
||||||
|
@ -76,6 +78,7 @@
|
||||||
| `proxy.<alias>.<field>` | set field for specific alias | `proxy.gitlab-ssh.scheme` | N/A | N/A |
|
| `proxy.<alias>.<field>` | set field for specific alias | `proxy.gitlab-ssh.scheme` | N/A | N/A |
|
||||||
| `proxy.#<index>.<field>` | set field for specific alias at index (starting from **1**) | `proxy.#3.port` | N/A | N/A |
|
| `proxy.#<index>.<field>` | set field for specific alias at index (starting from **1**) | `proxy.#3.port` | N/A | N/A |
|
||||||
| `proxy.*.<field>` | set field for all aliases | `proxy.*.set_headers` | N/A | N/A |
|
| `proxy.*.<field>` | set field for all aliases | `proxy.*.set_headers` | N/A | N/A |
|
||||||
|
| `proxy.?.middlewares.<middleware>[.<field>]` | enable and set field for specific middleware | **?** here means `<alias>` / `$<index>` / `*` <ul><li>`proxy.#1.middlewares.modify_request.set_headers`</li><li>`proxy.*.middlewares.modify_response.hide_headers`</li><li>`proxy.app1.middlewares.redirect_http`</li></ul> | N/A | Middleware specific<br>See [middlewares.md](middlewares.md) for more |
|
||||||
|
|
||||||
### Fields
|
### Fields
|
||||||
|
|
||||||
|
@ -87,8 +90,7 @@
|
||||||
| `port` | proxy port **(tcp/udp)** | `0:first_port` | `x:y` <br><ul><li>**x**: port for `go-proxy` to listen on.<br>**x** can be 0, which means listen on a random port</li><li>**y**: port or [_service name_](../src/common/constants.go#L55) of target container</li></ul> |
|
| `port` | proxy port **(tcp/udp)** | `0:first_port` | `x:y` <br><ul><li>**x**: port for `go-proxy` to listen on.<br>**x** can be 0, which means listen on a random port</li><li>**y**: port or [_service name_](../src/common/constants.go#L55) of target container</li></ul> |
|
||||||
| `no_tls_verify` | whether skip tls verify **(https only)** | `false` | boolean |
|
| `no_tls_verify` | whether skip tls verify **(https only)** | `false` | boolean |
|
||||||
| `path_patterns` | proxy path patterns **(http/s only)**<br> only requests that matched a pattern will be proxied | `/` **(proxy all requests)** | yaml style list[<sup>1</sup>](#list-example) of ([path patterns](https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)) |
|
| `path_patterns` | proxy path patterns **(http/s only)**<br> only requests that matched a pattern will be proxied | `/` **(proxy all requests)** | yaml style list[<sup>1</sup>](#list-example) of ([path patterns](https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)) |
|
||||||
| `set_headers` | header to set **(http/s only)** | empty | yaml style key-value mapping[<sup>2</sup>](#key-value-mapping-example) of header-value pairs |
|
|
||||||
| `hide_headers` | header to hide **(http/s only)** | empty | yaml style list[<sup>1</sup>](#list-example) of headers |
|
|
||||||
|
|
||||||
[🔼Back to top](#table-of-content)
|
[🔼Back to top](#table-of-content)
|
||||||
|
|
||||||
|
@ -101,12 +103,9 @@ services:
|
||||||
nginx:
|
nginx:
|
||||||
...
|
...
|
||||||
labels:
|
labels:
|
||||||
# values from duplicated header keys will be combined
|
proxy.nginx.middlewares.modify_request.set_headers: | # remember to add the '|'
|
||||||
proxy.nginx.set_headers: | # remember to add the '|'
|
|
||||||
X-Custom-Header1: value1, value2
|
X-Custom-Header1: value1, value2
|
||||||
X-Custom-Header2: value3
|
X-Custom-Header2: value3, value4
|
||||||
X-Custom-Header2: value4
|
|
||||||
# X-Custom-Header2 will be "value3, value4"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
File Provider
|
File Provider
|
||||||
|
@ -114,8 +113,9 @@ File Provider
|
||||||
```yaml
|
```yaml
|
||||||
service_a:
|
service_a:
|
||||||
host: service_a.internal
|
host: service_a.internal
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
set_headers:
|
set_headers:
|
||||||
# do not duplicate header keys, as it is not allowed in YAML
|
|
||||||
X-Custom-Header1: value1, value2
|
X-Custom-Header1: value1, value2
|
||||||
X-Custom-Header2: value3
|
X-Custom-Header2: value3
|
||||||
```
|
```
|
||||||
|
@ -134,12 +134,12 @@ services:
|
||||||
proxy.nginx.path_patterns: | # remember to add the '|'
|
proxy.nginx.path_patterns: | # remember to add the '|'
|
||||||
- GET /
|
- GET /
|
||||||
- POST /auth
|
- POST /auth
|
||||||
proxy.nginx.hide_headers: | # remember to add the '|'
|
proxy.nginx.middlewares.modify_request.hide_headers: | # remember to add the '|'
|
||||||
- X-Custom-Header1
|
- X-Custom-Header1
|
||||||
- X-Custom-Header2
|
- X-Custom-Header2
|
||||||
```
|
```
|
||||||
|
|
||||||
File Provider
|
Include file
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
service_a:
|
service_a:
|
||||||
|
@ -147,6 +147,8 @@ service_a:
|
||||||
path_patterns:
|
path_patterns:
|
||||||
- GET /
|
- GET /
|
||||||
- POST /auth
|
- POST /auth
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
hide_headers:
|
hide_headers:
|
||||||
- X-Custom-Header1
|
- X-Custom-Header1
|
||||||
- X-Custom-Header2
|
- X-Custom-Header2
|
||||||
|
@ -209,10 +211,10 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
labels:
|
labels:
|
||||||
- proxy.aliases=adg,adg-dns,adg-setup
|
- proxy.aliases=adg,adg-dns,adg-setup
|
||||||
- proxy.$1.port=80
|
- proxy.#1.port=80
|
||||||
- proxy.$2.scheme=udp
|
- proxy.#2.scheme=udp
|
||||||
- proxy.$2.port=20000:dns
|
- proxy.#2.port=20000:dns
|
||||||
- proxy.$3.port=3000
|
- proxy.#3.port=3000
|
||||||
volumes:
|
volumes:
|
||||||
- adg-work:/opt/adguardhome/work
|
- adg-work:/opt/adguardhome/work
|
||||||
- adg-conf:/opt/adguardhome/conf
|
- adg-conf:/opt/adguardhome/conf
|
||||||
|
@ -245,8 +247,8 @@ services:
|
||||||
labels:
|
labels:
|
||||||
- proxy.aliases=pal1,pal2
|
- proxy.aliases=pal1,pal2
|
||||||
- proxy.*.scheme=udp
|
- proxy.*.scheme=udp
|
||||||
- proxy.$1.port=20002:8211
|
- proxy.#1.port=20002:8211
|
||||||
- proxy.$2.port=20003:27015
|
- proxy.#2.port=20003:27015
|
||||||
environment: ...
|
environment: ...
|
||||||
volumes:
|
volumes:
|
||||||
- palworld:/palworld
|
- palworld:/palworld
|
||||||
|
|
245
docs/middlewares.md
Normal file
245
docs/middlewares.md
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
# Middlewares
|
||||||
|
|
||||||
|
## Table of content
|
||||||
|
|
||||||
|
<!-- TOC -->
|
||||||
|
|
||||||
|
- [Middlewares](#middlewares)
|
||||||
|
- [Table of content](#table-of-content)
|
||||||
|
- [Available middlewares](#available-middlewares)
|
||||||
|
- [Redirect http](#redirect-http)
|
||||||
|
- [Modify request or response](#modify-request-or-response)
|
||||||
|
- [Set headers](#set-headers)
|
||||||
|
- [Add headers](#add-headers)
|
||||||
|
- [Hide headers](#hide-headers)
|
||||||
|
- [X-Forwarded-\* Headers](#x-forwarded--headers)
|
||||||
|
- [Add X-Forwarded-\*](#add-x-forwarded-)
|
||||||
|
- [Set X-Forwarded-\*](#set-x-forwarded-)
|
||||||
|
- [Forward Authorization header (experimental)](#forward-authorization-header-experimental)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Authentik](#authentik)
|
||||||
|
|
||||||
|
<!-- TOC -->
|
||||||
|
|
||||||
|
## Available middlewares
|
||||||
|
|
||||||
|
### Redirect http
|
||||||
|
|
||||||
|
Redirect http requests to https
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.redirect_http:
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
redirect_http:
|
||||||
|
```
|
||||||
|
|
||||||
|
nginx equivalent:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name domain.tld;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[🔼Back to top](#table-of-content)
|
||||||
|
|
||||||
|
### Modify request or response
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.field:
|
||||||
|
proxy.app1.middlewares.modify_response.field:
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
field:
|
||||||
|
modify_response:
|
||||||
|
field:
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Set headers
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.set_headers: |
|
||||||
|
X-Custom-Header1: value1, value2
|
||||||
|
X-Custom-Header2: value3
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
set_headers:
|
||||||
|
X-Custom-Header1: value1, value2
|
||||||
|
X-Custom-Header2: value3
|
||||||
|
```
|
||||||
|
|
||||||
|
nginx equivalent:
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
add_header X-Custom-Header1 value1, value2;
|
||||||
|
add_header X-Custom-Header2 value3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add headers
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.add_headers: |
|
||||||
|
X-Custom-Header1: value1, value2
|
||||||
|
X-Custom-Header2: value3
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
add_headers:
|
||||||
|
X-Custom-Header1: value1, value2
|
||||||
|
X-Custom-Header2: value3
|
||||||
|
```
|
||||||
|
|
||||||
|
nginx equivalent:
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
more_set_headers "X-Custom-Header1: value1, value2";
|
||||||
|
more_set_headers "X-Custom-Header2: value3";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Hide headers
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.hide_headers: |
|
||||||
|
- X-Custom-Header1
|
||||||
|
- X-Custom-Header2
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
hide_headers:
|
||||||
|
- X-Custom-Header1
|
||||||
|
- X-Custom-Header2
|
||||||
|
```
|
||||||
|
|
||||||
|
nginx equivalent:
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
more_clear_headers "X-Custom-Header1";
|
||||||
|
more_clear_headers "X-Custom-Header2";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### X-Forwarded-* Headers
|
||||||
|
|
||||||
|
#### Add X-Forwarded-*
|
||||||
|
|
||||||
|
Append `X-Forwarded-*` headers to existing headers
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.add_x_forwarded:
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
add_x_forwarded:
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Set X-Forwarded-*
|
||||||
|
|
||||||
|
Replace existing `X-Forwarded-*` headers with `go-proxy` provided headers
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.modify_request.set_x_forwarded:
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
modify_request:
|
||||||
|
set_x_forwarded:
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forward Authorization header (experimental)
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
- `address`: authentication provider URL _(required)_
|
||||||
|
- `trust_forward_header`: whether to trust `X-Forwarded-*` headers from upstream proxies _(default: `false`)_
|
||||||
|
- `auth_response_headers`: list of headers to copy from auth response _(default: empty)_
|
||||||
|
- `add_auth_cookies_to_response`: list of cookies to add to response _(default: empty)_
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
proxy.app1.middlewares.forward_auth.address: https://auth.example.com
|
||||||
|
proxy.app1.middlewares.forward_auth.trust_forward_header: true
|
||||||
|
proxy.app1.middlewares.forward_auth.auth_response_headers: |
|
||||||
|
- X-Auth-Token
|
||||||
|
- X-Auth-User
|
||||||
|
proxy.app1.middlewares.forward_auth.add_auth_cookies_to_response: |
|
||||||
|
- uid
|
||||||
|
- session_id
|
||||||
|
|
||||||
|
# include file
|
||||||
|
app1:
|
||||||
|
middlewares:
|
||||||
|
forward_authorization:
|
||||||
|
address: https://auth.example.com
|
||||||
|
trust_forward_header: true
|
||||||
|
auth_response_headers:
|
||||||
|
- X-Auth-Token
|
||||||
|
- X-Auth-User
|
||||||
|
add_auth_cookies_to_response:
|
||||||
|
- uid
|
||||||
|
- session_id
|
||||||
|
```
|
||||||
|
|
||||||
|
Traefik equivalent:
|
||||||
|
```yaml
|
||||||
|
# docker labels
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.address: https://auth.example.com
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-Auth-Token, X-Auth-User
|
||||||
|
traefik.http.middlewares.authentik.forwardauth.addAuthCookiesToResponse: uid, session_id
|
||||||
|
|
||||||
|
# standalone
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
forwardAuth:
|
||||||
|
address: https://auth.example.com
|
||||||
|
trustForwardHeader: true
|
||||||
|
authResponseHeaders:
|
||||||
|
- X-Auth-Token
|
||||||
|
- X-Auth-User
|
||||||
|
addAuthCookiesToResponse:
|
||||||
|
- uid
|
||||||
|
- session_id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Authentik
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker compose
|
||||||
|
services:
|
||||||
|
...
|
||||||
|
server:
|
||||||
|
...
|
||||||
|
container_name: authentik
|
||||||
|
labels:
|
||||||
|
proxy.authentik.middlewares.redirect_http:
|
||||||
|
proxy.authentik.middlewares.set_x_forwarded:
|
||||||
|
proxy.authentik.middlewares.modify_request.add_headers: |
|
||||||
|
Strict-Transport-Security: "max-age=63072000" always
|
||||||
|
```
|
|
@ -59,8 +59,8 @@ var (
|
||||||
"nginx-proxy-manager": 81,
|
"nginx-proxy-manager": 81,
|
||||||
"open-webui": 8080,
|
"open-webui": 8080,
|
||||||
"plex": 32400,
|
"plex": 32400,
|
||||||
"portainer": 9000,
|
"portainer-be": 9443,
|
||||||
"portainer-ce": 9000,
|
"portainer-ce": 9443,
|
||||||
"prometheus": 9090,
|
"prometheus": 9090,
|
||||||
"prowlarr": 9696,
|
"prowlarr": 9696,
|
||||||
"radarr": 7878,
|
"radarr": 7878,
|
||||||
|
|
|
@ -108,12 +108,12 @@ func ParseLabel(label string, value string) (*Label, E.NestedError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// find if namespace has value parser
|
// find if namespace has value parser
|
||||||
pm, ok := valueParserMap.Load(l.Namespace)
|
pm, ok := valueParserMap.Load(U.ToLowerNoSnake(l.Namespace))
|
||||||
if !ok {
|
if !ok {
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
// find if attribute has value parser
|
// find if attribute has value parser
|
||||||
p, ok := pm[l.Attribute]
|
p, ok := pm[U.ToLowerNoSnake(l.Attribute)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,11 @@ func ParseLabel(label string, value string) (*Label, E.NestedError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterNamespace(namespace string, pm ValueParserMap) {
|
func RegisterNamespace(namespace string, pm ValueParserMap) {
|
||||||
valueParserMap.Store(namespace, pm)
|
pmCleaned := make(ValueParserMap, len(pm))
|
||||||
|
for k, v := range pm {
|
||||||
|
pmCleaned[U.ToLowerNoSnake(k)] = v
|
||||||
|
}
|
||||||
|
valueParserMap.Store(U.ToLowerNoSnake(namespace), pmCleaned)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRegisteredNamespaces() map[string][]string {
|
func GetRegisteredNamespaces() map[string][]string {
|
||||||
|
|
|
@ -49,7 +49,7 @@ func YamlLikeMappingParser(allowDuplicate bool) func(string) (any, E.NestedError
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
parts := strings.SplitN(line, ":", 2)
|
parts := strings.SplitN(line, ":", 2)
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return nil, E.Invalid("syntax", line)
|
return nil, E.Invalid("syntax", line).With("too many colons")
|
||||||
}
|
}
|
||||||
key := strings.TrimSpace(parts[0])
|
key := strings.TrimSpace(parts[0])
|
||||||
val := strings.TrimSpace(parts[1])
|
val := strings.TrimSpace(parts[1])
|
||||||
|
|
|
@ -74,7 +74,7 @@ func newForwardAuth() (fa *forwardAuth) {
|
||||||
}
|
}
|
||||||
faWithOpts.m = &Middleware{
|
faWithOpts.m = &Middleware{
|
||||||
impl: faWithOpts,
|
impl: faWithOpts,
|
||||||
before: fa.forward,
|
before: faWithOpts.forward,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := U.Deserialize(optsRaw, faWithOpts.forwardAuthOpts)
|
err := U.Deserialize(optsRaw, faWithOpts.forwardAuthOpts)
|
||||||
|
|
|
@ -108,13 +108,13 @@ func Serialize(data any) (SerializedObject, E.NestedError) {
|
||||||
|
|
||||||
func Deserialize(src SerializedObject, target any) E.NestedError {
|
func Deserialize(src SerializedObject, target any) E.NestedError {
|
||||||
// convert data fields to lower no-snake
|
// convert data fields to lower no-snake
|
||||||
// convert target fields to lower
|
// convert target fields to lower no-snake
|
||||||
// then check if the field of data is in the target
|
// then check if the field of data is in the target
|
||||||
mapping := make(map[string]string)
|
mapping := make(map[string]string)
|
||||||
t := reflect.TypeOf(target).Elem()
|
t := reflect.TypeOf(target).Elem()
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
snakeCaseField := strings.ToLower(field.Name)
|
snakeCaseField := ToLowerNoSnake(field.Name)
|
||||||
mapping[snakeCaseField] = field.Name
|
mapping[snakeCaseField] = field.Name
|
||||||
}
|
}
|
||||||
tValue := reflect.ValueOf(target)
|
tValue := reflect.ValueOf(target)
|
||||||
|
@ -122,7 +122,7 @@ func Deserialize(src SerializedObject, target any) E.NestedError {
|
||||||
return E.Invalid("value", "nil")
|
return E.Invalid("value", "nil")
|
||||||
}
|
}
|
||||||
for k, v := range src {
|
for k, v := range src {
|
||||||
kCleaned := toLowerNoSnake(k)
|
kCleaned := ToLowerNoSnake(k)
|
||||||
if fieldName, ok := mapping[kCleaned]; ok {
|
if fieldName, ok := mapping[kCleaned]; ok {
|
||||||
prop := reflect.ValueOf(target).Elem().FieldByName(fieldName)
|
prop := reflect.ValueOf(target).Elem().FieldByName(fieldName)
|
||||||
propType := prop.Type()
|
propType := prop.Type()
|
||||||
|
@ -175,7 +175,7 @@ func DeserializeJson(j map[string]string, target any) E.NestedError {
|
||||||
return E.From(json.Unmarshal(data, target))
|
return E.From(json.Unmarshal(data, target))
|
||||||
}
|
}
|
||||||
|
|
||||||
func toLowerNoSnake(s string) string {
|
func ToLowerNoSnake(s string) string {
|
||||||
return strings.ToLower(strings.ReplaceAll(s, "_", ""))
|
return strings.ToLower(strings.ReplaceAll(s, "_", ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue