Pull request: upd-websvc
Merge in DNS/adguard-home from upd-websvc to master Squashed commit of the following: commit 30d6a2dc5083efd91479bcbe20f03c37baddbf94 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Aug 9 18:55:42 2022 +0300 all: upd openapi, websvc
This commit is contained in:
parent
70f85fca21
commit
50565bed3b
|
@ -154,10 +154,13 @@ func GetValidNetInterfacesForWeb() (netIfaces []*NetInterface, err error) {
|
||||||
return netIfaces, nil
|
return netIfaces, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInterfaceByIP returns the name of interface containing provided ip.
|
// InterfaceByIP returns the name of the interface bound to ip.
|
||||||
//
|
//
|
||||||
// TODO(e.burkov): See TODO on GetValidInterfacesForWeb.
|
// TODO(a.garipov, e.burkov): This function is technically incorrect, since one
|
||||||
func GetInterfaceByIP(ip net.IP) string {
|
// IP address can be shared by multiple interfaces in some configurations.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): See TODO on GetValidNetInterfacesForWeb.
|
||||||
|
func InterfaceByIP(ip net.IP) (ifaceName string) {
|
||||||
ifaces, err := GetValidNetInterfacesForWeb()
|
ifaces, err := GetValidNetInterfacesForWeb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
@ -177,7 +180,7 @@ func GetInterfaceByIP(ip net.IP) string {
|
||||||
// GetSubnet returns pointer to net.IPNet for the specified interface or nil if
|
// GetSubnet returns pointer to net.IPNet for the specified interface or nil if
|
||||||
// the search fails.
|
// the search fails.
|
||||||
//
|
//
|
||||||
// TODO(e.burkov): See TODO on GetValidInterfacesForWeb.
|
// TODO(e.burkov): See TODO on GetValidNetInterfacesForWeb.
|
||||||
func GetSubnet(ifaceName string) *net.IPNet {
|
func GetSubnet(ifaceName string) *net.IPNet {
|
||||||
netIfaces, err := GetValidNetInterfacesForWeb()
|
netIfaces, err := GetValidNetInterfacesForWeb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -132,7 +132,7 @@ func TestGatewayIP(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInterfaceByIP(t *testing.T) {
|
func TestInterfaceByIP(t *testing.T) {
|
||||||
ifaces, err := GetValidNetInterfacesForWeb()
|
ifaces, err := GetValidNetInterfacesForWeb()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, ifaces)
|
require.NotEmpty(t, ifaces)
|
||||||
|
@ -142,7 +142,7 @@ func TestGetInterfaceByIP(t *testing.T) {
|
||||||
require.NotEmpty(t, iface.Addresses)
|
require.NotEmpty(t, iface.Addresses)
|
||||||
|
|
||||||
for _, ip := range iface.Addresses {
|
for _, ip := range iface.Addresses {
|
||||||
ifaceName := GetInterfaceByIP(ip)
|
ifaceName := InterfaceByIP(ip)
|
||||||
require.Equal(t, iface.Name, ifaceName)
|
require.Equal(t, iface.Name, ifaceName)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -216,7 +216,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request)
|
||||||
func handleStaticIP(ip net.IP, set bool) staticIPJSON {
|
func handleStaticIP(ip net.IP, set bool) staticIPJSON {
|
||||||
resp := staticIPJSON{}
|
resp := staticIPJSON{}
|
||||||
|
|
||||||
interfaceName := aghnet.GetInterfaceByIP(ip)
|
interfaceName := aghnet.InterfaceByIP(ip)
|
||||||
resp.Static = "no"
|
resp.Static = "no"
|
||||||
|
|
||||||
if len(interfaceName) == 0 {
|
if len(interfaceName) == 0 {
|
||||||
|
|
|
@ -8,12 +8,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/v1/websvc"
|
"github.com/AdguardTeam/AdGuardHome/internal/v1/websvc"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Main is the entry point of application.
|
// Main is the entry point of application.
|
||||||
|
@ -32,10 +31,7 @@ func Main(clientBuildFS fs.FS) {
|
||||||
|
|
||||||
// TODO(a.garipov): Make configurable.
|
// TODO(a.garipov): Make configurable.
|
||||||
web := websvc.New(&websvc.Config{
|
web := websvc.New(&websvc.Config{
|
||||||
Addresses: []*netutil.IPPort{{
|
Addresses: []netip.AddrPort{netip.MustParseAddrPort("127.0.0.1:3001")},
|
||||||
IP: net.IP{127, 0, 0, 1},
|
|
||||||
Port: 3001,
|
|
||||||
}},
|
|
||||||
Start: start,
|
Start: start,
|
||||||
Timeout: 60 * time.Second,
|
Timeout: 60 * time.Second,
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,13 +10,13 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/v1/agh"
|
"github.com/AdguardTeam/AdGuardHome/internal/v1/agh"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
httptreemux "github.com/dimfeld/httptreemux/v5"
|
httptreemux "github.com/dimfeld/httptreemux/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ type Config struct {
|
||||||
TLS *tls.Config
|
TLS *tls.Config
|
||||||
|
|
||||||
// Addresses are the addresses on which to serve the plain HTTP API.
|
// Addresses are the addresses on which to serve the plain HTTP API.
|
||||||
Addresses []*netutil.IPPort
|
Addresses []netip.AddrPort
|
||||||
|
|
||||||
// SecureAddresses are the addresses on which to serve the HTTPS API. If
|
// SecureAddresses are the addresses on which to serve the HTTPS API. If
|
||||||
// SecureAddresses is not empty, TLS must not be nil.
|
// SecureAddresses is not empty, TLS must not be nil.
|
||||||
SecureAddresses []*netutil.IPPort
|
SecureAddresses []netip.AddrPort
|
||||||
|
|
||||||
// Start is the time of start of AdGuard Home.
|
// Start is the time of start of AdGuard Home.
|
||||||
Start time.Time
|
Start time.Time
|
||||||
|
|
|
@ -3,14 +3,13 @@ package websvc_test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/v1/websvc"
|
"github.com/AdguardTeam/AdGuardHome/internal/v1/websvc"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -31,10 +30,7 @@ func newTestServer(t testing.TB) (svc *websvc.Service, addr string) {
|
||||||
|
|
||||||
c := &websvc.Config{
|
c := &websvc.Config{
|
||||||
TLS: nil,
|
TLS: nil,
|
||||||
Addresses: []*netutil.IPPort{{
|
Addresses: []netip.AddrPort{netip.MustParseAddrPort("127.0.0.1:0")},
|
||||||
IP: net.IP{127, 0, 0, 1},
|
|
||||||
Port: 0,
|
|
||||||
}},
|
|
||||||
SecureAddresses: nil,
|
SecureAddresses: nil,
|
||||||
Timeout: testTimeout,
|
Timeout: testTimeout,
|
||||||
Start: testStart,
|
Start: testStart,
|
||||||
|
|
121
openapi/v1.yaml
121
openapi/v1.yaml
|
@ -144,6 +144,13 @@
|
||||||
'/health-check':
|
'/health-check':
|
||||||
'get':
|
'get':
|
||||||
'operationId': 'HealthCheck'
|
'operationId': 'HealthCheck'
|
||||||
|
'responses':
|
||||||
|
'200':
|
||||||
|
'description': >
|
||||||
|
An OK response.
|
||||||
|
'content':
|
||||||
|
'text/plain':
|
||||||
|
'example': 'OK'
|
||||||
'servers':
|
'servers':
|
||||||
- 'url': '/'
|
- 'url': '/'
|
||||||
'summary': 'Check if the server is up.'
|
'summary': 'Check if the server is up.'
|
||||||
|
@ -874,6 +881,26 @@
|
||||||
'tags':
|
'tags':
|
||||||
- 'settings'
|
- 'settings'
|
||||||
|
|
||||||
|
'/settings/http':
|
||||||
|
'patch':
|
||||||
|
'operationId': 'PatchV1SettingsHttp'
|
||||||
|
'requestBody':
|
||||||
|
'$ref': '#/components/requestBodies/PatchV1SettingsHttpReq'
|
||||||
|
'responses':
|
||||||
|
'200':
|
||||||
|
'$ref': '#/components/responses/PatchV1SettingsHttpResp'
|
||||||
|
'400':
|
||||||
|
'$ref': '#/components/responses/BadRequestResp'
|
||||||
|
'401':
|
||||||
|
'$ref': '#/components/responses/UnauthorizedResp'
|
||||||
|
'422':
|
||||||
|
'$ref': '#/components/responses/UnprocessableEntityResp'
|
||||||
|
'500':
|
||||||
|
'$ref': '#/components/responses/InternalServerErrorResp'
|
||||||
|
'summary': 'Update web interface settings.'
|
||||||
|
'tags':
|
||||||
|
- 'settings'
|
||||||
|
|
||||||
'/settings/log':
|
'/settings/log':
|
||||||
'patch':
|
'patch':
|
||||||
'operationId': 'PatchV1SettingsLog'
|
'operationId': 'PatchV1SettingsLog'
|
||||||
|
@ -1209,6 +1236,13 @@
|
||||||
'$ref': '#/components/schemas/PatchV1SettingsDnsReq'
|
'$ref': '#/components/schemas/PatchV1SettingsDnsReq'
|
||||||
'required': true
|
'required': true
|
||||||
|
|
||||||
|
'PatchV1SettingsHttpReq':
|
||||||
|
'content':
|
||||||
|
'application/json':
|
||||||
|
'schema':
|
||||||
|
'$ref': '#/components/schemas/PatchV1SettingsHttpReq'
|
||||||
|
'required': true
|
||||||
|
|
||||||
'PatchV1SettingsLogReq':
|
'PatchV1SettingsLogReq':
|
||||||
'content':
|
'content':
|
||||||
'application/json':
|
'application/json':
|
||||||
|
@ -1604,6 +1638,14 @@
|
||||||
'description': >
|
'description': >
|
||||||
A successful response to a `PATCH /api/v1/settings/dns` request.
|
A successful response to a `PATCH /api/v1/settings/dns` request.
|
||||||
|
|
||||||
|
'PatchV1SettingsHttpResp':
|
||||||
|
'content':
|
||||||
|
'application/json':
|
||||||
|
'schema':
|
||||||
|
'$ref': '#/components/schemas/PatchV1SettingsHttpResp'
|
||||||
|
'description': >
|
||||||
|
A successful response to a `PATCH /api/v1/settings/http` request.
|
||||||
|
|
||||||
'PatchV1SettingsLogResp':
|
'PatchV1SettingsLogResp':
|
||||||
'content':
|
'content':
|
||||||
'application/json':
|
'application/json':
|
||||||
|
@ -2229,6 +2271,9 @@
|
||||||
- 'description': >
|
- 'description': >
|
||||||
DNS server settings.
|
DNS server settings.
|
||||||
'example':
|
'example':
|
||||||
|
'addresses':
|
||||||
|
- '127.0.0.1:53'
|
||||||
|
- '192.168.1.1:53'
|
||||||
'blocking_mode': 'default'
|
'blocking_mode': 'default'
|
||||||
'bootstrap_servers':
|
'bootstrap_servers':
|
||||||
- '9.9.9.10'
|
- '9.9.9.10'
|
||||||
|
@ -2244,7 +2289,9 @@
|
||||||
'upstream_servers':
|
'upstream_servers':
|
||||||
- '1.1.1.1'
|
- '1.1.1.1'
|
||||||
- '8.8.8.8'
|
- '8.8.8.8'
|
||||||
|
'upstream_timeout': '1s'
|
||||||
'required':
|
'required':
|
||||||
|
- 'addresses'
|
||||||
- 'blocking_mode'
|
- 'blocking_mode'
|
||||||
- 'bootstrap_servers'
|
- 'bootstrap_servers'
|
||||||
- 'cache_size'
|
- 'cache_size'
|
||||||
|
@ -2256,6 +2303,7 @@
|
||||||
- 'rate_limit'
|
- 'rate_limit'
|
||||||
- 'upstream_mode'
|
- 'upstream_mode'
|
||||||
- 'upstream_servers'
|
- 'upstream_servers'
|
||||||
|
- 'upstream_timeout'
|
||||||
|
|
||||||
'DnsSettingsPatch':
|
'DnsSettingsPatch':
|
||||||
'description': >
|
'description': >
|
||||||
|
@ -2265,6 +2313,13 @@
|
||||||
'upstream_servers':
|
'upstream_servers':
|
||||||
- '1.1.1.1'
|
- '1.1.1.1'
|
||||||
'properties':
|
'properties':
|
||||||
|
'addresses':
|
||||||
|
'description': >
|
||||||
|
Addresses on which to serve plain DNS, in ip:port format. Empty
|
||||||
|
array disables plain DNS.
|
||||||
|
'items':
|
||||||
|
'type': 'string'
|
||||||
|
'type': 'array'
|
||||||
'blocking_ipv4':
|
'blocking_ipv4':
|
||||||
'description': >
|
'description': >
|
||||||
IPv4 address to respond with when `blocking_mode` is `custom_ip`.
|
IPv4 address to respond with when `blocking_mode` is `custom_ip`.
|
||||||
|
@ -2340,6 +2395,10 @@
|
||||||
'items':
|
'items':
|
||||||
'$ref': '#/components/schemas/UpstreamServerAddr'
|
'$ref': '#/components/schemas/UpstreamServerAddr'
|
||||||
'type': 'array'
|
'type': 'array'
|
||||||
|
'upstream_timeout':
|
||||||
|
'description': >
|
||||||
|
Upstream request timeout, as a human readable duration.
|
||||||
|
'type': 'string'
|
||||||
'type': 'object'
|
'type': 'object'
|
||||||
|
|
||||||
'DnsType':
|
'DnsType':
|
||||||
|
@ -3038,6 +3097,8 @@
|
||||||
'$ref': '#/components/schemas/DhcpSettings'
|
'$ref': '#/components/schemas/DhcpSettings'
|
||||||
'dns':
|
'dns':
|
||||||
'$ref': '#/components/schemas/DnsSettings'
|
'$ref': '#/components/schemas/DnsSettings'
|
||||||
|
'http':
|
||||||
|
'$ref': '#/components/schemas/HttpSettings'
|
||||||
'log':
|
'log':
|
||||||
'$ref': '#/components/schemas/LogSettings'
|
'$ref': '#/components/schemas/LogSettings'
|
||||||
'protection':
|
'protection':
|
||||||
|
@ -3049,6 +3110,7 @@
|
||||||
'required':
|
'required':
|
||||||
- 'dhcp'
|
- 'dhcp'
|
||||||
- 'dns'
|
- 'dns'
|
||||||
|
- 'http'
|
||||||
- 'log'
|
- 'log'
|
||||||
- 'protection'
|
- 'protection'
|
||||||
- 'stats'
|
- 'stats'
|
||||||
|
@ -3432,6 +3494,53 @@
|
||||||
- 'version'
|
- 'version'
|
||||||
'type': 'object'
|
'type': 'object'
|
||||||
|
|
||||||
|
'HttpSettings':
|
||||||
|
'allOf':
|
||||||
|
- '$ref': '#/components/schemas/HttpSettingsPatch'
|
||||||
|
- 'description': >
|
||||||
|
HTTP interface server settings.
|
||||||
|
|
||||||
|
**TODO(a.garipov): Finish, split from TLS settings.**
|
||||||
|
'example':
|
||||||
|
'addresses':
|
||||||
|
- '127.0.0.1:80'
|
||||||
|
- '192.168.1.1:80'
|
||||||
|
'secure_addresses':
|
||||||
|
- '127.0.0.1:443'
|
||||||
|
- '192.168.1.1:443'
|
||||||
|
'force_https': true
|
||||||
|
'required':
|
||||||
|
- 'addresses'
|
||||||
|
- 'secure_addresses'
|
||||||
|
- 'force_https'
|
||||||
|
|
||||||
|
'HttpSettingsPatch':
|
||||||
|
'description': >
|
||||||
|
HTTP server settings update object.
|
||||||
|
'example':
|
||||||
|
'force_https': false
|
||||||
|
'properties':
|
||||||
|
'addresses':
|
||||||
|
'description': >
|
||||||
|
Addresses on which to serve the plain-HTTP web interface and API, in
|
||||||
|
ip:port format. Empty array disables the web interface over plain
|
||||||
|
HTTP.
|
||||||
|
'items':
|
||||||
|
'type': 'string'
|
||||||
|
'type': 'array'
|
||||||
|
'force_https':
|
||||||
|
'description': >
|
||||||
|
If `true`, enabled the HTTP-to-HTTPS redirect.
|
||||||
|
'type': 'boolean'
|
||||||
|
'secure_addresses':
|
||||||
|
'description': >
|
||||||
|
Addresses on which to serve the HTTPS web interface and API, in
|
||||||
|
ip:port format. Empty array disables the web interface over HTTPS.
|
||||||
|
'items':
|
||||||
|
'type': 'string'
|
||||||
|
'type': 'array'
|
||||||
|
'type': 'object'
|
||||||
|
|
||||||
'InternalServerErrorResp':
|
'InternalServerErrorResp':
|
||||||
'example':
|
'example':
|
||||||
'code': 'RNT000'
|
'code': 'RNT000'
|
||||||
|
@ -3725,6 +3834,12 @@
|
||||||
'PatchV1SettingsDnsResp':
|
'PatchV1SettingsDnsResp':
|
||||||
'$ref': '#/components/schemas/DnsSettings'
|
'$ref': '#/components/schemas/DnsSettings'
|
||||||
|
|
||||||
|
'PatchV1SettingsHttpReq':
|
||||||
|
'$ref': '#/components/schemas/HttpSettingsPatch'
|
||||||
|
|
||||||
|
'PatchV1SettingsHttpResp':
|
||||||
|
'$ref': '#/components/schemas/HttpSettings'
|
||||||
|
|
||||||
'PatchV1SettingsLogReq':
|
'PatchV1SettingsLogReq':
|
||||||
'$ref': '#/components/schemas/LogSettingsPatch'
|
'$ref': '#/components/schemas/LogSettingsPatch'
|
||||||
|
|
||||||
|
@ -4750,7 +4865,6 @@
|
||||||
'example':
|
'example':
|
||||||
'certificate_path': '/etc/ssl/example.com.cert'
|
'certificate_path': '/etc/ssl/example.com.cert'
|
||||||
'enabled': true
|
'enabled': true
|
||||||
'force_https': true
|
|
||||||
'port_dns_over_quic': 784
|
'port_dns_over_quic': 784
|
||||||
'port_dns_over_tls': 853
|
'port_dns_over_tls': 853
|
||||||
'port_https': 443
|
'port_https': 443
|
||||||
|
@ -4758,7 +4872,6 @@
|
||||||
'server_name': 'dns.example.com'
|
'server_name': 'dns.example.com'
|
||||||
'required':
|
'required':
|
||||||
- 'enabled'
|
- 'enabled'
|
||||||
- 'force_https'
|
|
||||||
- 'port_dns_over_quic'
|
- 'port_dns_over_quic'
|
||||||
- 'port_dns_over_tls'
|
- 'port_dns_over_tls'
|
||||||
- 'port_https'
|
- 'port_https'
|
||||||
|
@ -4793,10 +4906,6 @@
|
||||||
over HTTPS, and the DNS server will listen requests over
|
over HTTPS, and the DNS server will listen requests over
|
||||||
DNS-over-TLS and other protocols.
|
DNS-over-TLS and other protocols.
|
||||||
'type': 'boolean'
|
'type': 'boolean'
|
||||||
'force_https':
|
|
||||||
'description': >
|
|
||||||
If `true`, enabled the HTTP-to-HTTPS redirect.
|
|
||||||
'type': 'boolean'
|
|
||||||
'port_dns_over_quic':
|
'port_dns_over_quic':
|
||||||
'default': 784
|
'default': 784
|
||||||
'description': >
|
'description': >
|
||||||
|
|
Loading…
Reference in New Issue