-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Uwe Steinmann
committed
Apr 3, 2023
0 parents
commit a4f784f
Showing
19 changed files
with
764 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
PKGNAME=golang-seeddms-seeddms-apiclient | ||
VERSION=0.0.2 | ||
|
||
test: | ||
go test -v . | ||
|
||
build: | ||
go build seeddms.org/seeddms/apiclient | ||
|
||
dist: | ||
rm -rf ${PKGNAME}-${VERSION} | ||
mkdir ${PKGNAME}-${VERSION} | ||
cp -r *.go Makefile go.mod go.sum ${PKGNAME}-${VERSION} | ||
mkdir -p ${PKGNAME}-${VERSION}/testdata/fixtures | ||
cp testdata/fixtures/*.json ${PKGNAME}-${VERSION}/testdata/fixtures | ||
tar czvf ${PKGNAME}-${VERSION}.tar.gz ${PKGNAME}-${VERSION} | ||
rm -rf ${PKGNAME}-${VERSION} | ||
|
||
debian: dist | ||
mv ${PKGNAME}-${VERSION}.tar.gz ../${PKGNAME}_${VERSION}.orig.tar.gz | ||
debuild | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
package apiclient | ||
|
||
import ( | ||
"net/http" | ||
"net/http/cookiejar" | ||
// "net/url" | ||
"fmt" | ||
"time" | ||
"io" | ||
"io/ioutil" | ||
// "os" | ||
"log" | ||
"encoding/json" | ||
) | ||
|
||
type Client struct { | ||
BaseURL string | ||
username string | ||
password string | ||
ApiKey string | ||
HTTPClient *http.Client | ||
StatusCode int | ||
ErrorMsg string | ||
} | ||
|
||
type Attribute struct { | ||
Id int | ||
Name string | ||
Value string | ||
} | ||
|
||
type Object struct { | ||
Id int | ||
Objtype string `json:"type"` | ||
Name string | ||
Comment string | ||
Date string | ||
} | ||
|
||
type Folder struct { | ||
Id int | ||
Objtype string `json:"type"` | ||
Name string | ||
Comment string | ||
Date string | ||
Attributes []Attribute | ||
} | ||
|
||
type Document struct { | ||
Id int | ||
Objtype string `json:"type"` | ||
Name string | ||
Comment string | ||
Keywords string | ||
Date string | ||
Mimetype string | ||
Filetype string | ||
Origfilename string | ||
Islocked bool | ||
Expires string | ||
Version int | ||
VersionComment string `json:"version_comment"` | ||
VersionDate string `json:"version_date"` | ||
Size int | ||
Attributes []Attribute | ||
VersionAttributes []Attribute `json:"version_attributes"` | ||
} | ||
|
||
type Group struct { | ||
Id int | ||
Objtype string `json:"type"` | ||
Name string | ||
Comment string | ||
} | ||
|
||
type Role struct { | ||
Id int | ||
Name string | ||
} | ||
|
||
type User struct { | ||
Id int | ||
Objtype string `json:"type"` | ||
Name string | ||
Comment string | ||
Login string | ||
Email string | ||
Language string | ||
Theme string | ||
Role Role | ||
Hidden bool | ||
Disabled bool | ||
Isguest bool | ||
Isadmin bool | ||
Groups []Group | ||
} | ||
|
||
type Statstotal struct { | ||
Docstotal int | ||
Folderstotal int | ||
Userstotal int | ||
} | ||
|
||
type errorResponse struct { | ||
Success bool | ||
Message string | ||
Data string | ||
} | ||
|
||
type successResponse struct { | ||
success bool | ||
message string | ||
data interface{} | ||
} | ||
|
||
func Connect(baseurl string, apikey string) *Client { | ||
jar, err := cookiejar.New(nil) | ||
if err != nil { | ||
log.Fatalf("Got error while creating cookie jar %s", err.Error()) | ||
} | ||
return &Client{ | ||
BaseURL: baseurl, | ||
ApiKey: apikey, | ||
HTTPClient: &http.Client{ | ||
Timeout: time.Minute, | ||
Jar: jar, | ||
}, | ||
} | ||
} | ||
|
||
func (c *Client) getBody(url string) (io.Reader, error) { | ||
req, err := http.NewRequest(http.MethodGet, url, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if c.ApiKey != "" { | ||
req.Header.Set("Authorization", fmt.Sprintf("%s", c.ApiKey)) | ||
} | ||
|
||
res, err := c.HTTPClient.Do(req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
c.StatusCode = res.StatusCode | ||
if res.StatusCode < http.StatusOK || res.StatusCode >= http.StatusBadRequest { | ||
var errRes errorResponse | ||
if err = json.NewDecoder(res.Body).Decode(&errRes); err == nil { | ||
c.ErrorMsg = errRes.Message | ||
return nil, fmt.Errorf(errRes.Message) | ||
} | ||
|
||
return nil, fmt.Errorf("unknown error, status code: %d", res.StatusCode) | ||
} | ||
|
||
return res.Body, nil | ||
} | ||
|
||
func (c *Client) sendRequest(req *http.Request, target interface{}) error { | ||
if req.Header.Get("Content-Type") == "" { | ||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") | ||
} | ||
req.Header.Set("Accept", "application/json; charset=utf-8") | ||
if c.ApiKey != "" { | ||
req.Header.Set("Authorization", fmt.Sprintf("%s", c.ApiKey)) | ||
} | ||
|
||
// urlObj, _ := url.Parse(c.BaseURL) | ||
// fmt.Print(c.HTTPClient.Jar.Cookies(urlObj)) | ||
|
||
res, err := c.HTTPClient.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer res.Body.Close() | ||
|
||
c.StatusCode = res.StatusCode | ||
if res.StatusCode < http.StatusOK || res.StatusCode >= http.StatusBadRequest { | ||
var errRes errorResponse | ||
if err = json.NewDecoder(res.Body).Decode(&errRes); err == nil { | ||
c.ErrorMsg = errRes.Message | ||
return fmt.Errorf(errRes.Message) | ||
} | ||
|
||
return fmt.Errorf("unknown error, status code: %d", res.StatusCode) | ||
} | ||
|
||
if false { | ||
// since goland 1.16 io.ReadAll should be used | ||
bodyBytes, err := ioutil.ReadAll(res.Body) | ||
if err == nil { | ||
jsonerr := json.Unmarshal([]byte(bodyBytes), target) | ||
//fmt.Printf("%+v", target) | ||
return jsonerr | ||
} else { | ||
//fmt.Print(err) | ||
return err | ||
} | ||
} else { | ||
// For some reason reading from the io stream didn't work because 'success' | ||
// was an unknown field | ||
//io.Copy(os.Stdout, res.Body) | ||
decoder := json.NewDecoder(res.Body) | ||
// Children() returns both, folders and documents and they have different | ||
// structs. That's why the json is mapped on the struct Object which just | ||
// contains the fields common to both folders and documents. But that | ||
// requires to allow unknows fields. | ||
// decoder.DisallowUnknownFields() | ||
return decoder.Decode(target) | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package apiclient | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
type childrenResponse struct { | ||
Success bool `json:"success"` | ||
Message string `json:"message"` | ||
Data []Object | ||
} | ||
|
||
func (c *Client) Children(id int) (*childrenResponse, error) { | ||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/folder/%d/children", c.BaseURL, id), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
res := childrenResponse{} | ||
if err := c.sendRequest(req, &res); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &res, nil | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package apiclient | ||
|
||
import ( | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
func TestChildren(t *testing.T) { | ||
// Create the test server and shut it down when the test ends | ||
c, teardown := setupTestServer() | ||
defer teardown() | ||
|
||
// Add restapi endpoint to retrieve the children of a folder | ||
mux.HandleFunc("/folder/1/children", func(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
// ... return the JSON | ||
fmt.Fprint(w, fixture("children.json")) | ||
}) | ||
|
||
c.Login("admin", "admin") | ||
|
||
res, err := c.Children(1) | ||
|
||
assert.Nil(t, err, "expecting nil error") | ||
assert.NotNil(t, res, "expecting non-nil result") | ||
assert.NotNil(t, res.Data, "expecting array of objects") | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package apiclient | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
) | ||
|
||
func (c *Client) Content(id int) (io.Reader, error) { | ||
body, err := c.getBody(fmt.Sprintf("%s/document/%d/content", c.BaseURL, id)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
//defer body.Close() | ||
|
||
return body, nil | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package apiclient | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
type documentResponse struct { | ||
Success bool `json:"success"` | ||
Message string `json:"message"` | ||
Data Document | ||
} | ||
|
||
func (c *Client) Document(id int) (*documentResponse, error) { | ||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/document/%d", c.BaseURL, id), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
res := documentResponse{} | ||
if err := c.sendRequest(req, &res); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &res, nil | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package apiclient | ||
|
||
import ( | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
func TestDocument(t *testing.T) { | ||
// Create the test server and shut it down when the test ends | ||
c, teardown := setupTestServer() | ||
defer teardown() | ||
|
||
// Add restapi endpoint to retrieve a document | ||
mux.HandleFunc("/document/22545", func(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
// ... return the JSON | ||
fmt.Fprint(w, fixture("document.json")) | ||
}) | ||
|
||
c.Login("admin", "admin") | ||
|
||
res, err := c.Document(22545) | ||
|
||
assert.Nil(t, err, "expecting nil error") | ||
assert.NotNil(t, res, "expecting non-nil result") | ||
assert.Equal(t, 22545, res.Data.Id, "expecting id=22545 as we asked for it") | ||
} | ||
|
||
|
Oops, something went wrong.