description |
---|
Bring your own custom endpoint to pREST |
With prestd's http plugin system it is possible to create new endpoints in the "private" URI,
The plugin endpoint has the following default: /_PLUGIN/{file}/{func}
The plugin endpoint (/_PLUGIN/{file}/{func}
) receives two parameters:
- File name: The name of the file without the extension (
{file}
) - Function name: The name of the function (
{func}
)
The file name will be used on the endpoint to identify which library will be loaded when it receives the first access.
After the first access the library will not be loaded again, it will only be executed, i.e., if the file (
.so
) is changed after the first execution it will have no effect because it has already been loaded.
When talking about a compiled library we have no way of identifying its functions. Given this characteristic we have defined some name and behavior patterns to develop libraries for prestd.
function name: {HTTP Method}{Function Name}Handler
{HTTP Method}
: The HTTP method that the function will be called for (in upper case letters){Function Name}
: The name of the function that will be calledHandler
: The suffix of the function name - it is alwaysHandler
fmt.Sprintf("%s%sHandler", r.Method, funcName)
- Source code name:
./lib/src/hello.go
- Library file name:
./lib/hello.so
- Function name:
GETHelloHandler
- Endpoint:
/_PLUGIN/hello/Hello
- Verb HTTP:
GET
// all plugins must have their package name as `main`
// each plugin is isolated at compile time
package main
import (
"encoding/json"
)
var (
// HTTPVars route variables for the current request
HTTPVars map[string]string
// URLQuery parses RawQuery and returns the corresponding values
URLQuery map[string][]string
)
// Response return structure of the get method
type Response struct {
HTTPVars map[string]string `json:"http_vars"`
URLQuery map[string][]string `json:"url_query"`
MSG string `json:"msg"`
}
// GETHelloHandler plugin
// function is invoked via [go language plugin](https://pkg.go.dev/plugin),
// it is not possible to pass parameters, that's why there are global
// variables to receive data from http protocol
//
// BUILD:
// go build -o lib/hello.so -buildmode=plugin lib/src/hello.go
func GETHelloHandler() (ret string) {
resp := Response{
HTTPVars: HTTPVars,
URLQuery: URLQuery,
MSG: "Hello plugin caller!",
}
respJSON, err := json.Marshal(resp)
if err != nil {
return
}
ret = string(respJSON)
return
}
// GETHelloHandler plugin
// same function as GETHelloHandler, but this time we can return status code.
func GETHelloWithStatusHandler() (ret string, code int) {
resp := Response{
HTTPVars: HTTPVars,
URLQuery: URLQuery,
MSG: "Hello plugin caller!",
}
respJSON, err := json.Marshal(resp)
if err != nil {
return
}
ret = string(respJSON)
code = http.StatusAccepted
return
}
Request:
GET /_PLUGIN/hello/Hello?abc=123 HTTP/1.1
Response:
{
"http_vars": {
"file": "hello",
"func": "Hello"
},
"url_query": {
"abc": [
"123"
]
},
"msg": "Hello plugin caller!"
}