feat: add support for proxies to use with IRC and Indexers (#1421)

* feat: add support for proxies

* fix(http): release handler

* fix(migrations): define proxy early

* fix(migrations): pg proxy

* fix(proxy): list update delete

* fix(proxy): remove log and imports

* feat(irc): use proxy

* feat(irc): tests

* fix(web): update imports for ProxyForms.tsx

* fix(database): migration

* feat(proxy): test

* feat(proxy): validate proxy type

* feat(proxy): validate and test

* feat(proxy): improve validate and test

* feat(proxy): fix db schema

* feat(proxy): add db tests

* feat(proxy): handle http errors

* fix(http): imports

* feat(proxy): use proxy for indexer downloads

* feat(proxy): indexerforms select proxy

* feat(proxy): handle torrent download

* feat(proxy): skip if disabled

* feat(proxy): imports

* feat(proxy): implement in Feeds

* feat(proxy): update helper text indexer proxy

* feat(proxy): add internal cache
This commit is contained in:
ze0s 2024-09-02 11:10:45 +02:00 committed by GitHub
parent 472d327308
commit bc0f4cc055
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 2533 additions and 371 deletions

View file

@ -6,11 +6,11 @@ package http
import (
"context"
"encoding/json"
"github.com/autobrr/autobrr/pkg/errors"
"net/http"
"strconv"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/go-chi/chi/v5"
)

View file

@ -7,12 +7,12 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/autobrr/autobrr/pkg/errors"
"net/http"
"strconv"
"strings"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/go-chi/chi/v5"
"github.com/r3labs/sse/v2"

View file

@ -6,11 +6,11 @@ package http
import (
"context"
"encoding/json"
"github.com/autobrr/autobrr/pkg/errors"
"net/http"
"strconv"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/go-chi/chi/v5"
)

151
internal/http/proxy.go Normal file
View file

@ -0,0 +1,151 @@
// Copyright (c) 2021 - 2024, Ludvig Lundgren and the autobrr contributors.
// SPDX-License-Identifier: GPL-2.0-or-later
package http
import (
"context"
"encoding/json"
"net/http"
"strconv"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/go-chi/chi/v5"
)
type proxyService interface {
Store(ctx context.Context, p *domain.Proxy) error
Update(ctx context.Context, p *domain.Proxy) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context) ([]domain.Proxy, error)
FindByID(ctx context.Context, id int64) (*domain.Proxy, error)
Test(ctx context.Context, p *domain.Proxy) error
}
type proxyHandler struct {
encoder encoder
service proxyService
}
func newProxyHandler(encoder encoder, service proxyService) *proxyHandler {
return &proxyHandler{
encoder: encoder,
service: service,
}
}
func (h proxyHandler) Routes(r chi.Router) {
r.Get("/", h.list)
r.Post("/", h.store)
r.Post("/test", h.test)
r.Route("/{proxyID}", func(r chi.Router) {
r.Get("/", h.findByID)
r.Put("/", h.update)
r.Delete("/", h.delete)
})
}
func (h proxyHandler) store(w http.ResponseWriter, r *http.Request) {
var data domain.Proxy
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
h.encoder.Error(w, err)
return
}
if err := h.service.Store(r.Context(), &data); err != nil {
h.encoder.Error(w, err)
return
}
h.encoder.NoContent(w)
}
func (h proxyHandler) update(w http.ResponseWriter, r *http.Request) {
var data domain.Proxy
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
h.encoder.Error(w, err)
return
}
if err := h.service.Update(r.Context(), &data); err != nil {
if errors.Is(err, domain.ErrUpdateFailed) {
h.encoder.StatusError(w, http.StatusBadRequest, err)
return
}
h.encoder.Error(w, err)
return
}
h.encoder.NoContent(w)
}
func (h proxyHandler) list(w http.ResponseWriter, r *http.Request) {
proxies, err := h.service.List(r.Context())
if err != nil {
h.encoder.Error(w, err)
return
}
h.encoder.StatusResponse(w, http.StatusOK, proxies)
}
func (h proxyHandler) findByID(w http.ResponseWriter, r *http.Request) {
proxyID, err := strconv.Atoi(chi.URLParam(r, "proxyID"))
if err != nil {
h.encoder.Error(w, err)
return
}
proxies, err := h.service.FindByID(r.Context(), int64(proxyID))
if err != nil {
if errors.Is(err, domain.ErrRecordNotFound) {
h.encoder.NotFoundErr(w, errors.New("could not find proxy with id %d", proxyID))
return
}
h.encoder.Error(w, err)
return
}
h.encoder.StatusResponse(w, http.StatusOK, proxies)
}
func (h proxyHandler) delete(w http.ResponseWriter, r *http.Request) {
proxyID, err := strconv.Atoi(chi.URLParam(r, "proxyID"))
if err != nil {
h.encoder.Error(w, err)
return
}
err = h.service.Delete(r.Context(), int64(proxyID))
if err != nil {
if errors.Is(err, domain.ErrDeleteFailed) {
h.encoder.StatusError(w, http.StatusBadRequest, err)
return
}
h.encoder.Error(w, err)
return
}
h.encoder.NoContent(w)
}
func (h proxyHandler) test(w http.ResponseWriter, r *http.Request) {
var data domain.Proxy
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
h.encoder.Error(w, err)
return
}
if err := h.service.Test(r.Context(), &data); err != nil {
h.encoder.Error(w, err)
return
}
h.encoder.NoContent(w)
}

View file

@ -43,11 +43,12 @@ type Server struct {
indexerService indexerService
ircService ircService
notificationService notificationService
proxyService proxyService
releaseService releaseService
updateService updateService
}
func NewServer(log logger.Logger, config *config.AppConfig, sse *sse.Server, db *database.DB, version string, commit string, date string, actionService actionService, apiService apikeyService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, feedSvc feedService, indexerSvc indexerService, ircSvc ircService, notificationSvc notificationService, releaseSvc releaseService, updateSvc updateService) Server {
func NewServer(log logger.Logger, config *config.AppConfig, sse *sse.Server, db *database.DB, version string, commit string, date string, actionService actionService, apiService apikeyService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, feedSvc feedService, indexerSvc indexerService, ircSvc ircService, notificationSvc notificationService, proxySvc proxyService, releaseSvc releaseService, updateSvc updateService) Server {
return Server{
log: log.With().Str("module", "http").Logger(),
config: config,
@ -68,6 +69,7 @@ func NewServer(log logger.Logger, config *config.AppConfig, sse *sse.Server, db
indexerService: indexerSvc,
ircService: ircSvc,
notificationService: notificationSvc,
proxyService: proxySvc,
releaseService: releaseSvc,
updateService: updateSvc,
}
@ -142,6 +144,7 @@ func (s Server) Handler() http.Handler {
r.Route("/keys", newAPIKeyHandler(encoder, s.apiService).Routes)
r.Route("/logs", newLogsHandler(s.config).Routes)
r.Route("/notification", newNotificationHandler(encoder, s.notificationService).Routes)
r.Route("/proxy", newProxyHandler(encoder, s.proxyService).Routes)
r.Route("/release", newReleaseHandler(encoder, s.releaseService).Routes)
r.Route("/updates", newUpdateHandler(encoder, s.updateService).Routes)