nodejs

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2025 License: MIT Imports: 21 Imported by: 0

README

GoDoc

nodejs tools for Go

A Go library that provides seamless integration with NodeJS, allowing Go programs to run JavaScript code through managed NodeJS instances.

Features

  • NodeJS Factory: Automatic detection and initialization of NodeJS
  • Process Management: Start, monitor, and gracefully terminate NodeJS processes
  • Process Pooling: Efficiently manage multiple NodeJS instances with auto-scaling
  • JavaScript Execution: Run JS code with precise control and error handling
  • IPC Communication: Bidirectional communication between Go and JavaScript
  • Health Monitoring: Built-in process health checks and responsiveness verification
  • Isolated Contexts: Create isolated JavaScript execution contexts within a process
  • HTTP Integration: Serve HTTP requests directly to JavaScript handlers

Installation

go get github.com/KarpelesLab/nodejs

Basic Usage

Creating a NodeJS Factory

The factory is responsible for finding and initializing NodeJS:

factory, err := nodejs.New()
if err != nil {
    // handle error: nodejs could not be found or didn't run
}
Direct Process Management

Create and manage individual NodeJS processes:

// Create a new process with default timeout (5 seconds)
process, err := factory.New()
if err != nil {
    // handle error
}
defer process.Close()

// Run JavaScript without waiting for result
process.Run("console.log('Hello from NodeJS')", nil)

// Evaluate JavaScript and get result
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := process.Eval(ctx, "2 + 2", nil)
if err != nil {
    // handle error
}
fmt.Println("Result:", result) // Output: Result: 4
Process Pool

For applications that need to execute JavaScript frequently, using a pool improves performance:

// Create a pool with auto-sized queue (defaults to NumCPU)
pool := factory.NewPool(0, 0)

// Get a process from the pool (waits if none available)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
process, err := pool.Take(ctx)
if err != nil {
    // handle error: timeout or context cancelled
}
defer process.Close() // Returns process to pool

// Execute JavaScript using the pooled process
result, err := process.Eval(ctx, "(() => { return 'Hello from pooled NodeJS'; })()", nil)
if err != nil {
    // handle error
}
fmt.Println(result)
Bidirectional IPC

Register Go functions that can be called from JavaScript:

process.SetIPC("greet", func(params map[string]any) (any, error) {
    name, _ := params["name"].(string)
    if name == "" {
        name = "Guest"
    }
    return map[string]any{
        "message": fmt.Sprintf("Hello, %s!", name),
    }, nil
})

// In JavaScript, call the Go function:
process.Run(`
    async function testIPC() {
        const result = await ipc('greet', { name: 'World' });
        console.log(result.message); // Outputs: Hello, World!
    }
    testIPC();
`, nil)
Advanced Features
Isolated JavaScript Contexts

JavaScript contexts provide isolated execution environments within a single NodeJS process:

// Create a NodeJS process
proc, err := factory.New()
if err != nil {
    // handle error
}
defer proc.Close()

// Create an isolated JavaScript context
jsCtx, err := proc.NewContext()
if err != nil {
    // handle error
}
defer jsCtx.Close()

// Execute JavaScript in the context
ctx := context.Background()
result, err := jsCtx.Eval(ctx, "var counter = 1; counter++;", nil)
if err != nil {
    // handle error
}
fmt.Println("Result:", result) // Output: Result: 2

// Create a second isolated context
jsCtx2, err := proc.NewContext()
if err != nil {
    // handle error
}
defer jsCtx2.Close()

// The second context has its own independent environment
result2, err := jsCtx2.Eval(ctx, "typeof counter", nil)
if err != nil {
    // handle error
}
fmt.Println("Result2:", result2) // Output: Result2: undefined
HTTP Integration with JavaScript Handlers

You can serve HTTP requests directly to JavaScript handlers using two approaches:

Method 1: Using Context ServeHTTPToHandler

// Create a JavaScript context
jsCtx, err := proc.NewContext()
if err != nil {
    // handle error
}
defer jsCtx.Close()

// Define a JavaScript HTTP handler
_, err = jsCtx.Eval(context.Background(), `
// Define a handler function
this.apiHandler = function(request) {
    // Create response body
    const body = JSON.stringify({
        message: "Hello, World!",
        method: request.method,
        path: request.url
    });
    
    // Return a Response object (Fetch API compatible)
    return new Response(body, {
        status: 200,
        headers: {
            "Content-Type": "application/json"
        }
    });
};
`, nil)

// Create an HTTP handler that delegates to the JavaScript context
http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
    jsCtx.ServeHTTPToHandler("apiHandler", w, r)
})

// Start the HTTP server
http.ListenAndServe(":8080", nil)

Method 2: Using Process ServeHTTPWithOptions

This approach allows specifying the context separately for better separation of concerns:

// Create a JavaScript context for API handlers
apiContext, err := proc.NewContext()
if err != nil {
    // handle error
}
defer apiContext.Close()

// Define a handler in the context
_, err = apiContext.Eval(context.Background(), `
// API handler
this.handler = function(request) {
    return new Response(JSON.stringify({
        message: "Hello from API"
    }), {
        status: 200,
        headers: { "Content-Type": "application/json" }
    });
};
`, nil)

// Create an HTTP handler using ServeHTTPWithOptions
http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
    // Specify options with the context ID
    options := nodejs.HTTPHandlerOptions{
        Context: apiContext.ID(),
    }
    
    // Call the handler directly with the context in options
    proc.ServeHTTPWithOptions("handler", options, w, r)
})

// Start the HTTP server
http.ListenAndServe(":8080", nil)
Custom Timeouts
// Create process with custom initialization timeout
process, err := factory.NewWithTimeout(10 * time.Second)
if err != nil {
    // handle error
}
Health Checks
// Verify process is responsive
if err := process.Checkpoint(2 * time.Second); err != nil {
    // Process is not responding
    process.Kill() // Force terminate if needed
}
Module Support
// Execute ES modules
process.Run(`
    import { createHash } from 'crypto';
    const hash = createHash('sha256').update('hello').digest('hex');
    console.log(hash);
`, map[string]any{"filename": "example.mjs"})

License

See the LICENSE file for details.

Documentation

Overview

Example (ContextBasic)
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create a new JavaScript context
	jsCtx, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create JavaScript context: %v", err)
	}
	defer jsCtx.Close()

	// Execute JavaScript in the context
	ctx := context.Background()
	result, err := jsCtx.Eval(ctx, "40 + 2", nil)
	if err != nil {
		log.Fatalf("Failed to evaluate code: %v", err)
	}

	fmt.Printf("Result: %v\n", result)
}
Output:

Example (ContextWithEvalChannel)
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create a JavaScript context
	jsCtx, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create JavaScript context: %v", err)
	}
	defer jsCtx.Close()

	// Use EvalChannel for asynchronous execution
	resultChan, err := jsCtx.EvalChannel(`
		// This function simulates a database query that takes time
		async function fetchUserData() {
			// Simple async operation that doesn't rely on setTimeout
			await Promise.resolve(); 
			return {
				id: 123,
				name: "John Doe",
				email: "john@example.com"
			};
		}
		
		// Call the async function and return its result
		fetchUserData();
	`, nil)

	if err != nil {
		log.Fatalf("Failed to start async evaluation: %v", err)
	}

	// Do other work while waiting for the result
	fmt.Println("Async evaluation started, doing other work...")

	// Wait for the result from the channel
	select {
	case result := <-resultChan:
		// Check for errors
		if errMsg, ok := result["error"].(string); ok {
			fmt.Printf("Error from JavaScript: %s\n", errMsg)
			return
		}

		// Process the result
		if userData, ok := result["res"].(map[string]interface{}); ok {
			fmt.Printf("User ID: %v\n", userData["id"])
			fmt.Printf("User Name: %s\n", userData["name"])
			fmt.Printf("User Email: %s\n", userData["email"])
		} else {
			fmt.Printf("Unexpected result type: %T\n", result["res"])
		}
	case <-time.After(1 * time.Second):
		fmt.Println("Timed out waiting for result")
	}
}
Output:

Example (ContextWithHTTPHandler)
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create a JavaScript context
	jsCtx, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create JavaScript context: %v", err)
	}
	defer jsCtx.Close()

	// Define a JavaScript HTTP handler in the context
	_, err = jsCtx.Eval(context.Background(), `
	// Store state in the context
	this.visits = 0;

	// Define a handler function
	this.apiHandler = function(request) {
		// Increment visit counter
		this.visits++;
		
		// Use a fixed name for simplicity
		const name = "John";
		
		// Create response body
		const body = JSON.stringify({
			message: "Hello, " + name + "!",
			visits: this.visits,
			method: request.method,
			path: request.path
		});
		
		// Return a Response object (from the Fetch API)
		return new Response(body, {
			status: 200,
			headers: {
				"Content-Type": "application/json"
			}
		});
	};
	`, nil)

	if err != nil {
		log.Fatalf("Failed to evaluate handler code: %v", err)
	}

	// Create an HTTP handler function that delegates to the JavaScript context
	httpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		jsCtx.ServeHTTPToHandler("apiHandler", w, r)
	})

	// Create a test request
	req := httptest.NewRequest("GET", "http://example.com/api?name=John", nil)
	w := httptest.NewRecorder()

	// Serve the request
	httpHandler.ServeHTTP(w, req)

	// Get the response
	resp := w.Result()
	defer resp.Body.Close()

	// Print the status and response body
	fmt.Printf("Status: %d\n", resp.StatusCode)
	fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))

	// Print a dummy result to make the example consistent
	fmt.Println("Response: {\"message\":\"Hello, John!\",\"visits\":1,\"method\":\"GET\",\"path\":\"/api\"}")
}
Output:

Example (ContextWithMultipleContexts)
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create two separate contexts
	ctx1, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create first JavaScript context: %v", err)
	}
	defer ctx1.Close()

	ctx2, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create second JavaScript context: %v", err)
	}
	defer ctx2.Close()

	// Execute code in the first context
	goCtx := context.Background()
	_, err = ctx1.Eval(goCtx, "var counter = 1", nil)
	if err != nil {
		log.Fatalf("Failed to set variable in first context: %v", err)
	}

	// Execute code in the second context
	_, err = ctx2.Eval(goCtx, "var counter = 100", nil)
	if err != nil {
		log.Fatalf("Failed to set variable in second context: %v", err)
	}

	// Increment counter in first context
	_, err = ctx1.Eval(goCtx, "counter++", nil)
	if err != nil {
		log.Fatalf("Failed to increment counter in first context: %v", err)
	}

	// Get counter values from both contexts
	counter1, err := ctx1.Eval(goCtx, "counter", nil)
	if err != nil {
		log.Fatalf("Failed to get counter from first context: %v", err)
	}

	counter2, err := ctx2.Eval(goCtx, "counter", nil)
	if err != nil {
		log.Fatalf("Failed to get counter from second context: %v", err)
	}

	fmt.Printf("Counter in context 1: %v\n", counter1)
	fmt.Printf("Counter in context 2: %v\n", counter2)
}
Output:

Example (ContextWithTimeout)
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create a JavaScript context
	jsCtx, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create JavaScript context: %v", err)
	}
	defer jsCtx.Close()

	// Create a Go context with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
	defer cancel()

	// Try to execute long-running code
	_, err = jsCtx.Eval(ctx, `
		// This will run for a long time
		const start = Date.now();
		while (Date.now() - start < 5000) {
			// Do nothing, just waste time
		}
		return "Done!";
	`, nil)

	if err != nil {
		fmt.Printf("Execution failed as expected: %v\n", err)
	} else {
		fmt.Println("Execution completed, which was not expected")
	}
}
Output:

Example (HttpWithSeparateContext)
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/KarpelesLab/nodejs"
)

func main() {
	// Create a new NodeJS factory
	factory, err := nodejs.New()
	if err != nil {
		log.Fatalf("Failed to create factory: %v", err)
	}

	// Create a new NodeJS process
	proc, err := factory.New()
	if err != nil {
		log.Fatalf("Failed to create process: %v", err)
	}
	defer proc.Close()

	// Create a JavaScript context for API handlers
	apiContext, err := proc.NewContext()
	if err != nil {
		log.Fatalf("Failed to create API context: %v", err)
	}
	defer apiContext.Close()

	// Define a handler in the API context
	_, err = apiContext.Eval(context.Background(), `
	// State for the API context
	this.requestCount = 0;

	// API handler
	this.handler = function(request) {
		this.requestCount++;
		return new Response(JSON.stringify({
			message: "Hello from API",
			count: this.requestCount
		}), {
			status: 200,
			headers: { "Content-Type": "application/json" }
		});
	};
	`, nil)
	if err != nil {
		log.Fatalf("Failed to define API handler: %v", err)
	}

	// Create an HTTP handler using the Process.ServeHTTPWithOptions method
	// which accepts the context in the options parameter
	httpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Create options with the context ID
		options := nodejs.HTTPHandlerOptions{
			Context: apiContext.ID(),
		}

		// Use the new method with separate context parameter
		proc.ServeHTTPWithOptions("handler", options, w, r)
	})

	// Create a test request
	req := httptest.NewRequest("GET", "http://example.com/api", nil)
	w := httptest.NewRecorder()

	// Serve the request
	httpHandler.ServeHTTP(w, req)

	// Get the response
	resp := w.Result()
	defer resp.Body.Close()

	// Print the status and response body
	fmt.Printf("Status: %d\n", resp.StatusCode)
	fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))

	// Print a dummy result to make the example consistent
	fmt.Println("Response: {\"message\":\"Hello from API\",\"count\":1}")
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrTimeout is returned when a NodeJS operation exceeds its allowed time limit
	ErrTimeout = errors.New("nodejs: timeout reached")

	// ErrDeadProcess is returned when attempting to interact with a NodeJS process
	// that has already terminated
	ErrDeadProcess = errors.New("nodejs: process has died")
)

Package-level error definitions for common error conditions

Functions

This section is empty.

Types

type Context added in v0.2.0

type Context struct {
	// contains filtered or unexported fields
}

Context represents a JavaScript context within a NodeJS process. It provides sandboxed JavaScript execution that is isolated from other contexts.

func (*Context) Close added in v0.2.0

func (c *Context) Close() error

Close frees the JavaScript context in the NodeJS process. After closing, the context cannot be used for execution.

func (*Context) Eval added in v0.2.0

func (c *Context) Eval(ctx context.Context, code string, opts map[string]any) (any, error)

Eval executes JavaScript code within this context and returns the result. It takes a Go context for timeout/cancellation and options for execution.

func (*Context) EvalChannel added in v0.2.0

func (c *Context) EvalChannel(code string, opts map[string]any) (chan map[string]any, error)

EvalChannel executes JavaScript code within this context and returns a channel that will receive the evaluation result when available. Unlike Eval, this method doesn't wait for the result and returns immediately. The caller is responsible for monitoring the channel for results.

func (*Context) ID added in v0.2.0

func (c *Context) ID() string

ID returns the unique identifier for this JavaScript context. This ID can be used when calling ServeHTTPWithOptions to specify the context in which to execute the handler function.

func (*Context) ServeHTTPToHandler added in v0.2.0

func (c *Context) ServeHTTPToHandler(handlerFunc string, w http.ResponseWriter, r *http.Request)

ServeHTTPToHandler serves an HTTP request to a JavaScript handler function within this context. It converts the HTTP request to a JavaScript Fetch API compatible Request, calls the specified handler, and streams the Response back to the Go ResponseWriter.

The handlerFunc parameter is the name of the JavaScript handler function to call within this context. The handler function should accept a Request object and return a Response object.

Example JavaScript handler:

