mirror of
https://codeberg.org/scip/ephemerup.git
synced 2025-12-18 13:01:13 +01:00
+api doc, fixed endpoints
This commit is contained in:
77
README.md
77
README.md
@@ -141,6 +141,83 @@ the `-4` respective the `-6` commandline flags.
|
|||||||
It does not support TLS at the moment. Use a nginx reverse proxy in
|
It does not support TLS at the moment. Use a nginx reverse proxy in
|
||||||
front of it.
|
front of it.
|
||||||
|
|
||||||
|
### Server REST API
|
||||||
|
|
||||||
|
Every endpoint returns a JSON object. Each returned object contains the data requested plus:
|
||||||
|
|
||||||
|
- success: true or false
|
||||||
|
- code: HTTP Response Code
|
||||||
|
- message: error message, if success==false
|
||||||
|
|
||||||
|
#### Endpoints
|
||||||
|
|
||||||
|
| HTTP Method | Endpoint | Parameters | Input | Returns | Description |
|
||||||
|
|-------------|-------------------|---------------------|----------------------------|---------------------------------------|-----------------------------------------------|
|
||||||
|
| GET | /v1/uploads | apicontext,q,expire | | List of upload objects | list upload objects |
|
||||||
|
| POST | /v1/uploads | | multipart-formdata file[s] | List of 1 upload object if successful | upload a file and create a new upload object |
|
||||||
|
| GET | /v1/uploads/{id} | | | List of 1 upload object if successful | list one specific upload object matching {id} |
|
||||||
|
| DELETE | /v1/uploads/{id} | | | Noting | delete an upload object identified by {id} |
|
||||||
|
| PUT | /v1/uploads/{id} | | JSON upload object | List of 1 upload object if successful | modify an upload object identified by {id} |
|
||||||
|
| GET | /v1/download/{id} | | | File download | Download the file associated with the object |
|
||||||
|
| GET | /v1/forms | apicontext,q,expire | | List of form objects | list form objects |
|
||||||
|
| POST | /v1/forms | | JSON form object | List of 1 form object if successful | create a new form object |
|
||||||
|
| GET | /v1/forms/{id} | | | List of 1 form object if successful | list one specific form object matching {id} |
|
||||||
|
| DELETE | /v1/forms/{id} | | | Noting | delete an form object identified by {id} |
|
||||||
|
| PUT | /v1/forms/{id} | | JSON form object | List of 1 form object if successful | modify an form object identified by {id} |
|
||||||
|
|
||||||
|
#### Consumer URLs
|
||||||
|
|
||||||
|
The following endpoints are no API urls, but accessed directly by consumers using their browser or `wget` etc:
|
||||||
|
|
||||||
|
| URL | Description |
|
||||||
|
|-------------------------|---------------------------------------------------------|
|
||||||
|
| / | Display a short welcome message, can be customized |
|
||||||
|
| /download/{id}[/{file}] | Download link returned after an upload has been created |
|
||||||
|
| /form/{id} | Upload form for consumer |
|
||||||
|
|
||||||
|
#### API Objects
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
| Field | Data Type | Description |
|
||||||
|
|---------|-----------|---------------------------------------|
|
||||||
|
| success | bool | if true the request was successful |
|
||||||
|
| code | int | HTTP response code |
|
||||||
|
| message | string | error message, if any |
|
||||||
|
| uploads | array | list of upload objects (may be empty) |
|
||||||
|
| forms | array | list of form objects (may be empty) |
|
||||||
|
|
||||||
|
Upload:
|
||||||
|
|
||||||
|
| Field | Data Type | Description |
|
||||||
|
|----------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| id | string | unique identifier for the object |
|
||||||
|
| expire | string | when the upload has to expire, either "asap" or a Duration using numbers and the letters d,h,m,s (days,hours,minutes,seconds), e.g. 2d4h30m |
|
||||||
|
| file | string | filename after uploading, this is what a consumer gets when downloading it |
|
||||||
|
| members | array of strings | list of the original filenames |
|
||||||
|
| uploaded | timestamp | time of object creation |
|
||||||
|
| context | string | the API context the upload has been created under |
|
||||||
|
| url | string | the download URL |
|
||||||
|
|
||||||
|
Form:
|
||||||
|
|
||||||
|
| Field | Data Type | Description |
|
||||||
|
|-------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| id | string | unique identifier for the object |
|
||||||
|
| expire | string | when the form has to expire, either "asap" or a Duration using numbers and the letters d,h,m,s (days,hours,minutes,seconds), e.g. 2d4h30m |
|
||||||
|
| description | string | arbitrary description, shown on the form page |
|
||||||
|
| context | string | the API context the form has been created under and the uploaded files will be created on |
|
||||||
|
| notify | string | email address of the form creator, who gets an email once the consumer has uploaded files using the form |
|
||||||
|
| created | timestamp | time of object creation |
|
||||||
|
| url | string | the form URL |
|
||||||
|
|
||||||
|
Note: if the expire field for a form is not set or set to "asap" only
|
||||||
|
1 upload object can be created from it. However, if a duration has
|
||||||
|
been specified, the form can be used multiple times and thus creates
|
||||||
|
multiple upload objects.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Client Usage
|
## Client Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -56,33 +56,30 @@ func Runserver(conf *cfg.Config, args []string) error {
|
|||||||
api := router.Group(conf.ApiPrefix + ApiVersion)
|
api := router.Group(conf.ApiPrefix + ApiVersion)
|
||||||
{
|
{
|
||||||
// upload
|
// upload
|
||||||
api.Post("/file/", auth, func(c *fiber.Ctx) error {
|
api.Post("/uploads/", auth, func(c *fiber.Ctx) error {
|
||||||
return FilePut(c, conf, db)
|
return FilePut(c, conf, db)
|
||||||
})
|
})
|
||||||
|
|
||||||
// download w/o expire
|
|
||||||
api.Get("/file/:id/:file", auth, func(c *fiber.Ctx) error {
|
|
||||||
return FileGet(c, conf, db)
|
|
||||||
})
|
|
||||||
api.Get("/file/:id/", auth, func(c *fiber.Ctx) error {
|
|
||||||
return FileGet(c, conf, db)
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove
|
// remove
|
||||||
api.Delete("/file/:id/", auth, func(c *fiber.Ctx) error {
|
api.Delete("/uploads/:id/", auth, func(c *fiber.Ctx) error {
|
||||||
err := DeleteUpload(c, conf, db)
|
err := DeleteUpload(c, conf, db)
|
||||||
return SendResponse(c, "", err)
|
return SendResponse(c, "", err)
|
||||||
})
|
})
|
||||||
|
|
||||||
// listing
|
// listing
|
||||||
api.Get("/list/", auth, func(c *fiber.Ctx) error {
|
api.Get("/uploads", auth, func(c *fiber.Ctx) error {
|
||||||
return List(c, conf, db)
|
return List(c, conf, db)
|
||||||
})
|
})
|
||||||
|
|
||||||
// info
|
// info/describe
|
||||||
api.Get("/upload/:id/", auth, func(c *fiber.Ctx) error {
|
api.Get("/upload/:id/", auth, func(c *fiber.Ctx) error {
|
||||||
return Describe(c, conf, db)
|
return Describe(c, conf, db)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// download w/o expire
|
||||||
|
api.Get("/download/:id/", auth, func(c *fiber.Ctx) error {
|
||||||
|
return FileGet(c, conf, db)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// public routes
|
// public routes
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ func HandleResponse(c *cfg.Config, resp *req.Response) error {
|
|||||||
|
|
||||||
func UploadFiles(w io.Writer, c *cfg.Config, args []string) error {
|
func UploadFiles(w io.Writer, c *cfg.Config, args []string) error {
|
||||||
// setup url, req.Request, timeout handling etc
|
// setup url, req.Request, timeout handling etc
|
||||||
rq := Setup(c, "/file/")
|
rq := Setup(c, "/uploads/")
|
||||||
|
|
||||||
// collect files to upload from @argv
|
// collect files to upload from @argv
|
||||||
if err := GatherFiles(rq, args); err != nil {
|
if err := GatherFiles(rq, args); err != nil {
|
||||||
@@ -220,7 +220,7 @@ func List(w io.Writer, c *cfg.Config, args []string) error {
|
|||||||
|
|
||||||
func Delete(w io.Writer, c *cfg.Config, args []string) error {
|
func Delete(w io.Writer, c *cfg.Config, args []string) error {
|
||||||
for _, id := range args {
|
for _, id := range args {
|
||||||
rq := Setup(c, "/file/"+id+"/")
|
rq := Setup(c, "/uploads/"+id+"/")
|
||||||
|
|
||||||
resp, err := rq.R.Delete(rq.Url)
|
resp, err := rq.R.Delete(rq.Url)
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ func Download(w io.Writer, c *cfg.Config, args []string) error {
|
|||||||
|
|
||||||
id := args[0]
|
id := args[0]
|
||||||
|
|
||||||
rq := Setup(c, "/file/"+id+"/")
|
rq := Setup(c, "/uploads/"+id+"/")
|
||||||
|
|
||||||
if !c.Silent {
|
if !c.Silent {
|
||||||
// progres bar
|
// progres bar
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ func TestUploadFiles(t *testing.T) {
|
|||||||
name: "upload-file",
|
name: "upload-file",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: false,
|
wantfail: false,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: `{"success": true}`,
|
sendjson: `{"success": true}`,
|
||||||
files: []string{"../t/t1"}, // pwd is lib/ !
|
files: []string{"../t/t1"}, // pwd is lib/ !
|
||||||
@@ -121,7 +121,7 @@ func TestUploadFiles(t *testing.T) {
|
|||||||
name: "upload-dir",
|
name: "upload-dir",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: false,
|
wantfail: false,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: `{"success": true}`,
|
sendjson: `{"success": true}`,
|
||||||
files: []string{"../t"}, // pwd is lib/ !
|
files: []string{"../t"}, // pwd is lib/ !
|
||||||
@@ -131,7 +131,7 @@ func TestUploadFiles(t *testing.T) {
|
|||||||
name: "upload-catch-nonexistent-file",
|
name: "upload-catch-nonexistent-file",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: `{"success": false}`,
|
sendjson: `{"success": false}`,
|
||||||
files: []string{"../t/none"},
|
files: []string{"../t/none"},
|
||||||
@@ -141,7 +141,7 @@ func TestUploadFiles(t *testing.T) {
|
|||||||
name: "upload-catch-no-access",
|
name: "upload-catch-no-access",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 403,
|
sendcode: 403,
|
||||||
sendjson: `{"success": false}`,
|
sendjson: `{"success": false}`,
|
||||||
files: []string{"../t/t1"},
|
files: []string{"../t/t1"},
|
||||||
@@ -151,7 +151,7 @@ func TestUploadFiles(t *testing.T) {
|
|||||||
name: "upload-check-output",
|
name: "upload-check-output",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: false,
|
wantfail: false,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: `{"uploads":[
|
sendjson: `{"uploads":[
|
||||||
{
|
{
|
||||||
@@ -313,7 +313,7 @@ func TestDelete(t *testing.T) {
|
|||||||
name: "delete",
|
name: "delete",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: false,
|
wantfail: false,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: `{"success":true,"message":"","code":200}`,
|
sendjson: `{"success":true,"message":"","code":200}`,
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
@@ -324,7 +324,7 @@ func TestDelete(t *testing.T) {
|
|||||||
name: "delete-catch-empty-json",
|
name: "delete-catch-empty-json",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendjson: "",
|
sendjson: "",
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
@@ -334,7 +334,7 @@ func TestDelete(t *testing.T) {
|
|||||||
name: "delete-catch-no-access",
|
name: "delete-catch-no-access",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 503,
|
sendcode: 503,
|
||||||
sendjson: listingnoaccess,
|
sendjson: listingnoaccess,
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
@@ -365,7 +365,7 @@ func TestDownload(t *testing.T) {
|
|||||||
name: "download",
|
name: "download",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: false,
|
wantfail: false,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
sendfile: "../t/t1",
|
sendfile: "../t/t1",
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
@@ -376,7 +376,7 @@ func TestDownload(t *testing.T) {
|
|||||||
name: "download-catch-empty-response",
|
name: "download-catch-empty-response",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 200,
|
sendcode: 200,
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -385,7 +385,7 @@ func TestDownload(t *testing.T) {
|
|||||||
name: "download-catch-no-access",
|
name: "download-catch-no-access",
|
||||||
apikey: "token",
|
apikey: "token",
|
||||||
wantfail: true,
|
wantfail: true,
|
||||||
route: "/file/",
|
route: "/uploads/",
|
||||||
sendcode: 503,
|
sendcode: 503,
|
||||||
sendjson: listingnoaccess,
|
sendjson: listingnoaccess,
|
||||||
files: []string{"cc2c965a"},
|
files: []string{"cc2c965a"},
|
||||||
|
|||||||
Reference in New Issue
Block a user