mirror of
https://github.com/jech/galene.git
synced 2024-12-22 15:25:48 +01:00
Use JSON arrays instead of plain text in API.
Suggested by Dianne Skoll.
This commit is contained in:
parent
aa35408dba
commit
a12331ee09
4 changed files with 42 additions and 61 deletions
14
README.API
14
README.API
|
@ -43,8 +43,8 @@ allowed methods are HEAD and GET.
|
|||
|
||||
/galene-api/v0/.groups/
|
||||
|
||||
Returns a list of groups, as plain text, one per line. The only allowed
|
||||
methods are HEAD and GET.
|
||||
Returns a list of groups, as a JSON array. The only allowed methods are
|
||||
HEAD and GET.
|
||||
|
||||
### Group definition
|
||||
|
||||
|
@ -75,8 +75,8 @@ accepted content-type is `application/jwk-set+json`.
|
|||
|
||||
/galene-api/v0/.groups/groupname/.users/
|
||||
|
||||
Returns a list of users, as plain text, one per line. The only allowed
|
||||
methods are HEAD and GET.
|
||||
Returns a list of users, as a JSON array. The only allowed methods are
|
||||
HEAD and GET.
|
||||
|
||||
### User definition
|
||||
|
||||
|
@ -101,9 +101,9 @@ POST.
|
|||
|
||||
/galene-api/v0/.groups/groupname/.users/username/.tokens/
|
||||
|
||||
GET returns the list of stateful tokens, as plain text, one token per
|
||||
line. POST creates a new token, and returns its name in the `Location`
|
||||
header. Allowed methods are HEAD, GET and POST.
|
||||
GET returns the list of stateful tokens, as a JSON array. POST creates
|
||||
a new token, and returns its name in the `Location` header. Allowed
|
||||
methods are HEAD, GET and POST.
|
||||
|
||||
### Stateful token
|
||||
|
||||
|
|
|
@ -49,12 +49,11 @@ async function listObjects(url) {
|
|||
let r = await fetch(url);
|
||||
if(!r.ok)
|
||||
throw httpError(r);
|
||||
let strings = (await r.text()).split('\n');
|
||||
if(strings[strings.length - 1] === '') {
|
||||
strings.pop();
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
let data = await r.json();
|
||||
if(!(data instanceof Array))
|
||||
throw new Error("Server didn't return array");
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* createObject makes a PUT request to url with JSON data.
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -118,13 +117,12 @@ func apiGroupHandler(w http.ResponseWriter, r *http.Request, pth string) {
|
|||
httpError(w, err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("content-type", "text/plain; charset=utf-8")
|
||||
w.Header().Set("content-type", "application/json")
|
||||
if r.Method == "HEAD" {
|
||||
return
|
||||
}
|
||||
for _, g := range groups {
|
||||
fmt.Fprintln(w, g)
|
||||
}
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(groups)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -257,7 +255,7 @@ func usersHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||
httpError(w, err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("content-type", "text/plain; charset=utf-8")
|
||||
w.Header().Set("content-type", "application/json")
|
||||
w.Header().Set("etag", etag)
|
||||
done := checkPreconditions(w, r, etag)
|
||||
if done {
|
||||
|
@ -266,9 +264,8 @@ func usersHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||
if r.Method == "HEAD" {
|
||||
return
|
||||
}
|
||||
for _, u := range users {
|
||||
fmt.Fprintln(w, u)
|
||||
}
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(users)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -545,17 +542,19 @@ func tokensHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||
httpError(w, err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("content-type",
|
||||
"text/plain; charset=utf-8")
|
||||
w.Header().Set("content-type", "application/json")
|
||||
if etag != "" {
|
||||
w.Header().Set("etag", etag)
|
||||
}
|
||||
if r.Method == "HEAD" {
|
||||
return
|
||||
}
|
||||
for _, t := range tokens {
|
||||
fmt.Fprintln(w, t.Token)
|
||||
toknames := make([]string, len(tokens))
|
||||
for i, t := range tokens {
|
||||
toknames[i] = t.Token
|
||||
}
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(toknames)
|
||||
return
|
||||
} else if r.Method == "POST" {
|
||||
ctype := parseContentType(r.Header.Get("Content-Type"))
|
||||
|
@ -586,8 +585,6 @@ func tokensHandler(w http.ResponseWriter, r *http.Request, g, pth string) {
|
|||
httpError(w, err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("content-type",
|
||||
"text/plain; charset=utf-8")
|
||||
w.Header().Set("location", t.Token)
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
return
|
||||
|
|
|
@ -3,7 +3,6 @@ package webserver
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -91,23 +90,6 @@ func TestApi(t *testing.T) {
|
|||
return client.Do(req)
|
||||
}
|
||||
|
||||
getString := func(path string) (string, error) {
|
||||
resp, err := do("GET", path, "", "", "", "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("Status is %v", resp.StatusCode)
|
||||
}
|
||||
ctype := parseContentType(resp.Header.Get("Content-Type"))
|
||||
if !strings.EqualFold(ctype, "text/plain") {
|
||||
return "", errors.New("Unexpected Content-Type")
|
||||
}
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
getJSON := func(path string, value any) error {
|
||||
resp, err := do("GET", path, "", "", "", "")
|
||||
if err != nil {
|
||||
|
@ -119,14 +101,15 @@ func TestApi(t *testing.T) {
|
|||
}
|
||||
ctype := parseContentType(resp.Header.Get("Content-Type"))
|
||||
if !strings.EqualFold(ctype, "application/json") {
|
||||
return errors.New("Unexpected")
|
||||
return errors.New("Unexpected content-type")
|
||||
}
|
||||
d := json.NewDecoder(resp.Body)
|
||||
return d.Decode(value)
|
||||
}
|
||||
|
||||
s, err := getString("/galene-api/v0/.groups/")
|
||||
if err != nil || s != "" {
|
||||
var groups []string
|
||||
err = getJSON("/galene-api/v0/.groups/", &groups)
|
||||
if err != nil || len(groups) != 0 {
|
||||
t.Errorf("Get groups: %v", err)
|
||||
}
|
||||
|
||||
|
@ -171,9 +154,9 @@ func TestApi(t *testing.T) {
|
|||
t.Errorf("Delete group (bad ETag): %v %v", err, resp.StatusCode)
|
||||
}
|
||||
|
||||
s, err = getString("/galene-api/v0/.groups/")
|
||||
if err != nil || s != "test\n" {
|
||||
t.Errorf("Get groups: %v %#v", err, s)
|
||||
err = getJSON("/galene-api/v0/.groups/", &groups)
|
||||
if err != nil || len(groups) != 1 || groups[0] != "test" {
|
||||
t.Errorf("Get groups: %v %v", err, groups)
|
||||
}
|
||||
|
||||
resp, err = do("PUT", "/galene-api/v0/.groups/test/.fallback-users",
|
||||
|
@ -193,8 +176,8 @@ func TestApi(t *testing.T) {
|
|||
t.Errorf("Set key: %v %v", err, resp.StatusCode)
|
||||
}
|
||||
|
||||
s, err = getString("/galene-api/v0/.groups/test/.users/")
|
||||
if err != nil || s != "" {
|
||||
err = getJSON("/galene-api/v0/.groups/test/.users/", &groups)
|
||||
if err != nil || len(groups) != 0 {
|
||||
t.Errorf("Get users: %v", err)
|
||||
}
|
||||
|
||||
|
@ -213,9 +196,10 @@ func TestApi(t *testing.T) {
|
|||
t.Errorf("Create user: %v %v", err, resp.StatusCode)
|
||||
}
|
||||
|
||||
s, err = getString("/galene-api/v0/.groups/test/.users/")
|
||||
if err != nil || s != "jch\n" {
|
||||
t.Errorf("Get users: %v", err)
|
||||
var users []string
|
||||
err = getJSON("/galene-api/v0/.groups/test/.users/", &users)
|
||||
if err != nil || len(users) != 1 || users[0] != "jch" {
|
||||
t.Errorf("Get users: %v %v", err, users)
|
||||
}
|
||||
|
||||
resp, err = do("PUT", "/galene-api/v0/.groups/test/.users/jch",
|
||||
|
@ -296,11 +280,12 @@ func TestApi(t *testing.T) {
|
|||
t.Errorf("Create token: %v %v", err, resp.StatusCode)
|
||||
}
|
||||
|
||||
tokname, err := getString("/galene-api/v0/.groups/test/.tokens/")
|
||||
if err != nil {
|
||||
t.Errorf("Get tokens: %v", err)
|
||||
var toknames []string
|
||||
err = getJSON("/galene-api/v0/.groups/test/.tokens/", &toknames)
|
||||
if err != nil || len(toknames) != 1 {
|
||||
t.Errorf("Get tokens: %v %v", err, toknames)
|
||||
}
|
||||
tokname = tokname[:len(tokname)-1]
|
||||
tokname := toknames[0]
|
||||
|
||||
tokens, etag, err := token.List("test")
|
||||
if err != nil || len(tokens) != 1 || tokens[0].Token != tokname {
|
||||
|
|
Loading…
Reference in a new issue