GitHub - GoogleCloudPlatform/ezcx (original) (raw)

ezcx is a framework for building containerized Dialogflow CX webhook fulfillment APIs. ezcx runs happiest on Google's Cloud Run service.

ezcx was designed to remove most (if not all) the complexity associated with building Dialogflow CX webhook fulfillment APIs:

func CxHandler(res *ezcx.WebhookResponse, req *ezcx.WebhookRequest) error { // Add text res.AddTextResponse("Made with ezcx in 5 minutes or less...")

// Add SSML
res.AddOutputAudioTextResponse("<ssml>Made with ezcx in <prosody rate=slow>5 minutes </prosody>or less...</ssml>")    

// Add Session Parameters
params = make(map[string]any)
params["made_with"] = "ezcx"
res.AddSessionParameters(params)

return nil

}

type HandlerFunc func(*WebhookResponse, *WebhookRequest) error

// Ignore for now. func (h HandlerFunc) Handle(res *WebhookResponse, req *WebhookRequest) error { return h(res, req) }

// Implements the http.Handler interface - this is relatively low level; // ezcx "handles" this for you, instead, allowing you to focus on what really matters: // working with the data in WebhookRequest and returning a WebhookResponse. func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() req, err := WebhookRequestFromRequest(r) if err != nil { log.Println(err) return } res := req.PrepareResponse() err = h.Handle(res, req) if err != nil { log.Println(err) return } res.WriteResponse(w) }

// main.go package main

import ( "context" "fmt" "log"

"github.com/googlecloudplatform/ezcx"

)

func main() { parent := context.Background() lg := log.Default()

server := ezcx.NewServer(parent, ":8082", lg)
// HandleCx adapts ezcx.HandlerFunc into an http.Handler for you!
server.HandleCx("/from-dfcx", CxHandler)
server.ListenAndServe(parent)

}

Handlers have been moved to a separate file to show just how little effort is required. server.HandleCx adapts an ezcx.HandlerFunc into an http.Handler for you!

// handlers.go func CxHandler(res *ezcx.WebhookResponse, req *ezcx.WebhookRequest) error { // Read parameters. params, err := req.GetSessionParameters() if err != nil { return err } callerName := params["caller-name"]

// Update your response.
res.AddTextResponse(fmt.Sprintf("Hi there %s, how are you?", callerName))

// Update some session parameters
params["saidHi"] = true
err = res.AddSessionParameters(params)
if err != nil {
    return err
}

return nil

}

Basic Usage

Request-scoped Web Service Calls.

ezcx's WebhookRequest flows down http.Request's context; this context is accessible via the WebhookRequest's Context() method. Under the hood, WebhookRequests.Context() method is just a pass-through for (*http.Request).Context().

func CxHandler(res *ezcx.WebhookResponse, req *ezcx.WebhookRequest) error { ... ctx := req.Context() apiResult, err := makeWebServiceCall(ctx, ...callOpts) if err != nil { return err } ... return nil }

Testing

More on testing coming soon!

Examples

Please visit the examples folder to check out how ezcx stacks up!

Dockerfile

Provided for convenience.

FROM golang:1.18-buster as builder WORKDIR /app COPY . ./ RUN go build -o service

FROM debian:buster-slim RUN set -x &&
apt-get update &&
DEBIAN_FRONTEND=noninteractive apt-get install -y
ca-certificates &&
rm -rf /var/lib/apt/lists/* COPY --from=builder /app/service /app/service

CMD ["/app/service"]

Cloud Build

Provided for convenience. Review all the parameters for deploying to Cloud Run before issuing a gcloud builds submit!

steps:

substitutions: _SERVICE: ezcx-service _REGION: us-central-1

Backlog

Testing

EmptyWebhookRequest

Review the initialization of emptyWebhookRequest which is used for testing webhooks. I need to add a place for "pageInfo" which is an object that's rarely used. Details on pageInfo here: https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/dialogflow/cx/v3#PageInfo

Updates