diff --git a/Taskfile.yml b/Taskfile.yml index 5808e99..5b1e85c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -22,8 +22,9 @@ tasks: env: #TAG: "v0.0.1" #TAG: "v0.0.2" - TAG: "v0.0.3" # current release - #TAG: "v0.0.4" # current release + TAG: "v0.0.4" # current release + #TAG: "v0.0.5" # it will be the next release + cmds: - echo "📦 Generating release..." - git add . diff --git a/capsule.dk.go b/capsule.dk.go index d7458e3..ff7fadc 100644 --- a/capsule.dk.go +++ b/capsule.dk.go @@ -6,7 +6,6 @@ import "errors" const isFailure = rune('F') const isSuccess = rune('S') - func success(buffer []byte) uint64 { return copyBufferToMemory(append([]byte(string(isSuccess)), buffer...)) } @@ -15,6 +14,16 @@ func failure(buffer []byte) uint64 { return copyBufferToMemory(append([]byte(string(isFailure)), buffer...)) } +// Success function +func Success(buffer []byte) uint64 { + return success(buffer) +} + +// Failure function +func Failure(buffer []byte) uint64 { + return failure(buffer) +} + // Result function func Result(data []byte,) ([]byte, error) { if data[0] == byte(isSuccess) { diff --git a/docs/helpers.md b/docs/helpers.md new file mode 100644 index 0000000..94ade6c --- /dev/null +++ b/docs/helpers.md @@ -0,0 +1,65 @@ +# 🧰 Helpers + +> 🚧 this is a work in progress + +## Success and Failure +> introduced in v0.0.4 + +`Success` and `Failure` copy an `[]byte` to the shared memory, and return the position and the length of the value "packed" into a single value (`uint64`). + +If you use `Success`, the `[]byte` is prefixed by `rune('S')` before being copied to the shared memory. + +If you use `Failure`, the `[]byte` is prefixed by `rune('F')` before being copied to the shared memory. + +This value will be used by the function `CallHandleFunction` of the [Host SDK](https://github.com/bots-garden/capsule-host-sdk/blob/main/runtime.go) that will use the [`Result` function](https://github.com/bots-garden/capsule-host-sdk/blob/main/capsule.dk.go) to extract the result status (success or failure) and the result value (value or error). + +```golang +// Package main +package main + +import ( + "strconv" + "github.com/bots-garden/capsule-module-sdk" +) + +// OnHealthCheck function +//export OnHealthCheck +func OnHealthCheck() uint64 { + capsule.Print("⛑️ OnHealthCheck") + + response := capsule.HTTPResponse{ + JSONBody: `{"message": "OK"}`, + Headers: `{"Content-Type": "application/json; charset=utf-8"}`, + StatusCode: 200, + } + + return capsule.Success([]byte(capsule.StringifyHTTPResponse(response))) +} + +func main() { + capsule.SetHandleHTTP(func (param capsule.HTTPRequest) (capsule.HTTPResponse, error) { + return capsule.HTTPResponse{ + TextBody: "👋 Hey", + Headers: `{"Content-Type": "text/plain; charset=utf-8"}`, + StatusCode: 200, + }, nil + + }) +} +``` +> 👋 don't forget to export the `OnHealthCheck` function + +## StringifyHTTPResponse +> introduced in v0.0.4 + +`StringifyHTTPResponse` converts a `capsule.HTTPResponse` into a string. + +```golang +response := capsule.HTTPResponse{ + JSONBody: `{"message": "OK"}`, + Headers: `{"Content-Type": "application/json; charset=utf-8"}`, + StatusCode: 200, +} + +str := capsule.StringifyHTTPResponse(response) +``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 9a4c199..55aa373 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,8 @@ # Capsule Module SDK !!! info "What's new?" + - `v0.0.4`: ✨ Add `Success` and `Failure` functions (public functionc to call `success` and `failure`) and `StringifyHTTPResponse` + - `v0.0.3`: ✨ Encode `retValue.TextBody` to avoid special characters in jsonString - `v0.0.2`: ✨ Redis support - `v0.0.1`: 🎉 first release diff --git a/handle.http.go b/handle.http.go index 56fa888..8367148 100644 --- a/handle.http.go +++ b/handle.http.go @@ -7,8 +7,6 @@ import ( "github.com/valyala/fastjson" ) - - var handleHTTPFunction func(param HTTPRequest) (HTTPResponse, error) // SetHandleHTTP sets the handle function @@ -16,9 +14,33 @@ func SetHandleHTTP(function func(param HTTPRequest) (HTTPResponse, error)) { handleHTTPFunction = function } +// StringifyHTTPResponse converts a HTTPResponse to a string +func StringifyHTTPResponse(response HTTPResponse) string { + + var jsonBody string + if len(response.JSONBody) == 0 { + jsonBody = "{}" + } else { + jsonBody = response.JSONBody + } + + var textBody string + if len(response.TextBody) == 0 { + textBody = "" + } else { + // avoid special characters in jsonString + textBody = base64.StdEncoding.EncodeToString([]byte(response.TextBody)) + //textBody = retValue.TextBody + } + + jsonHTTPResponse := `{"JSONBody":` + jsonBody + `,"TextBody":"` + textBody + `","Headers":` + response.Headers + `,"StatusCode":` + strconv.Itoa(response.StatusCode) + `}` + + return jsonHTTPResponse +} + //export callHandleHTTP func callHandleHTTP(JSONDataPos *uint32, JSONDataSize uint32) uint64 { - + parser := fastjson.Parser{} JSONDataBuffer := readBufferFromMemory(JSONDataPos, JSONDataSize) @@ -30,9 +52,9 @@ func callHandleHTTP(JSONDataPos *uint32, JSONDataSize uint32) uint64 { Body: string(JSONData.GetStringBytes("Body")), //JSONBody: string(JSONData.GetStringBytes("JSONBody")), //! to use in the future //TextBody: string(JSONData.GetStringBytes("TextBody")), //! to use in the future - URI: string(JSONData.GetStringBytes("URI")), - Method: string(JSONData.GetStringBytes("Method")), - Headers: string(JSONData.GetStringBytes("Headers")), + URI: string(JSONData.GetStringBytes("URI")), + Method: string(JSONData.GetStringBytes("Method")), + Headers: string(JSONData.GetStringBytes("Headers")), } // call the handle function @@ -49,7 +71,7 @@ func callHandleHTTP(JSONDataPos *uint32, JSONDataSize uint32) uint64 { } else { jsonBody = retValue.JSONBody } - + var textBody string if len(retValue.TextBody) == 0 { textBody = "" @@ -59,9 +81,9 @@ func callHandleHTTP(JSONDataPos *uint32, JSONDataSize uint32) uint64 { //textBody = retValue.TextBody } - jsonHTTPResponse := `{"JSONBody":`+jsonBody+`,"TextBody":"`+textBody+`","Headers":`+retValue.Headers+`,"StatusCode":`+strconv.Itoa(retValue.StatusCode)+`}` + jsonHTTPResponse := `{"JSONBody":` + jsonBody + `,"TextBody":"` + textBody + `","Headers":` + retValue.Headers + `,"StatusCode":` + strconv.Itoa(retValue.StatusCode) + `}` // first byte == 82 return success([]byte(jsonHTTPResponse)) -} \ No newline at end of file +} diff --git a/mkdocs.yml b/mkdocs.yml index a1697ad..09d54a9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,7 @@ nav: - First CLI module: first-cli-module.md - First HTTP module: first-http-module.md - 🛠️ Host functions: host-functions.md + - 🧰 Helpers: helpers.md theme: name: material diff --git a/samples/http-say-hello/go.sum b/samples/http-say-hello/go.sum new file mode 100644 index 0000000..a96e182 --- /dev/null +++ b/samples/http-say-hello/go.sum @@ -0,0 +1,4 @@ +github.com/bots-garden/capsule-module-sdk v0.0.3 h1:a0TRgwdiJjc+9raOe4zQoWPnzxKegqmInVmwzlaDuug= +github.com/bots-garden/capsule-module-sdk v0.0.3/go.mod h1:DtKYwanz4YvBwSpu0GuuhtkeFE6+jDgEucBOTWVBMy8= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= diff --git a/samples/http-say-hello/main.go b/samples/http-say-hello/main.go index d1b4c0e..48ee0ad 100644 --- a/samples/http-say-hello/main.go +++ b/samples/http-say-hello/main.go @@ -12,14 +12,14 @@ func main() { capsule.SetHandleHTTP(Handle) } -// Handle function +// Handle function func Handle(param capsule.HTTPRequest) (capsule.HTTPResponse, error) { - + capsule.Print("📝: " + param.Body) capsule.Print("🔠: " + param.Method) capsule.Print("🌍: " + param.URI) capsule.Print("👒: " + param.Headers) - + var p fastjson.Parser jsonBody, err := p.Parse(param.Body) if err != nil { @@ -29,8 +29,8 @@ func Handle(param capsule.HTTPRequest) (capsule.HTTPResponse, error) { capsule.Log(message) response := capsule.HTTPResponse{ - JSONBody: `{"message": "`+message+`"}`, - Headers: `{"Content-Type": "application/json; charset=utf-8"}`, + JSONBody: `{"message": "` + message + `"}`, + Headers: `{"Content-Type": "application/json; charset=utf-8"}`, StatusCode: 200, }