@@ -10,6 +10,7 @@ import (
1010 "net/http/httputil"
1111 "net/url"
1212 "path"
13+ "regexp"
1314 "strconv"
1415 "strings"
1516 "time"
@@ -31,6 +32,8 @@ type Server struct {
3132 transcodeManager * transcode.Manager
3233}
3334
35+ var embyTokenPattern = regexp .MustCompile (`(?i)\btoken\s*=\s*"?([^",\s]+)"?` )
36+
3437func New (cfg config.Config ) (* Server , error ) {
3538 return NewWithTransport (cfg , http .DefaultTransport )
3639}
@@ -193,7 +196,7 @@ func (s *Server) handlePlaybackInfo(w http.ResponseWriter, r *http.Request) {
193196 itemID := itemIDFromPlaybackPath (r .URL .Path )
194197 publicURL := s .publicURL (r )
195198 if strings .Contains (resp .Header .Get ("Content-Type" ), "application/json" ) && itemID != "" {
196- rewritten , changed , report , err := emby .RewritePlaybackInfoWithReport (respBody , itemID , publicURL , r . URL . RawQuery )
199+ rewritten , changed , report , err := emby .RewritePlaybackInfoWithReport (respBody , itemID , publicURL , authAwareRawQuery ( r ) )
197200 if err != nil {
198201 logging .Errorf ("playbackinfo rewrite error item=%s err=%v" , itemID , err )
199202 }
@@ -275,6 +278,7 @@ func (s *Server) prewarmPlaybackInfoTranscode(r *http.Request, report emby.Rewri
275278 inputURL := prewarmTranscodeInputURL (s .upstream , itemID , source .ID , audioStreamIndex , r )
276279 request := transcode.Request {
277280 InputURL : inputURL ,
281+ Headers : r .Header .Clone (),
278282 ItemID : itemID ,
279283 MediaSourceID : source .ID ,
280284 PlaySessionID : source .SessionID ,
@@ -317,7 +321,7 @@ func preferredAudioStreamIndex(streams []emby.AudioStreamReport) int {
317321func prewarmTranscodeInputURL (upstream * url.URL , id string , mediaSourceID string , audioStreamIndex int , r * http.Request ) string {
318322 u := * upstream
319323 u .Path = singleJoiningSlash (upstream .Path , path .Join ("/emby/Videos" , id , "stream" ))
320- query := r . URL . Query ( )
324+ query := authAwareQuery ( r )
321325 query .Del ("reqformat" )
322326 query .Set ("AutoOpenLiveStream" , "true" )
323327 query .Set ("IsPlayback" , "true" )
@@ -334,12 +338,50 @@ func prewarmTranscodeInputURL(upstream *url.URL, id string, mediaSourceID string
334338func transcodeInputURL (upstream * url.URL , id string , r * http.Request ) string {
335339 u := * upstream
336340 u .Path = singleJoiningSlash (upstream .Path , path .Join ("/emby/Videos" , id , "stream" ))
337- query := r . URL . Query ( )
341+ query := authAwareQuery ( r )
338342 query .Del ("reqformat" )
339343 u .RawQuery = query .Encode ()
340344 return u .String ()
341345}
342346
347+ func authAwareRawQuery (r * http.Request ) string {
348+ return authAwareQuery (r ).Encode ()
349+ }
350+
351+ func authAwareQuery (r * http.Request ) url.Values {
352+ query := r .URL .Query ()
353+ if query .Get ("X-Emby-Token" ) == "" {
354+ if token := embyTokenFromHeaders (r .Header ); token != "" {
355+ query .Set ("X-Emby-Token" , token )
356+ }
357+ }
358+ return query
359+ }
360+
361+ func embyTokenFromHeaders (headers http.Header ) string {
362+ for _ , key := range []string {"X-Emby-Token" , "X-MediaBrowser-Token" } {
363+ if value := strings .TrimSpace (headers .Get (key )); value != "" {
364+ return value
365+ }
366+ }
367+ for _ , key := range []string {"X-Emby-Authorization" , "Authorization" } {
368+ if value := strings .TrimSpace (headers .Get (key )); value != "" {
369+ if token := extractEmbyToken (value ); token != "" {
370+ return token
371+ }
372+ }
373+ }
374+ return ""
375+ }
376+
377+ func extractEmbyToken (value string ) string {
378+ match := embyTokenPattern .FindStringSubmatch (value )
379+ if len (match ) == 2 {
380+ return match [1 ]
381+ }
382+ return ""
383+ }
384+
343385func (s * Server ) publicURL (r * http.Request ) string {
344386 if s .cfg .Server .PublicURL != "" {
345387 return s .cfg .Server .PublicURL
0 commit comments