Skip to content

fix(sparql): POST 403 → fallback GET (WAF/Virtuoso, caso Senato) - #447

Merged
Gabrymi93 merged 2 commits into
mainfrom
fix/sparql-post-403-get-fallback
Aug 4, 2026
Merged

fix(sparql): POST 403 → fallback GET (WAF/Virtuoso, caso Senato)#447
Gabrymi93 merged 2 commits into
mainfrom
fix/sparql-post-403-get-fallback

Conversation

@Gabrymi93

Copy link
Copy Markdown
Member

Sintesi

Fix del plugin SPARQL: il fallback GET non scattava mai su endpoint che rifiutano il POST con 4xx. is_ok considerava "ok" qualsiasi risposta HTTP (response presente, err None) → un 403 con body HTML veniva salvato come CSV valido.

Scoperto lavorando su senato-ddl (issue dataset-incubator #781): dati.senato.it accetta solo GET (POST → 403), e il plugin falliva perché il 403 non attivava il fallback documentato ("Se POST fallisce (403, timeout), prova GET").

Contesto collegato

  • Rilevato in: dataset-incubator #781 (senato_ddl)
  • Il docstring del plugin già prometteva il fallback su 403 — il codice non lo implementava

Cosa cambia

  • Bug fix
  • Nuova funzionalità del motore
  • Nuovo plugin sorgente
  • Modifica contratto pubblico (dataset.yml, path output, schema parquet)
  • Refactor / performance
  • Documentazione
  • Dipendenze o CI

Impatto su contratti pubblici

  • Struttura dataset.yml (nuovo campo, cambio obbligatorietà)
  • Path output (nuovo layer, cambio percorso artifact)
  • Schema parquet (nuova colonna, rename, cambio tipo)
  • CLI o MCP tool (nuovo comando, cambio parametro)
  • API pubblica del toolkit (firma funzione, classe, eccezione)

Nessun contratto pubblico toccato — comportamento interno del fetch.

Dettaglio

Prima (bug):

if result.is_ok:  # True anche su 403 (response presente) → salva HTML come CSV
    return self._parse_response(result.response, is_json)

Dopo (fix):

  • POST ok solo se status < 400
  • fallback GET solo su 4xx (400-499) — il caso WAF/Virtuoso che rifiutano POST
  • 5xx solleva DownloadError con codice HTTP esplicito (il fallback non deve mascherare un errore server reale)

Verifica

pytest tests/test_sparql_plugin.py tests/test_contracts.py  # 34 passed
ruff check toolkit/plugins/sparql.py tests/test_sparql_plugin.py

Test nuovo: test_sparql_fetch_post_403_falls_back_to_get — regressione sul caso reale dati.senato.it (POST 403 → GET fallback → CSV valido). Verifica end-to-end: toolkit run raw -c candidates/senato-ddl/dataset.yml passa sul Senato reale.

Note

  • Il comportamento precedente su 5xx: _parse_response sollevava errore sul body non-SPARQL → ora errore esplicito con codice HTTP (stessa semantica, messaggio più chiaro)
  • Il test esistente test_sparql_fetch_http_error (500 → DownloadError "HTTP 500") continua a passare

Il plugin considerava 'ok' qualsiasi risposta HTTP (is_ok = response presente,
err None) → il fallback GET non scattava mai su endpoint che rifiutano POST
con 403 (es. dati.senato.it — accetta solo GET).

Fix:
- POST ok solo se status < 400
- fallback GET solo su 4xx (WAF/Virtuoso rifiutano POST, accettano GET)
- 5xx solleva DownloadError con codice HTTP esplicito (non mascherare
  l'errore server col fallback)

Test: test_sparql_fetch_post_403_falls_back_to_get (regressione, caso
dati.senato.it reale). 25/25 sparql plugin + 9 contracts pass.
Il fix mypy del CI segnalava 'Item None of ResponseLike|None has no
attribute text' sul raise 5xx. Gestito il caso response=None.
@Gabrymi93
Gabrymi93 merged commit 2e98037 into main Aug 4, 2026
3 checks passed
@Gabrymi93
Gabrymi93 deleted the fix/sparql-post-403-get-fallback branch August 4, 2026 10:16
Gabrymi93 added a commit that referenced this pull request Aug 4, 2026
… GET 5xx (#448)

Completa il fix #447 (POST 403 → GET fallback) con i casi che il docstring
prometteva ma il codice non copriva:
- POST con errore di rete/timeout (post_status None) → prova GET fallback
- GET fallback che restituisce 5xx → DownloadError esplicito con status

Test: 4 casi coperti (403→GET, timeout→GET, GET 500→errore, POST 500→errore).
26/26 pass, mypy ok, ruff ok. End-to-end sul Senato reale: OK.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant