Skip to content

Instantly share code, notes, and snippets.

@blainsmith
Last active July 18, 2019 20:25
Show Gist options
  • Save blainsmith/428bc949ca9ea16b2882591a50812022 to your computer and use it in GitHub Desktop.
Save blainsmith/428bc949ca9ea16b2882591a50812022 to your computer and use it in GitHub Desktop.
JWPlatform REST API Client example
package ovp
import (
"context"
"crypto/md5"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
)
type JWPlatformContextKey struct{}
type JWPlatformClient struct {
Key string
Secret string
}
// SignURL is used to sign video or playlist URLs to that players can be allowed to play them.
func (c *JWPlatformClient) SignURL(url *url.URL, expiresAt time.Time) error {
path := url.Path
if path[0] == '/' {
path = path[1:]
}
exp := strconv.FormatInt(expiresAt.Unix(), 10)
sig := md5.Sum([]byte(fmt.Sprintf("%s:%s:%s", path, exp, c.Secret)))
qs := url.Query()
qs.Set("exp", exp)
qs.Set("sig", fmt.Sprintf("%x", sig))
url.RawQuery = qs.Encode()
return nil
}
// SignRequest is used to sign v2 API endpoint calls.
func (c *JWPlatformClient) SignRequest(request *http.Request, expiresAt time.Time) error {
var resourceID string
var ok bool
if resourceID, ok = request.Context().Value(JWPlatformContextKey{}).(string); !ok {
return errors.New("cannot sign request with missing resourceID on context")
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"resource": resourceID,
"exp": expiresAt.Unix(),
})
tokenString, err := token.SignedString(c.Secret)
if err != nil {
return errors.Wrapf(err, "failed to sign request for %s", resourceID)
}
qs := request.URL.Query()
qs.Set("token", tokenString)
request.URL.RawQuery = qs.Encode()
return nil
}
// GetMediaContent is fills in the *http.Request with the required path and accept header to get a single video response. It will also add a context.Context value to be used for signing the request if needed.
func (c *JWPlatformClient) GetMediaContent(request *http.Request, mediaID string, imagewidth int) {
contentAPIURL(request.URL)
request.URL.Path = fmt.Sprintf("/v2/media/%s?poster_width=%d", mediaID, imagewidth)
request.Header.Set("Accept", "application/json")
ctx := context.WithValue(request.Context(), JWPlatformContextKey{}, mediaID)
request = request.WithContext(ctx)
}
// GetImageContent is fills in the *http.Request with the required path and accept header to get a single video image. It will also add a context.Context value to be used for signing the request if needed.
func (c *JWPlatformClient) GetImageContent(request *http.Request, mediaID string, imagewidth int) {
contentAPIURL(request.URL)
request.URL.Path = fmt.Sprintf("/thumbs/%s-%d", mediaID, imagewidth)
request.Header.Set("Accept", "image/jpeg")
ctx := context.WithValue(request.Context(), JWPlatformContextKey{}, mediaID)
request = request.WithContext(ctx)
}
// GetPlaylistContent is fills in the *http.Request with the required path and accept header to get a playlist of videos. It will also add a context.Context value to be used for signing the request if needed.
func (c *JWPlatformClient) GetPlaylistContent(request *http.Request, playlistID string, imagewidth int, pagelimit int, pageoffset int) {
contentAPIURL(request.URL)
request.URL.Path = fmt.Sprintf("/v2/media/%s?poster_width=%d&page_limit=%d&page_offset=%d", playlistID, imagewidth, pagelimit, pageoffset)
request.Header.Set("Accept", "application/json")
ctx := context.WithValue(request.Context(), JWPlatformContextKey{}, playlistID)
request = request.WithContext(ctx)
}
func contentAPIURL(url *url.URL) {
url.Scheme = "https"
url.Host = "cdn.jwplayer.com"
}
package ovp
type MediaResponse struct {
FeedInstanceID string `json:"feed_instance_id"`
Title string `json:"title"`
Kind string `json:"kind"`
Playlist []struct {
Mediaid string `json:"mediaid"`
Description string `json:"description"`
Pubdate int `json:"pubdate"`
Tags string `json:"tags"`
Image string `json:"image"`
Title string `json:"title"`
Variations struct {
} `json:"variations"`
Sources []struct {
Type string `json:"type"`
File string `json:"file"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Label string `json:"label,omitempty"`
} `json:"sources"`
Tracks []struct {
Kind string `json:"kind"`
File string `json:"file"`
Label string `json:"label,omitempty"`
} `json:"tracks"`
Link string `json:"link"`
Duration int `json:"duration"`
} `json:"playlist"`
Description string `json:"description"`
}
type PlaylistResponse struct {
Playist []MediaResponse `json:"playlist"`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment