Create a server (go) and webapp (vue) development tool to explore OPDS-PS capable servers. This tool is intended for development purposes only, it should allow to navigate the server, view raw requests and responses and interact with the API in a general way. I think it's best if we provide a columns layout to navigate the OPDS-PS server much like the macos finder does, with a panel with details to the far right for technical information. Here's the SPEC: https://specs.opds.io/
91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"opds-explorer/internal/proxy"
|
|
)
|
|
|
|
type Handler struct {
|
|
proxy proxyClient
|
|
}
|
|
|
|
type proxyClient interface {
|
|
Fetch(method, targetURL string, headers http.Header, body []byte) (*proxy.FetchResult, error)
|
|
}
|
|
|
|
func New(p proxyClient) *Handler {
|
|
return &Handler{proxy: p}
|
|
}
|
|
|
|
// FetchFeed handles GET/POST /api/fetch?url=... or JSON body { "url": "...", "method": "GET", "headers": {}, "body": "" }
|
|
func (h *Handler) FetchFeed(w http.ResponseWriter, r *http.Request) {
|
|
var method, targetURL string
|
|
var headers http.Header
|
|
var body []byte
|
|
|
|
if r.Method == http.MethodPost {
|
|
var req struct {
|
|
URL string `json:"url"`
|
|
Method string `json:"method"`
|
|
Headers map[string]string `json:"headers"`
|
|
Body string `json:"body"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid JSON body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
targetURL = req.URL
|
|
method = req.Method
|
|
if method == "" {
|
|
method = "GET"
|
|
}
|
|
headers = make(http.Header)
|
|
for k, v := range req.Headers {
|
|
headers.Set(k, v)
|
|
}
|
|
body = []byte(req.Body)
|
|
} else {
|
|
targetURL = r.URL.Query().Get("url")
|
|
method = r.Method
|
|
}
|
|
|
|
if targetURL == "" {
|
|
http.Error(w, "missing url", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
result, err := h.proxy.Fetch(method, targetURL, headers, body)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(result)
|
|
}
|
|
|
|
// ProxyResource streams a GET request to the given url (e.g. for images). Requires proxyClientStream interface.
|
|
func (h *Handler) ProxyResource(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
targetURL := r.URL.Query().Get("url")
|
|
if targetURL == "" {
|
|
http.Error(w, "missing url", http.StatusBadRequest)
|
|
return
|
|
}
|
|
streamer, ok := h.proxy.(interface {
|
|
ProxyStream(string, http.ResponseWriter) (int, error)
|
|
})
|
|
if !ok {
|
|
http.Error(w, "proxy does not support streaming", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
_, err := streamer.ProxyStream(targetURL, w)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadGateway)
|
|
}
|
|
}
|