Skip to content

Commit

Permalink
Merge pull request #34 from mutablelogic/v1
Browse files Browse the repository at this point in the history
Added a JSON streaming callback
  • Loading branch information
djthorpe authored Jul 27, 2024
2 parents c538601 + 78c4a59 commit ba67161
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 6 deletions.
21 changes: 19 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"io"
"mime"
Expand Down Expand Up @@ -47,6 +48,10 @@ type Client struct {

type ClientOpt func(*Client) error

// Callback for json stream events, return an error if you want to stop streaming
// with an error and io.EOF if you want to stop streaming and return success
type JsonStreamCallback func(v any) error

///////////////////////////////////////////////////////////////////////////////
// GLOBALS

Expand Down Expand Up @@ -302,8 +307,20 @@ func do(client *http.Client, req *http.Request, accept string, strict bool, out
// Decode the body
switch mimetype {
case ContentTypeJson:
if err := json.NewDecoder(response.Body).Decode(out); err != nil {
return err
// JSON decode is streamable
dec := json.NewDecoder(response.Body)
for {
if err := dec.Decode(out); err == io.EOF {
break
} else if err != nil {
return err
} else if reqopts.jsonStreamCallback != nil {
if err := reqopts.jsonStreamCallback(out); errors.Is(err, io.EOF) {
break
} else if err != nil {
return err
}
}
}
case ContentTypeTextStream:
if err := NewTextStream().Decode(response.Body, reqopts.textStreamCallback); err != nil {
Expand Down
90 changes: 90 additions & 0 deletions cmd/api/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"context"
"time"

// Packages
tablewriter "github.com/djthorpe/go-tablewriter"
client "github.com/mutablelogic/go-client"
auth "github.com/mutablelogic/go-server/pkg/handler/auth/client"
)

var (
authClient *auth.Client
authName = "tokenauth"
authDuration time.Duration
)

func authRegister(flags *Flags) {
// Register flags
flags.String(authName, "tokenauth-endpoint", "${TOKENAUTH_ENDPOINT}", "tokenauth endpoint (ie, http://host/api/auth/)")
flags.String(authName, "tokenauth-token", "${TOKENAUTH_TOKEN}", "tokenauth token")
flags.Duration(authName, "expiry", 0, "token expiry duration")

// Register commands
flags.Register(Cmd{
Name: authName,
Description: "Manage token authentication",
Parse: authParse,
Fn: []Fn{
// Default caller
{Call: authList, Description: "List authentication tokens"},
{Name: "list", Call: authList, Description: "List authentication tokens"},
{Name: "create", Call: authCreate, Description: "Create a token", MinArgs: 1},
{Name: "delete", Call: authDelete, Description: "Delete a token", MinArgs: 1, MaxArgs: 1},
},
})
}

func authParse(flags *Flags, opts ...client.ClientOpt) error {
endpoint := flags.GetString("tokenauth-endpoint")
if token := flags.GetString("tokenauth-token"); token != "" {
opts = append(opts, client.OptReqToken(client.Token{
Scheme: "Bearer",
Value: token,
}))
}

if duration := flags.GetString("expiry"); duration != "" {
if d, err := time.ParseDuration(duration); err != nil {
return err
} else {
authDuration = d
}
}

if client, err := auth.New(endpoint, opts...); err != nil {
return err
} else {
authClient = client
}
return nil
}

func authList(_ context.Context, w *tablewriter.Writer, _ []string) error {
tokens, err := authClient.List()
if err != nil {
return err
}
return w.Write(tokens)
}

func authCreate(_ context.Context, w *tablewriter.Writer, params []string) error {
name := params[0]
scopes := params[1:]
token, err := authClient.Create(name, authDuration, scopes...)
if err != nil {
return err
}
return w.Write(token)
}

func authDelete(ctx context.Context, w *tablewriter.Writer, params []string) error {
name := params[0]
err := authClient.Delete(name)
if err != nil {
return err
}
return authList(ctx, w, nil)
}
1 change: 1 addition & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func main() {

// Register commands
anthropicRegister(flags)
authRegister(flags)
bwRegister(flags)
elRegister(flags)
haRegister(flags)
Expand Down
48 changes: 48 additions & 0 deletions cmd/api/nginx.go_old
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"context"

// Packages
tablewriter "github.com/djthorpe/go-tablewriter"
client "github.com/mutablelogic/go-client"
nginx "github.com/mutablelogic/go-server/pkg/handler/nginx/client"
)

var (
nginxClient *nginx.Client
nginxName = "nginx"
nginxEndpoint string
)

func nginxRegister(flags *Flags) {
flags.Register(Cmd{
Name: nginxName,
Description: "Manage nginx instances",
Parse: nginxParse,
Fn: []Fn{
// Default caller
{Call: nginxGetVersion, Description: "Get the nginx version that is running"},
},
})
}

func nginxParse(flags *Flags, opts ...client.ClientOpt) error {
// Register flags
flags.String(nginxName, "nginx-endpoint", "${NGINX_ENDPOINT}", "nginx endpoint")

if client, err := nginx.New(nginxEndpoint, opts...); err != nil {
return err
} else {
nginxClient = client
}
return nil
}

func nginxGetVersion(_ context.Context, w *tablewriter.Writer, _ []string) error {
version, _, err := nginxClient.Health()
if err != nil {
return err
}
return w.Write(version)
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ toolchain go1.22.3
require (
github.com/andreburgaud/crypt2go v1.5.0
github.com/djthorpe/go-errors v1.0.3
github.com/djthorpe/go-tablewriter v0.0.6
github.com/djthorpe/go-tablewriter v0.0.7
github.com/go-audio/audio v1.0.0
github.com/go-audio/wav v1.1.0
github.com/mutablelogic/go-server v1.4.7
github.com/stretchr/testify v1.9.0
github.com/xdg-go/pbkdf2 v1.0.0
golang.org/x/crypto v0.23.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/djthorpe/go-errors v1.0.3 h1:GZeMPkC1mx2vteXLI/gvxZS0Ee9zxzwD1mcYyKU5jD0=
github.com/djthorpe/go-errors v1.0.3/go.mod h1:HtfrZnMd6HsX75Mtbv9Qcnn0BqOrrFArvCaj3RMnZhY=
github.com/djthorpe/go-tablewriter v0.0.6 h1:iGi1eln0KEknJUH9AtPeTeOUcioilDRs7QruyRcmtWM=
github.com/djthorpe/go-tablewriter v0.0.6/go.mod h1:LL+Dxaepm8Q0qUVD9EB6+d0xr7I7OgQYEfrugI8fBUA=
github.com/djthorpe/go-tablewriter v0.0.7 h1:jnNsJDjjLLCt0OAqB5DzGZN7V3beT1IpNMQ8GcOwZDU=
github.com/djthorpe/go-tablewriter v0.0.7/go.mod h1:NVBvytpL+6fHfCKn0+3lSi15/G3A1HWf2cLNeHg6YBg=
github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
Expand All @@ -14,6 +14,8 @@ github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g=
github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mutablelogic/go-server v1.4.7 h1:NpzG30f/D50Xbwr96dA6uiapyr4QHBziSanc/q/LR7k=
github.com/mutablelogic/go-server v1.4.7/go.mod h1:wrrDg863hlv5/DUpSG/Pb4k9LiSYO7VxRgLPiMhrE6M=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
Expand Down
2 changes: 1 addition & 1 deletion pkg/multipart/multipart.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewMultipartEncoder(w io.Writer) *Encoder {
}
}

// NewFormEncoder creates a new encoder object, whichwrites
// NewFormEncoder creates a new encoder object, which writes
// application/x-www-form-urlencoded to the io.Writer
func NewFormEncoder(w io.Writer) *Encoder {
return &Encoder{
Expand Down
9 changes: 9 additions & 0 deletions requestopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type requestOpts struct {
*http.Request
noTimeout bool // OptNoTimeout
textStreamCallback TextStreamCallback // OptTextStreamCallback
jsonStreamCallback JsonStreamCallback // OptJsonStreamCallback
}

type RequestOpt func(*requestOpts) error
Expand Down Expand Up @@ -103,3 +104,11 @@ func OptTextStreamCallback(fn TextStreamCallback) RequestOpt {
return nil
}
}

// OptJsonStreamCallback is called for each decoded JSON event
func OptJsonStreamCallback(fn JsonStreamCallback) RequestOpt {
return func(r *requestOpts) error {
r.jsonStreamCallback = fn
return nil
}
}

0 comments on commit ba67161

Please sign in to comment.