JsonMod response 403 - Ergebnis im Browser aber OK

Begonnen von mthome, 29 Mai 2023, 06:18:56

Vorheriges Thema - Nächstes Thema

mthome

Hallo zusammen,

ich wollte mir die aktuellen Angebote von Rewe per JsonMod abrufen. Leider bekomme ich immer einen "HTTP/1.1 403 Forbidden".

Wenn ich die URL direkt im Browser eingebe bekomme ich den Json   :o

Hat jemand eine Idee an was das liegen kann?

Vielen Dank im Voraus!

Hier das Device List:
Internals:
   API_LAST_MSG invalid server response
   API_LAST_RES 1685333652.70818
   CFGFN     
   DEF        https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034
   FUUID      6474266b-f33f-6d2a-d178-ca392f8f5724bea7
   NAME       Rewe_Angebote2
   NEXT       2023-05-29 07:00:00
   NR         277
   SOURCE     https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034 (403)
   STATE      ???
   SVN        27457 2023-04-17 23:35:57 UTC
   TYPE       JsonMod
   eventCount 2
   CONFIG:
     IN_REQUEST 0
     SOURCE     https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034
     SECRET:
Attributes:
   room       System
   verbose    5

Und hier der Log-Auszug:
2023.05.29 06:14:12 5: HttpUtils url=https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034 NonBlocking via https
2023.05.29 06:14:12 4: IP: mobile-api.rewe.de -> 104.16.64.9
2023.05.29 06:14:12 5: HttpUtils request header:
GET /api/v3/all-offers?marketCode=240034 HTTP/1.0
Host: mobile-api.rewe.de
User-Agent: fhem
Accept-Encoding: gzip,deflate

Accept: application/json
Accept-Charset: utf-8, iso-8859-1

2023.05.29 06:14:12 4: https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034: HTTP response code 403
2023.05.29 06:14:12 5: HttpUtils https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034: Got data, length: 16
2023.05.29 06:14:12 5: HttpUtils response header:
HTTP/1.1 403 Forbidden
Date: Mon, 29 May 2023 04:14:12 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 16
Connection: close
X-Frame-Options: SAMEORIGIN
Referrer-Policy: same-origin
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Set-Cookie: __cf_bm=73HquY_NQbvKIWa0dtC2xKt925JKZsJKdrzd2GxyCCg-1685333652-0-AYCjnKKRAcEl9TKMOOrCP+hTl8joWku/PMJ9bf+7i3lm3cr3FX2UmzjnlptyQ0nVMSi2Kpnmjn/fibau+rp20Cs=; path=/; expires=Mon, 29-May-23 04:44:12 GMT; domain=.rewe.de; HttpOnly; Secure; SameSite=None
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15552000
Server: cloudflare
CF-RAY: 7cebe8c14d7a9279-FRA
2023.05.29 06:14:12 4: [Rewe_Angebote2] api encoding is UTF-8, designated encoder is utf-8-strict
2023.05.29 06:14:12 5: [Rewe_Angebote2] start json decoding

betateilchen

Was Du im Browser siehst, ist nicht das direkte Ergebnis der URL-Anfrage.
Deshalb kannst Du nicht davon ausgehen, dass das Ergebnis im Browser mit dem Ergebnis einer direkten URL-Abfrage übereinstimmt - da spielen noch andere Faktoren mit, möglicherweise angefangen vom User-Agent über Session Cookies oder was auch immer.

Wenn Du den Aufruf manuell auf einer Konsole machst, passiert genau das gleiche, was Du in Deinem JsonMod device siehst:

wget https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034
--2023-05-30 10:18:46--  https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034
Resolving mobile-api.rewe.de (mobile-api.rewe.de)... 2606:4700::6810:4009, 2606:4700::6810:4109, 104.16.65.9, ...
Connecting to mobile-api.rewe.de (mobile-api.rewe.de)|2606:4700::6810:4009|:443... connected.
HTTP request sent, awaiting response... 403 Forbidden
2023-05-30 10:18:46 ERROR 403: Forbidden.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

mthome

#2
OK, vielen Dank. Was heißt das?

Ich hatte bereits probiert im Attribut httpHeader mit User-Agent weiter zu kommen. Habe die Info aus dem Browser eingetragen. Hatte aber leider nichts gebracht.

Wenn ich z.B. auf der Console folgenden curl Befehl eingebe geht es auch. Ist dann aber vermutlich auch das gleiche wie über Browser? Habe mal mit Verbose eingestellt - ist da was dabei was mir helfen würde?

curl -G -v  "https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034"
*   Trying 2606:4700::6810:4009:443...
* TCP_NODELAY set
* Connected to mobile-api.rewe.de (2606:4700::6810:4009) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=Cloudflare, Inc.; CN=rewe.de
*  start date: Apr  1 00:00:00 2023 GMT
*  expire date: Mar 31 23:59:59 2024 GMT
*  subjectAltName: host "mobile-api.rewe.de" matched cert's "*.rewe.de"
*  issuer: C=US; O=Cloudflare, Inc.; CN=Cloudflare Inc ECC CA-3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5592c16f8320)
> GET /api/v3/all-offers?marketCode=240034 HTTP/2
> Host: mobile-api.rewe.de
> user-agent: curl/7.68.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 200
< date: Tue, 30 May 2023 10:47:31 GMT
< content-type: application/json; charset=utf-8
< server-timing: intid;desc=4205dc9524cc7eea
< x-powered-by: hantayo/2.0.17-master-8507/-1
< ruleversion: 1
< traceparent: 00-00000000000000004205dc9524cc7eea-29fc1ccbc59a1f3e-01
< tracestate: in=4205dc9524cc7eea;29fc1ccbc59a1f3e
< x-instana-l: 1
< x-instana-s: 29fc1ccbc59a1f3e
< x-instana-t: 4205dc9524cc7eea
< etag: W/"36412-yqOJ6wo0lKiPi2Tlf3c0JCZ5W5Q"
< vary: Accept-Encoding
< via: 1.1 google
< cf-cache-status: DYNAMIC
< set-cookie: __cf_bm=kp_ovz5gXI8VE_O6JiaMDLnOrMjxOrwY_9cW7vCN7pU-1685443651-0-ASQ+TiZusS+NsBYlfBwF7RREQDRzlv/POkR99fDYrYYButrS1OnEBzF6gxmgT/R+gzOTUZVVbaSqGI1Q2Y7I9L0=; path=/; expires=Tue, 30-May-23 11:17:31 GMT; domain=.rewe.de; HttpOnly; Secure; SameSite=None
< strict-transport-security: max-age=15552000
< set-cookie: _cfuvid=TBZY9_rx0QeVl.zUEH_yUtNN_lcrUWeXYFA4v9b947I-1685443651072-0-604800000; path=/; domain=.rewe.de; HttpOnly; Secure; SameSite=None
< server: cloudflare
< cf-ray: 7cf66642d96c18d8-FRA
<
<
{....ab hier kommt das Json}

Bedeutet das, ich muss mich davon verabschieden es mit JsonMod zu machen?

ch.eick

Moin,
manchmal liegt es auch an der falschen HTTP Version.

im ersten Post sieht man HTTP/1.0 und beim curl wird HTTP/1.1 verwendet.
Dafür gibt es im Device ein Attribut, nur mal so zum testen.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Wernieman

#4
Also am UserAgent liegt es nicht ....

Frage mich gerade: Was macht curl anders als wget??

Edit:
an http/1.1 liegt es nicht ... jedenfalls nicht bei wget
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

betateilchen

* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5592c16f8320)
> GET /api/v3/all-offers?marketCode=240034 HTTP/2

Zitat von: Wernieman am 30 Mai 2023, 16:15:45Frage mich gerade: Was macht curl anders als wget??

curl unterstützt HTTP2, wget nicht.

Testet man das ganze mit wget2 (wget mit HTTP2 support) funktioniert es auch.

wget2 https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034
[0] Downloading 'https://mobile-api.rewe.de/api/v3/all-offers?marketCode=240034' ...
Saving 'all-offers?marketCode=240034'
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#6
Zitat von: mthome am 30 Mai 2023, 11:38:00OK, vielen Dank. Was heißt das?
...
Bedeutet das, ich muss mich davon verabschieden es mit JsonMod zu machen?

Ein möglicher Workaround wäre:
Per cronjob den Seiteninhalt abholen und in eine Textdatei schreiben, dann mit FHEM und JsonMod diese Textdatei verarbeiten.

Aber Vorsicht: das ergibt mit complete() im Moment fast 4500 readings!

