Added more lightweight API docs.

This commit is contained in:
Patrick Connolly 2018-12-03 20:51:26 +08:00
parent 84da2d6a29
commit 871026b031
4 changed files with 183 additions and 5 deletions

View File

@ -62,7 +62,16 @@
* [API](https://github.com/42wim/matterbridge/wiki/Features#api) * [API](https://github.com/42wim/matterbridge/wiki/Features#api)
### API ### API
The API is very basic at the moment and rather undocumented. The API is very basic at the moment. It uses the [Swagger/OpenAPI
specification](https://swagger.io/), and so will have documentation and
an interactive web interface accessible on your instance. To view it,
simply visit your own top level `/api` path or [view online][github-api-docs].
Note: The online API docs viewer won't be interactive.
[![Screenshot of Swagger API web interface](docs/screenshot-swagger-api.png)][github-api-docs]
[github-api-docs]: https://petstore.swagger.io/?url=https://raw.githubusercontent.com/42wim/matterbridge/master/docs/swagger/swagger.yaml
Used by at least 3 projects. Feel free to make a PR to add your project to this list. Used by at least 3 projects. Feel free to make a PR to add your project to this list.
@ -112,6 +121,13 @@ $ ls bin/
matterbridge matterbridge
``` ```
The Swagger API documentation can be updated by editting
[`/docs/swagger/swagger.yaml`][api-yml]. This is simplest to do via the
hosted editor tool, into which you can [import our file][editor].
[api-yml]: docs/swagger/swagger.yaml
[editor]: https://raw.githubusercontent.com/42wim/matterbridge/master/docs/swagger/swagger.yaml
## Configuration ## Configuration
### Basic configuration ### Basic configuration
See [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration. See [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration.

View File

@ -2,7 +2,9 @@ package api
import ( import (
"encoding/json" "encoding/json"
"fmt"
"net/http" "net/http"
"strings"
"sync" "sync"
"time" "time"
@ -36,9 +38,31 @@ func New(cfg *bridge.Config) bridge.Bridger {
if b.GetInt("Buffer") != 0 { if b.GetInt("Buffer") != 0 {
b.Messages.SetCapacity(b.GetInt("Buffer")) b.Messages.SetCapacity(b.GetInt("Buffer"))
} }
// Set up Swagger API docs and helpful redirects.
e.Pre(middleware.RemoveTrailingSlash())
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://petstore.swagger.io", "http://petstore.swagger.io"},
}))
e.File("/swagger/docs.yaml", "docs/swagger/swagger.yaml")
for _, path := range strings.Fields("/ /api /swagger") {
e.GET(path, b.handleDocsRedirect)
}
// Set up token auth with exclusions for non-sensitive endpoints and redirects.
if b.GetString("Token") != "" { if b.GetString("Token") != "" {
e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) { e.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
Validator: func(key string, c echo.Context) (bool, error) {
return key == b.GetString("Token"), nil return key == b.GetString("Token"), nil
},
Skipper: func(c echo.Context) bool {
for _, path := range strings.Fields("/ /api /api/health /swagger /swagger/*") {
if c.Path() == path {
return true
}
}
return false
},
})) }))
} }
e.GET("/api/health", b.handleHealthcheck) e.GET("/api/health", b.handleHealthcheck)
@ -58,13 +82,13 @@ func New(cfg *bridge.Config) bridge.Bridger {
func (b *API) Connect() error { func (b *API) Connect() error {
return nil return nil
} }
func (b *API) Disconnect() error { func (b *API) Disconnect() error {
return nil return nil
} }
func (b *API) JoinChannel(channel config.ChannelInfo) error { func (b *API) JoinChannel(channel config.ChannelInfo) error {
return nil return nil
} }
func (b *API) Send(msg config.Message) (string, error) { func (b *API) Send(msg config.Message) (string, error) {
@ -82,6 +106,17 @@ func (b *API) handleHealthcheck(c echo.Context) error {
return c.String(http.StatusOK, "OK") return c.String(http.StatusOK, "OK")
} }
func (b *API) handleDocsRedirect(c echo.Context) error {
host := c.Request().Host
scheme := c.Request().URL.Scheme
// Special-case where this is blank for localhost.
if scheme == "" {
scheme = "http"
}
urlTemplate := "https://petstore.swagger.io/?url=%s://%s/swagger/docs.yaml"
return c.Redirect(http.StatusMovedPermanently, fmt.Sprintf(urlTemplate, scheme, host))
}
func (b *API) handlePostMessage(c echo.Context) error { func (b *API) handlePostMessage(c echo.Context) error {
message := config.Message{} message := config.Message{}
if err := c.Bind(&message); err != nil { if err := c.Bind(&message); err != nil {

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

127
docs/swagger/swagger.yaml Normal file
View File

@ -0,0 +1,127 @@
basePath: /api
definitions:
config.Message:
properties:
account:
description: Unique account name of format "[protocol].[slug]"
example: slack.myteam
type: string
avatar:
description: URL to an avatar image
example: https://secure.gravatar.com/avatar/1234567890abcdef1234567890abcdef.jpg
type: string
channel:
description: Human-readable channel name
example: test-channel
type: string
event:
description: Can be blank.
type: string
extra:
description: Extra data that doesn't fit in other fields. Used for processing
incoming messages.
type: object
gateway:
description: Name of the gateway
example: test-channel-gateway
type: string
id:
description: Unique ID of message on the gateway
example: slack 1541361213.030700
type: string
parent_id:
description: Unique ID of a parent message, if threaded
type: string
protocol:
description: Chat protocol of incoming message
example: slack
type: string
text:
description: Content of the message
example: Testing, testing, 1-2-3.
type: string
timestamp:
example: "1541361213.030700"
type: string
userid:
description: userid on the bridge
example: U4MCXJKNC
type: string
username:
description: Human-readable username
example: alice
type: string
type: object
info:
contact: {}
description: A read/write API for the Matterbridge chat bridge.
license:
name: Apache 2.0
url: https://github.com/42wim/matterbridge/blob/master/LICENSE
title: Matterbridge API
paths:
/health:
get:
responses:
"200":
description: OK
schema:
type: string
summary: Checks if the server is alive.
/message:
post:
consumes:
- application/json
description: 'Required fields: text, gateway. Optional fields: username, avatar.'
parameters:
- description: Message object to create
in: body
name: message
required: true
schema:
$ref: '#/definitions/config.Message'
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/config.Message'
type: object
security:
- ApiKeyAuth: []
summary: Create/Update a message
/messages:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/config.Message'
type: array
security:
- ApiKeyAuth: []
summary: List new messages
/stream:
get:
produces:
- application/x-json-stream
responses:
"200":
description: OK
schema:
$ref: '#/definitions/config.Message'
type: object
security:
- ApiKeyAuth: []
summary: Stream realtime messages
securityDefinitions:
ApiKeyAuth:
in: header
name: Authorization
type: apiKey
swagger: "2.0"