Skip to content

Commit

Permalink
user logs
Browse files Browse the repository at this point in the history
  • Loading branch information
anthdm committed Jan 10, 2024
1 parent 59c3e8e commit 22edb8d
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 37 deletions.
4 changes: 2 additions & 2 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func main() {
}

func seedEndpoint(store storage.Store, cache storage.ModCacher) {
b, err := os.ReadFile("examples/js/index.js")
b, err := os.ReadFile("examples/go/app.wasm")
if err != nil {
log.Fatal(err)
}
endpoint := &types.Endpoint{
ID: uuid.MustParse("09248ef6-c401-4601-8928-5964d61f2c61"),
Runtime: "js",
Runtime: "go",
Name: "Catfact parser",
Environment: map[string]string{"FOO": "bar"},
CreatedAT: time.Now(),
Expand Down
2 changes: 2 additions & 0 deletions examples/go/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"net/http"

raptor "github.com/anthdm/raptor/sdk"
Expand All @@ -20,5 +21,6 @@ func main() {
// router := chi.NewMux()
// router.Get("/dashboard", handleDashboard)
// router.Get("/login", handleLogin)
fmt.Println("user log")
raptor.Handle(http.HandlerFunc(handleLogin))
}
26 changes: 12 additions & 14 deletions examples/js/index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
function generateEndHex(length, status) {
// This should come from the official SDK.
// But there is no official SDK yet, so we keep it here.
function respond(res, status) {
var buffer = new ArrayBuffer(8);
var view = new DataView(buffer);

view.setUint32(0, status, true);
view.setUint32(4, length, true);

var hexString = "";
for (var i = 0; i < buffer.byteLength; i++) {
var hex = view.getUint8(i).toString(16);
hexString += hex.padStart(2, "0");
}
view.setUint32(4, res.length, true);

return hexString;
var bytes = new Uint8Array(buffer);
print(res)
print(bytes)
}

// This should come from the official SDK.
// But there is no official SDK yet, so we keep it here.
function respond(res, status) {
putstr(res+generateEndHex(res.length, status))
}
console.log("user log here")
console.log("user log here")
console.log("user log here")
console.log("user log here")
console.log("user log here")

respond("<h1>From my Raptor application</h1></br>some other stuff here</br>", 200)
2 changes: 1 addition & 1 deletion internal/actrs/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (r *Runtime) handleHTTPRequest(ctx *actor.Context, msg *proto.HTTPRequest)
return
}

res, status, err := shared.ParseRuntimeHTTPResponse(r.stdout.String())
_, res, status, err := shared.ParseStdout(r.stdout)
if err != nil {
respondError(ctx, http.StatusInternalServerError, "invalid response", msg.ID)
return
Expand Down
4 changes: 2 additions & 2 deletions internal/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestRuntimeInvokeJSCode(t *testing.T) {
scriptArgs := []string{"", "-e", string(b)}
require.Nil(t, r.Invoke(bytes.NewReader(breq), nil, scriptArgs...))

_, status, err := shared.ParseRuntimeHTTPResponse(out.String())
_, _, status, err := shared.ParseStdout(out)
require.Nil(t, err)
require.Equal(t, http.StatusOK, status)
require.Nil(t, r.Close())
Expand Down Expand Up @@ -71,7 +71,7 @@ func TestRuntimeInvokeGoCode(t *testing.T) {
r, err := New(context.Background(), args)
require.Nil(t, err)
require.Nil(t, r.Invoke(bytes.NewReader(breq), nil))
_, status, err := shared.ParseRuntimeHTTPResponse(out.String())
_, _, status, err := shared.ParseStdout(out)
require.Nil(t, err)
require.Equal(t, http.StatusOK, status)
require.Nil(t, r.Close())
Expand Down
25 changes: 25 additions & 0 deletions internal/shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,33 @@ import (
"github.com/anthdm/raptor/proto"
)

const magicLen = 8

var errInvalidHTTPResponse = errors.New("invalid HTTP response")

func ParseStdout(stdout io.Reader) (logs []byte, resp []byte, status int, err error) {
stdoutb, err := io.ReadAll(stdout)
if err != nil {
return
}
outLen := len(stdoutb)
if outLen < magicLen {
err = fmt.Errorf("mallformed HTTP response missing last %d bytes", magicLen)
return
}
magicStart := outLen - magicLen
status = int(binary.LittleEndian.Uint32(stdoutb[magicStart : magicStart+4]))
respLen := binary.LittleEndian.Uint32(stdoutb[magicStart+4:])
if int(respLen) > outLen-magicLen {
err = fmt.Errorf("response length exceeds available data")
return
}
respStart := outLen - magicLen - int(respLen)
resp = stdoutb[respStart : respStart+int(respLen)]
logs = stdoutb[:respStart]
return
}

func ParseRuntimeHTTPResponse(in string) (resp string, status int, err error) {
if len(in) < 16 {
err = fmt.Errorf("misformed HTTP response missing last 16 bytes")
Expand Down
105 changes: 91 additions & 14 deletions internal/shared/shared_test.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,104 @@
package shared

import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"log"
"testing"

"github.com/stretchr/testify/require"
)

func BenchmarkParseStdout(b *testing.B) {
userResp := "<h1>This is the actual response</h1>"
statusCode := uint32(200)
userLogs := `
the big brown fox
the big brown fox
the big brown fox
the big brown fox
the big brown fox
`
builder := &bytes.Buffer{}

buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], statusCode)
binary.LittleEndian.PutUint32(buf[4:8], uint32(len(userResp)))

b.ResetTimer()
b.StartTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
builder.WriteString(userLogs)
builder.WriteString(userResp)
builder.Write(buf)
if _, _, _, err := ParseStdout(builder); err != nil {
log.Fatal(err)
}
builder.Reset()
}
b.StopTimer()
}

func TestParseWithoutUserLogs(t *testing.T) {
userResp := "<h1>This is the actual response</h1>"
statusCode := uint32(200)
builder := &bytes.Buffer{}
builder.WriteString(userResp)

// += userResp
buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], statusCode)
binary.LittleEndian.PutUint32(buf[4:8], uint32(len(userResp)))
builder.Write(buf)

logs, resp, status, err := ParseStdout(builder)
require.Nil(t, err)
require.Equal(t, int(statusCode), status)
require.Equal(t, userResp, string(resp))
require.Equal(t, []byte{}, logs)
}

func TestParseWithUserLogs(t *testing.T) {
userResp := "<h1>This is the actual response</h1>"
statusCode := uint32(200)
userLogs := `
the big brown fox
the big brown fox
the big brown fox
the big brown fox
the big brown fox
`
builder := &bytes.Buffer{}
builder.WriteString(userLogs)
builder.WriteString(userResp)

// += userResp
buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], statusCode)
binary.LittleEndian.PutUint32(buf[4:8], uint32(len(userResp)))
builder.Write(buf)

