Repository: streamlink/streamlink

Issue:
plugins.goltelevision: 401 Client Error: Unauthorized for url
### Checklist

- [X] This is a plugin issue and not a different kind of issue
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

Latest stable release

### Description

Using the latest app image with Tvheadend with command:

pipe:///usr/local/bin/streamlink -O http://www.goltelevision.com/en-directo best

2022-10-09 19:34:55.795 mpegts: GOL TV HD in Streams - tuning on IPTV #1
2022-10-09 19:34:55.840 spawn: Executing "/usr/local/bin/streamlink"
2022-10-09 19:34:55.840 subscription: 0109: "scan" subscribing to mux "GOL TV HD", weight: 6, adapter: "IPTV #1", network: "Streams", service: "Raw PID Subscription"
2022-10-09 19:34:56.216 spawn: [cli][info] Found matching plugin goltelevision for URL http://www.goltelevision.com/en-directo
2022-10-09 19:34:56.348 spawn: error: Unable to open URL: https://play.goltelevision.com/api/stream/live (401 Client Error: Unauthorized for url: https://play.goltelevision.com/api/stream/live)
2022-10-09 19:34:56.430 iptv: stdin pipe 88 unexpectedly closed: No data

Seems like it´s expecting an URL starting with https but actually the website is using:
http://www.goltelevision.com/en-directo

Don´t know if this is the root cause of the issue.


### Debug log

```text
nud@NUC:~/streamlink$ ./streamlink -l debug http://www.goltelevision.com/en-directo
[cli][debug] OS:         Linux-5.15.0-48-generic-x86_64-with-glibc2.31
[cli][debug] Python:     3.10.7
[cli][debug] Streamlink: 5.0.1
[cli][debug] Dependencies:
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 4.9.1
[cli][debug]  pycountry: 22.3.5
[cli][debug]  pycryptodome: 3.15.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.28.1
[cli][debug]  websocket-client: 1.4.1
[cli][debug] Arguments:
[cli][debug]  url=http://www.goltelevision.com/en-directo
[cli][debug]  --loglevel=debug
[cli][info] Found matching plugin goltelevision for URL http://www.goltelevision.com/en-directo
error: Unable to open URL: https://play.goltelevision.com/api/stream/live (401 Client Error: Unauthorized for url: https://play.goltelevision.com/api/stream/live)

If I try this command: ./streamlink -l debug https://www.goltelevision.com/en-directo
./streamlink -l debug https://www.goltelevision.com/en-directo
[cli][debug] OS:         Linux-5.15.0-48-generic-x86_64-with-glibc2.31
[cli][debug] Python:     3.10.7
[cli][debug] Streamlink: 5.0.1
[cli][debug] Dependencies:
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 4.9.1
[cli][debug]  pycountry: 22.3.5
[cli][debug]  pycryptodome: 3.15.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.28.1
[cli][debug]  websocket-client: 1.4.1
[cli][debug] Arguments:
[cli][debug]  url=https://www.goltelevision.com/en-directo
[cli][debug]  --loglevel=debug
[cli][info] Found matching plugin goltelevision for URL https://www.goltelevision.com/en-directo
error: Unable to open URL: https://play.goltelevision.com/api/stream/live (401 Client Error: Unauthorized for url: https://play.goltelevision.com/api/stream/live)

I have the same result.

nuc@NUC:~/streamlink$ ./streamlink --version-check
[cli][info] Your Streamlink version (5.0.1) is up to date!

nuc@NUC:~/streamlink$ ./streamlink --version
streamlink 5.0.1

nuc@NUC:~/streamlink$ ./streamlink --plugins
Loaded plugins: abematv, adultswim, afreeca, albavision, aloula, app17, ard_live, ard_mediathek, artetv, atpchallenger, atresplayer, bbciplayer, bfmtv, bigo, bilibili, blazetv, bloomberg, booyah, brightcove, btv, cbsnews, cdnbg, ceskatelevize, cinergroup, clubbingtv, cmmedia, cnews, crunchyroll, dailymotion, dash, delfi, deutschewelle, dlive, dogan, dogus, drdk, earthcam, egame, euronews, facebook, filmon, foxtr, funimationnow, galatasaraytv, **goltelevision**, goodgame, googledrive, gulli, hiplayer, hls, http, htv, huajiao, huya, idf1, invintus, kugou, linelive, livestream, lnk, lrt, ltv_lsm_lv, mdstrm, mediaklikk, mediavitrina, mildom, mitele, mjunoon, mrtmk, n13tv, nbcnews, nhkworld, nicolive, nimotv, nos, nownews, nrk, ntv, okru, olympicchannel, oneplusone, onetv, openrectv, orf_tvthek, pandalive, picarto, piczel, pixiv, pluto, pluzz, qq, radiko, radionet, raiplay, reuters, rtbf, rtpa, rtpplay, rtve, rtvs, ruv, sbscokr, schoolism, showroom, sportal, sportschau, ssh101, stadium, steam, streamable, streann, stv, svtplay, swisstxt, telefe, tf1, trovo, turkuvaz, tv360, tv3cat, tv4play, tv5monde, tv8, tv999, tvibo, tviplayer, tvp, tvrby, tvrplus, tvtoya, twitcasting, twitch, useetv, ustreamtv, ustvnow, vidio, vimeo, vinhlongtv, vk, vlive, vtvgo, wasd, webtv, welt, wwenetwork, youtube, yupptv, zattoo, zdf_mediathek, zeenews, zengatv, zhanqi
```



Discussion:
The API endpoint where the stream URL is read from requires the `Referer` and `Origin` HTTP headers to be set. That's all. I'll submit a PR in a couple of minutes.

Resolving patch:
diff --git a/src/streamlink/plugins/goltelevision.py b/src/streamlink/plugins/goltelevision.py
--- a/src/streamlink/plugins/goltelevision.py
+++ b/src/streamlink/plugins/goltelevision.py
@@ -17,12 +17,16 @@
 ))
 class GOLTelevision(Plugin):
     def _get_streams(self):
+        self.session.http.headers.update({
+            "Origin": "https://goltelevision.com",
+            "Referer": "https://goltelevision.com/",
+        })
         url = self.session.http.get(
             "https://play.goltelevision.com/api/stream/live",
             schema=validate.Schema(
                 validate.parse_json(),
                 {"manifest": validate.url()},
-                validate.get("manifest")
+                validate.get("manifest"),
             )
         )
         return HLSStream.parse_variant_playlist(self.session, url)


Test patch: