Go Integration
Complete Go examples for Lunar Stream API integration.
Installation
bash
go mod init your-project
go get github.com/go-resty/resty/v2API Client
go
// lunarstream/client.go
package lunarstream
import (
"encoding/json"
"fmt"
"os"
"github.com/go-resty/resty/v2"
)
type Client struct {
baseURL string
apiKey string
projectID string
http *resty.Client
}
type ApiResponse struct {
Data json.RawMessage `json:"data"`
Meta json.RawMessage `json:"meta"`
}
type MediaServer struct {
ID string `json:"id"`
Name string `json:"name"`
ServerType string `json:"serverType"`
Host string `json:"host"`
Port int `json:"port"`
}
type Livestream struct {
ID string `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
StreamKey string `json:"streamKey"`
PushToken string `json:"pushToken"`
RtmpServer string `json:"rmtpServer"`
StreamKeyWithParams string `json:"streamKeyWithParams"`
HlsPaths []string `json:"hlsPaths"`
HlsSources []HlsSource `json:"hlsSources"`
CreatedAt string `json:"createdAt"`
}
type HlsSource struct {
Name string `json:"name"`
URL string `json:"url"`
}
type PushTokenResponse struct {
LivestreamID string `json:"livestreamId"`
PushToken string `json:"pushToken"`
StreamKey string `json:"streamKey"`
ExpiresAt string `json:"expiresAt"`
RtmpURL string `json:"rtmpUrl"`
StreamKeyWithToken string `json:"streamKeyWithToken"`
}
func NewClient(apiKey, projectID string) *Client {
baseURL := os.Getenv("LUNAR_STREAM_API_URL")
if baseURL == "" {
baseURL = "https://api.lunarstream.kozow.com/api/v1"
}
return &Client{
baseURL: baseURL,
apiKey: apiKey,
projectID: projectID,
http: resty.New().
SetHeader("ls-api-key", apiKey).
SetHeader("Content-Type", "application/json"),
}
}
func (c *Client) GetMediaServers() ([]MediaServer, error) {
var response ApiResponse
_, err := c.http.R().
SetQueryParam("projectId", c.projectID).
SetResult(&response).
Get(c.baseURL + "/media-servers/available")
if err != nil {
return nil, err
}
var servers []MediaServer
if err := json.Unmarshal(response.Data, &servers); err != nil {
return nil, err
}
return servers, nil
}
func (c *Client) CreateLivestream(name, mediaServerID string) (*Livestream, error) {
var response ApiResponse
_, err := c.http.R().
SetBody(map[string]string{
"name": name,
"projectId": c.projectID,
"mediaServerId": mediaServerID,
}).
SetResult(&response).
Post(c.baseURL + "/livestream")
if err != nil {
return nil, err
}
var stream Livestream
if err := json.Unmarshal(response.Data, &stream); err != nil {
return nil, err
}
return &stream, nil
}
func (c *Client) GetLivestream(id string) (*Livestream, error) {
var response ApiResponse
_, err := c.http.R().
SetQueryParam("projectId", c.projectID).
SetResult(&response).
Get(c.baseURL + "/livestream/" + id)
if err != nil {
return nil, err
}
var stream Livestream
if err := json.Unmarshal(response.Data, &stream); err != nil {
return nil, err
}
return &stream, nil
}
func (c *Client) ListLivestreams(page, limit int) ([]Livestream, error) {
var response ApiResponse
_, err := c.http.R().
SetQueryParams(map[string]string{
"projectId": c.projectID,
"page": fmt.Sprintf("%d", page),
"limit": fmt.Sprintf("%d", limit),
}).
SetResult(&response).
Get(c.baseURL + "/livestream")
if err != nil {
return nil, err
}
var streams []Livestream
if err := json.Unmarshal(response.Data, &streams); err != nil {
return nil, err
}
return streams, nil
}
func (c *Client) DeleteLivestream(id string) error {
_, err := c.http.R().
SetQueryParam("projectId", c.projectID).
Delete(c.baseURL + "/livestream/" + id)
return err
}
func (c *Client) GeneratePushToken(streamKey string, expiresIn int) (*PushTokenResponse, error) {
var response ApiResponse
_, err := c.http.R().
SetBody(map[string]interface{}{
"projectId": c.projectID,
"streamKey": streamKey,
"expiresIn": expiresIn,
}).
SetResult(&response).
Post(c.baseURL + "/livestream/generate-push-token")
if err != nil {
return nil, err
}
var tokenResp PushTokenResponse
if err := json.Unmarshal(response.Data, &tokenResp); err != nil {
return nil, err
}
return &tokenResp, nil
}
func (c *Client) GetStreamInfo(streamKey string) (*Livestream, error) {
var response ApiResponse
_, err := resty.New().R().
SetHeader("Content-Type", "application/json").
SetResult(&response).
Get(c.baseURL + "/livestreams/stream-info/" + streamKey)
if err != nil {
return nil, err
}
var stream Livestream
if err := json.Unmarshal(response.Data, &stream); err != nil {
return nil, err
}
return &stream, nil
}HTTP Server Example
go
// main.go
package main
import (
"encoding/json"
"log"
"net/http"
"os"
"strconv"
"your-project/lunarstream"
)
var client *lunarstream.Client
func main() {
apiKey := os.Getenv("LUNAR_STREAM_API_KEY")
projectID := os.Getenv("LUNAR_STREAM_PROJECT_ID")
if apiKey == "" || projectID == "" {
log.Fatal("LUNAR_STREAM_API_KEY and LUNAR_STREAM_PROJECT_ID are required")
}
client = lunarstream.NewClient(apiKey, projectID)
http.HandleFunc("POST /api/streams", createStream)
http.HandleFunc("GET /api/streams/{streamKey}", getStreamInfo)
http.HandleFunc("GET /api/streams", listStreams)
http.HandleFunc("DELETE /api/streams/{id}", deleteStream)
http.HandleFunc("POST /api/streams/{streamKey}/refresh-token", refreshToken)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Server running on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
type CreateStreamRequest struct {
Name string `json:"name"`
}
type StreamResponse struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Status string `json:"status"`
RtmpURL string `json:"rtmpUrl,omitempty"`
HlsURL string `json:"hlsUrl,omitempty"`
}
func createStream(w http.ResponseWriter, r *http.Request) {
var req CreateStreamRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
jsonError(w, "Invalid request body", http.StatusBadRequest)
return
}
servers, err := client.GetMediaServers()
if err != nil || len(servers) == 0 {
jsonError(w, "No media servers available", http.StatusServiceUnavailable)
return
}
stream, err := client.CreateLivestream(req.Name, servers[0].ID)
if err != nil {
jsonError(w, "Failed to create stream", http.StatusInternalServerError)
return
}
hlsURL := ""
if len(stream.HlsSources) > 0 {
hlsURL = stream.HlsSources[0].URL
}
jsonResponse(w, StreamResponse{
ID: stream.ID,
Name: stream.Name,
Status: stream.Status,
RtmpURL: stream.RtmpServer + "/" + stream.StreamKeyWithParams,
HlsURL: hlsURL,
})
}
func getStreamInfo(w http.ResponseWriter, r *http.Request) {
streamKey := r.PathValue("streamKey")
stream, err := client.GetStreamInfo(streamKey)
if err != nil {
jsonError(w, "Stream not found", http.StatusNotFound)
return
}
jsonResponse(w, StreamResponse{
Name: stream.Name,
Status: stream.Status,
})
}
func listStreams(w http.ResponseWriter, r *http.Request) {
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
if page < 1 {
page = 1
}
if limit < 1 {
limit = 10
}
streams, err := client.ListLivestreams(page, limit)
if err != nil {
jsonError(w, "Failed to list streams", http.StatusInternalServerError)
return
}
jsonResponse(w, map[string]interface{}{"streams": streams})
}
func deleteStream(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
if err := client.DeleteLivestream(id); err != nil {
jsonError(w, "Failed to delete stream", http.StatusInternalServerError)
return
}
jsonResponse(w, map[string]bool{"success": true})
}
func refreshToken(w http.ResponseWriter, r *http.Request) {
streamKey := r.PathValue("streamKey")
expiresIn := 7200
if exp := r.URL.Query().Get("expiresIn"); exp != "" {
if val, err := strconv.Atoi(exp); err == nil {
expiresIn = val
}
}
token, err := client.GeneratePushToken(streamKey, expiresIn)
if err != nil {
jsonError(w, "Failed to refresh token", http.StatusInternalServerError)
return
}
jsonResponse(w, map[string]string{
"rtmpUrl": token.RtmpURL,
"streamKeyWithToken": token.StreamKeyWithToken,
"expiresAt": token.ExpiresAt,
})
}
func jsonResponse(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
func jsonError(w http.ResponseWriter, message string, status int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(map[string]string{"error": message})
}Environment Variables
bash
export LUNAR_STREAM_API_KEY="ls_proj_v1_your_api_key_here"
export LUNAR_STREAM_PROJECT_ID="your-project-id-here"
export PORT="8080"Usage
bash
# Run the server
go run main.go
# Create a stream
curl -X POST http://localhost:8080/api/streams \
-H "Content-Type: application/json" \
-d '{"name": "My Stream"}'
# Get stream info
curl http://localhost:8080/api/streams/ee04affe2a669854052102fe762bd715
# List streams
curl "http://localhost:8080/api/streams?page=1&limit=10"
# Refresh token
curl -X POST "http://localhost:8080/api/streams/ee04affe2a669854052102fe762bd715/refresh-token?expiresIn=7200"