logs, resp, status, err := ParseStdout(builder)
require.Nil(t, err)
require.Equal(t, int(statusCode), status)
require.Equal(t, userResp, string(resp))
require.Equal(t, userLogs, string(logs))
}

func TestParseRuntimeHTTPResponse(t *testing.T) {
t.Run("multiline response", func(t *testing.T) {
text := "This is the best.\nBut not always correct.\nThe big brown fox."
statusCode := uint32(500)

buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], statusCode)
binary.LittleEndian.PutUint32(buf[4:8], uint32(len(text)))

in := fmt.Sprintf("%s%s", text, hex.EncodeToString(buf))
resp, status, err := ParseRuntimeHTTPResponse(in)
require.Nil(t, err)
require.Equal(t, int(statusCode), status)
require.Equal(t, text, resp)
})
text := "This is the best.\nBut not always correct.\nThe big brown fox."
statusCode := uint32(500)

buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], statusCode)
binary.LittleEndian.PutUint32(buf[4:8], uint32(len(text)))

in := fmt.Sprintf("%s%s", text, hex.EncodeToString(buf))
resp, status, err := ParseRuntimeHTTPResponse(in)
require.Nil(t, err)
require.Equal(t, int(statusCode), status)
require.Equal(t, text, resp)
}
6 changes: 2 additions & 4 deletions sdk/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package run
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"log"
"net/http"
Expand Down Expand Up @@ -46,12 +44,12 @@ func Handle(h http.Handler) {
r.Header[k] = v.Fields
}
h.ServeHTTP(w, r) // execute the user's handler
fmt.Print(w.buffer.String())
os.Stdout.Write(w.buffer.Bytes())

buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:4], uint32(w.statusCode))
binary.LittleEndian.PutUint32(buf[4:8], uint32(w.buffer.Len()))
fmt.Print(hex.EncodeToString(buf))
os.Stdout.Write(buf)
}

type ResponseWriter struct {
Expand Down

0 comments on commit 22edb8d

Please sign in to comment.