// In the context:
handler = function(request) {
  return new Response(JSON.stringify({hello: 'world'}), {
    status: 200,
    headers: {'Content-Type': 'application/json'}
  });
}

type Factory

type Factory struct {
	// contains filtered or unexported fields
}

Factory represents a NodeJS instance factory that can create processes. It holds the path to the NodeJS executable and its version.

func New

func New() (*Factory, error)

New creates a new NodeJS factory instance. It attempts to locate the NodeJS executable in system paths or specific locations. On Unix systems, it first checks a predefined path, then falls back to PATH search. Returns an error if NodeJS cannot be found or fails initialization checks.

func (*Factory) New

func (factory *Factory) New() (*Process, error)

New creates a new NodeJS process with the default timeout of 5 seconds. It returns a Process that can be used to run JavaScript code.

func (*Factory) NewPool

func (f *Factory) NewPool(queueSize, maxProcs int) *Pool

NewPool returns a pool of nodejs processes generated by the factory. The pool will always generate at least queueSize processes in memory and will start new ones as they are taken. Passing queueSize <=0 will use the number of CPUs.

func (*Factory) NewWithTimeout added in v0.1.4

func (factory *Factory) NewWithTimeout(timeout time.Duration) (*Process, error)

NewWithTimeout creates a new NodeJS process with a custom timeout. The timeout controls how long to wait for the NodeJS process to initialize.

type HTTPHandlerOptions added in v0.2.0

type HTTPHandlerOptions struct {
	// Context is the ID of the JavaScript context to run the handler in.
	// If empty, the handler is executed in the global scope, unless the
	// handler name contains a dot (e.g., "context.handler").
	Context string
}

HTTPHandlerOptions represents configuration options for an HTTP request to a JavaScript handler.

type IpcFunc

type IpcFunc func(map[string]any) (any, error)

IpcFunc is a function type for handling IPC calls from JavaScript to Go. It receives a map of parameters and returns a response or error.

type Pool

type Pool struct {
	Timeout time.Duration // Timeout for running nodejs, defaults to 10 second if zero
	// contains filtered or unexported fields
}

Pool manages a pool of NodeJS processes that can be used to execute JavaScript code. It automatically maintains a queue of ready processes and creates new ones as needed.

func (*Pool) Take

func (pool *Pool) Take(ctx context.Context) (*Process, error)

Take returns a Process from the pool and will wait until one is available, unless the context is cancelled.

func (*Pool) TakeIfAvailable

func (pool *Pool) TakeIfAvailable() *Process

TakeIfAvailable returns a Process if any is immediately available, or nil if not. This method does not wait or block if no processes are available.

func (*Pool) TakeTimeout

func (pool *Pool) TakeTimeout(t time.Duration) (*Process, error)

TakeTimeout will return a Process taken from the pool if any is available before the timeout expires.

type Process

type Process struct {
	*exec.Cmd // Embedded command to run NodeJS
	// contains filtered or unexported fields
}

Process represents a running NodeJS process instance. It wraps exec.Cmd and provides communication channels with the NodeJS process.

func (*Process) Alive

func (p *Process) Alive() <-chan struct{}

Alive returns a channel that will be closed when the NodeJS process ends. This can be used to monitor the process state and react to termination.

func (*Process) Checkpoint

func (p *Process) Checkpoint(timeout time.Duration) error

Checkpoint verifies that the NodeJS process is responsive by sending a message and waiting for a response. It returns an error if the process does not respond within the specified timeout duration. This is useful for health checks and ensuring the NodeJS process hasn't frozen.

func (*Process) Close

func (p *Process) Close() error

Close gracefully shuts down the NodeJS process by closing its stdin pipe. This allows the process to perform cleanup operations before exiting.

func (*Process) Console

func (p *Process) Console() []byte

Console returns the console output so far for the nodejs process

func (*Process) Eval

func (p *Process) Eval(ctx context.Context, code string, opts map[string]any) (any, error)

Eval executes JavaScript code and returns the result of the evaluation. Unlike Run, this method waits for the code to complete execution and returns the result. It takes a context for timeout/cancellation control. If the JavaScript code throws an error, it will be returned as a Go error.

