summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwikiapiserver2026-06-25 15:42:32 +0200
committerwikiapiserver2026-06-25 15:42:32 +0200
commit81258d39db6530699194f860206528c6f09a5238 (patch)
tree015290ae2f28e1f8123c0efecfea078f80d2ff70
parent1a25a89dfeeb7ed5af4df77907b65f99bdf5399a (diff)
downloadwikiapiserver-81258d39db6530699194f860206528c6f09a5238.tar.gz
feat: GET /article endpoint proxies Wikimedia structured contents
GET /article?username=alice&name=en.wikipedia/Sun → proxies to api.enterprise.wikimedia.com/v2/structured-contents/{name} with Authorization: Bearer <access_token> Returns 401 for unknown users, 400 if params missing, and passes through the upstream HTTP status on errors.
-rw-r--r--api/handlers.go49
-rw-r--r--main.go1
2 files changed, 50 insertions, 0 deletions
diff --git a/api/handlers.go b/api/handlers.go
index 0f3b48b..6813dc2 100644
--- a/api/handlers.go
+++ b/api/handlers.go
@@ -2,11 +2,13 @@ package api
import (
"context"
+ "io"
"database/sql"
"errors"
"encoding/json"
"log"
"net/http"
+ "net/url"
"time"
"wikiapiserver/db"
@@ -202,3 +204,50 @@ func (h *Handler) GetToken(w http.ResponseWriter, r *http.Request) {
ValidUntil: acct.AccessTokenExpiry.Add(24 * time.Hour).Format(time.RFC3339),
})
}
+// --- Get Article: GET /article?username=...&name=... ---
+
+func (h *Handler) GetArticle(w http.ResponseWriter, r *http.Request) {
+ ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
+ defer cancel()
+
+ username := r.URL.Query().Get("username")
+ article := r.URL.Query().Get("name")
+ if username == "" || article == "" {
+ badRequest(w, "username and name query parameters are required")
+ return
+ }
+
+ acct, err := h.db.GetAccount(ctx, username)
+ if err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ unauthorized(w)
+ return
+ }
+ serverError(w, "could not retrieve token")
+ return
+ }
+
+ url := "https://api.enterprise.wikimedia.com/v2/structured-contents/" + url.QueryEscape(article)
+ req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+ if err != nil {
+ serverError(w, "could not build request")
+ return
+ }
+ req.Header.Set("Authorization", "Bearer "+acct.AccessToken)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ serverError(w, "wikimedia api error")
+ return
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+ b, _ := io.ReadAll(resp.Body)
+ http.Error(w, string(b), resp.StatusCode)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ io.Copy(w, resp.Body) //nolint:errcheck
+}
diff --git a/main.go b/main.go
index f2cf44d..341a175 100644
--- a/main.go
+++ b/main.go
@@ -87,6 +87,7 @@ func main() {
mux.HandleFunc("POST /refresh", handler.Refresh)
mux.HandleFunc("GET /health", handler.Health)
mux.HandleFunc("GET /token", handler.GetToken)
+ mux.HandleFunc("GET /article", handler.GetArticle)
addr := fmt.Sprintf(":%d", cfg.Server.Port)
srv := &http.Server{