defmod rewe JsonMod file://tmp/rewe.json
attr rewe readingList complete()

...
setstate rewe 2023-05-30 17:42:00 hasOnlineOffers 1
setstate rewe 2023-05-30 17:42:00 untilDate 1685750400000

Du darfst diesen Dateianhang nicht ansehen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

herrmannj

Muss ja nicht per complete()

Problem ist also die fehlende http2 Unterstützung fhem, korrekt?

betateilchen

#8
Zitat von: herrmannj am 30 Mai 2023, 18:32:55Muss ja nicht per complete()

Stimmt, aber ich hatte vorhin keine Lust, mich durch die Struktur zu wühlen, mir ging es eher darum, ob das json überhaupt korrekt verarbeitet werden kann. Ausserdem weiß ich ja nicht, welche readings der Fragesteller tatsächlich braucht/haben möchte.

defmod rewe JsonMod file://tmp/rewe.json
attr rewe readingList single(jsonPath('$.categories.0.offers.0.title'),'artikeltext','?')\
single(jsonPath('$.categories.0.offers.0.subtitle'),'zusatztext','?')\
single(jsonPath('$.categories.0.offers.0.priceData.price'),'preis','?')

setstate rewe 2023-05-30 19:26:04 .computedReadings artikeltext,preis,zusatztext
setstate rewe 2023-05-30 19:26:04 artikeltext Géramont Cremig-zarte Scheiben
setstate rewe 2023-05-30 19:26:04 preis 1,99 €
setstate rewe 2023-05-30 19:26:04 zusatztext je 150-g-Pckg. (1 kg = 13.27)

Wem es schmeckt... 8)

Zitat von: herrmannj am 30 Mai 2023, 18:32:55Problem ist also die fehlende http2 Unterstützung fhem, korrekt?

Es deutet zumindest vieles darauf hin.

offtopic: kommst Du nächste Woche zum Stammtisch?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Wernieman

@betateilchen

Danke für die Info. Wußte gar nicht, das es ein wget2 gibt .... man lernt nicht aus ...
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

herrmannj


mthome

Zitat von: betateilchen am 30 Mai 2023, 17:37:03Ein möglicher Workaround wäre:
Per cronjob den Seiteninhalt abholen und in eine Textdatei schreiben, dann mit FHEM und JsonMod diese Textdatei verarbeiten.

Vielen Dank für den Workaround - dann werde ich es wohl so angehen. Mir reichen eigentlich alle "Topangebote" und deren Preis, die ich dann per Sprache an einem Echolautsprecher durchsagen lasse.

Der Hintergrund ist, dass mein Vater nicht mehr viel sehen kann, ich ihm aber ermöglichen möchte, dass er sich Angebote vorlesen lassen kann.

Nachmals Danke für Eure Hilfe!

betateilchen

Nur die Topangebote, bitteschön...
defmod rewe JsonMod file://tmp/rewe.json
attr rewe readingList multi(jsonPath('$.categories.0.offers.[*]'),concat('artikeltext_', count()),property('title'))\
multi(jsonPath('$.categories.0.offers.[*]'),concat('zusatztext_', count()),property('subtitle'))\
multi(jsonPath('$.categories.0.offers.[*]'),concat('preis_', count()),property('priceData.price'))
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

herrmannj

ich denke darüber nach, dass via JsonMod zugänglich zu machen. Noch nicht ausformuliert aber von der Idee her: analog zu file:// saw etwas wie shell:// oder system:// - Das so aufgerufene script würde dann idealerweise per pipe oder vergleichbar einen gültigen Json payload zurückgeben. Dann hätte man die ganzen "Sonderfälle" (POST, PUT, DELETE, irgendwelche Tokens etc oder OAUTH) alle ausgelagert. Da darf sich dann nach belieben bedient werden aber der "workflow" (cron, fehlerbehandlung etc) bleibt geradlinig im modul ...

betateilchen

Ob sich der Aufwand lohnt?
Bisher löse ich das einfach wie hier beschrieben:

  • Daten per cron abholen und in Datei schreiben
  • nach dem Holen der Daten wird aus dem gleichen Skript per telnet ein "set jsonmod-device reread" ausgelöst, um den Kram in readings zu verwursten.

Funktioniert einwandfrei und zuverlässig.

Und der cron auf Betriebssystemeben funktioniert vollumfänglich...
*duck-und-weg*

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!