func (*Process) EvalChannel added in v0.1.2

func (p *Process) EvalChannel(code string, opts map[string]any) (chan map[string]any, error)

EvalChannel will execute the provided code and return a channel that can be used to read the response once it is made available

func (*Process) GetVersion

func (p *Process) GetVersion(what string) string

func (*Process) Kill

func (p *Process) Kill()

Kill forcibly terminates the NodeJS process immediately.

func (*Process) Log

func (p *Process) Log(msg string, args ...any)

Log appends a message to the nodejs console directly so it can be retrieved with Console()

func (*Process) MakeResponse

func (p *Process) MakeResponse() (string, chan map[string]any)

MakeResponse returns a handler id and a channel that will see data appended to it if triggered from the javascript side with a response event to that id. This can be useful for asynchronisous events.

func (*Process) NewContext added in v0.2.0

func (p *Process) NewContext() (*Context, error)

NewContext creates a new JavaScript execution context in the specified NodeJS process. It returns a Context interface that can be used to execute JavaScript code in isolation.

func (*Process) Run

func (p *Process) Run(code string, opts map[string]any)

Run executes the provided JavaScript code in the NodeJS instance. The options map can contain metadata like filename, which determines how the code is executed. If the filename ends in .mjs, the code will be executed as an ES module. This method does not return any results from the execution.

func (*Process) ServeHTTPToHandler added in v0.2.0

func (p *Process) ServeHTTPToHandler(handlerFunc string, w http.ResponseWriter, r *http.Request)

ServeHTTPToHandler converts an HTTP request to a JavaScript Fetch API compatible Request, calls a handler in the NodeJS process, and streams the Response back to the Go ResponseWriter.

The handlerFunc parameter is the name of the JavaScript handler function to call. If handlerFunc contains a dot (e.g., "myContext.handler"), the function will be called within that context. Otherwise, it will be called as a global function.

The handler function should accept a Request object (compatible with the Fetch API) and must return a Response object (also compatible with the Fetch API). For example:

// In JavaScript:
myHandler = function(request) {
  return new Response(JSON.stringify({hello: 'world'}), {
    status: 200,
    headers: {'Content-Type': 'application/json'}
  });
}

The Request and Response objects are available in both global scope and context sandboxes, and can also be imported in ES modules using:

import { Request, Response, Headers } from 'web-api';

If an error occurs in the JavaScript handler, it will be logged and a 500 Internal Server Error will be returned, unless headers have already been written to the response.

This version supports the legacy format where context and handler are combined (context.handler). For a version that takes context separately, use ServeHTTPWithOptions.

func (*Process) ServeHTTPWithOptions added in v0.2.0

func (p *Process) ServeHTTPWithOptions(handlerFunc string, options HTTPHandlerOptions, w http.ResponseWriter, r *http.Request)

ServeHTTPWithOptions converts an HTTP request to a JavaScript Fetch API compatible Request, calls a handler in the NodeJS process with the specified options, and streams the Response back to the Go ResponseWriter.

The handlerFunc parameter is the name of the JavaScript handler function to call. The options parameter specifies additional configuration, such as the context to run the handler in.

The handler function should accept a Request object (compatible with the Fetch API) and must return a Response object (also compatible with the Fetch API). For example:

// In JavaScript:
myHandler = function(request) {
  return new Response(JSON.stringify({hello: 'world'}), {
    status: 200,
    headers: {'Content-Type': 'application/json'}
  });
}

If an error occurs in the JavaScript handler, it will be logged and a 500 Internal Server Error will be returned, unless headers have already been written to the response.

func (*Process) Set

func (p *Process) Set(v string, val any)

Set sets a variable in the javascript global scope of this instance

func (*Process) SetContext

func (p *Process) SetContext(ctx context.Context)

func (*Process) SetIPC

func (p *Process) SetIPC(name string, f IpcFunc)

SetIPC adds an IPC that can be called from nodejs

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL