Python15 dicembre 2025 117 visualizzazioni

Come distribuire un'API Flask o FastAPI su OuiPanel

Come distribuire un'API Flask o FastAPI su OuiPanel

Tempo stimato : 15 minuti
Difficoltà : Intermedia ⭐⭐
Tipo di server : Python


📋 Introduzione

Questa guida ti spiega come ospitare un'API REST sviluppata con Flask o FastAPI su OuiPanel. La tua API sarà accessibile 24 ore su 24, 7 giorni su 7, con la possibilità di aggiungere un nome di dominio personalizzato e HTTPS.

Flask vs FastAPI

Criterio Flask FastAPI
Difficoltà Principiante Intermedio
Installazione Facile (nessuna compilazione) Pesante (compilazione Rust)
Spazio disco richiesto ~100 MB ~5 GB minimo
Performance Buona Eccellente (async)
Documentazione auto No (estensione) Sì (Swagger/OpenAPI)
Validazione dati Manuale Automatica (Pydantic)
Ideale per API semplici, piccoli server API moderne, grandi server

💡 Raccomandazione : Se hai un server con poco spazio di archiviazione (< 5 GB), utilizza Flask.

Di cosa hai bisogno

Prerequisiti Descrizione
📁 Il tuo codice API File Python (app.py, main.py...)
🐍 Un server Python Ordinato su OuiHeberg
🌐 Un nome di dominio (Opzionale) Per un accesso tramite URL personalizzato

💡 Non hai ancora un server Python?
Ordina uno su : https://www.ouiheberg.com/fr/hebergement-python


📁 Passo 1 : Preparare i File dell'API

Struttura dei file

La tua API deve avere questa struttura :

📁 MonAPI/
├── 📄 app.py             ← File principale (o main.py)
├── 📄 requirements.txt   ← Dipendenze Python
├── 📄 .env               ← Variabili d'ambiente (creato sul server)
└── 📁 routes/            ← (Opzionale) Cartella delle route

🌶️ Opzione A : API con Flask

File requirements.txt (Flask)

flask==2.3.3
python-dotenv==1.0.0
werkzeug==2.3.7
Pacchetto Descrizione
flask Framework web minimalista
python-dotenv Caricare le variabili da .env
werkzeug Utilità WSGI (incluso con Flask)

⚠️ Importante : Utilizza queste versioni esatte per evitare problemi di compatibilità.


File principale (app.py) - Flask

import os
from dotenv import load_dotenv

# Caricare le variabili d'ambiente da .env
load_dotenv()

from flask import Flask, jsonify, request

# Creare l'applicazione Flask
app = Flask(__name__)

# ============================================
# ROUTE DELL'API
# ============================================

# Route principale
@app.route('/')
def home():
    return jsonify({
        'status': 'online',
        'message': 'Benvenuto nella mia API Flask!',
        'version': '1.0.0'
    })

# Route di salute (health check)
@app.route('/health')
def health():
    return jsonify({
        'status': 'healthy',
        'service': 'La mia API Flask'
    })

# Esempio di dati (simulando un database)
items = [
    {'id': 1, 'name': 'Item 1', 'price': 10.99},
    {'id': 2, 'name': 'Item 2', 'price': 24.99},
    {'id': 3, 'name': 'Item 3', 'price': 5.49}
]

# GET tutti gli elementi
@app.route('/api/items', methods=['GET'])
def get_items():
    return jsonify({
        'success': True,
        'data': items,
        'count': len(items)
    })

# GET un elemento per ID
@app.route('/api/items/<int:item_id>', methods=['GET'])
def get_item(item_id):
    for item in items:
        if item['id'] == item_id:
            return jsonify({
                'success': True,
                'data': item
            })
    return jsonify({
        'success': False,
        'error': 'Elemento non trovato'
    }), 404

# POST creare un elemento
@app.route('/api/items', methods=['POST'])
def create_item():
    data = request.get_json()
    
    if not data or 'name' not in data:
        return jsonify({
            'success': False,
            'error': 'Il campo "name" è obbligatorio'
        }), 400
    
    new_id = max(item['id'] for item in items) + 1 if items else 1
    new_item = {
        'id': new_id,
        'name': data['name'],
        'price': data.get('price', 0)
    }
    items.append(new_item)
    
    return jsonify({
        'success': True,
        'message': 'Elemento creato con successo',
        'data': new_item
    }), 201

# PUT modificare un elemento
@app.route('/api/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
    data = request.get_json()
    
    for item in items:
        if item['id'] == item_id:
            item['name'] = data.get('name', item['name'])
            item['price'] = data.get('price', item['price'])
            return jsonify({
                'success': True,
                'message': 'Elemento modificato con successo',
                'data': item
            })
    
    return jsonify({
        'success': False,
        'error': 'Elemento non trovato'
    }), 404

# DELETE eliminare un elemento
@app.route('/api/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
    for index, item in enumerate(items):
        if item['id'] == item_id:
            items.pop(index)
            return jsonify({
                'success': True,
                'message': f'Elemento {item_id} eliminato con successo'
            })
    
    return jsonify({
        'success': False,
        'error': 'Elemento non trovato'
    }), 404

# ============================================
# GESTIONE DEGLI ERRORI
# ============================================

@app.errorhandler(404)
def not_found(error):
    return jsonify({
        'success': False,
        'error': 'Risorsa non trovata'
    }), 404

@app.errorhandler(500)
def internal_error(error):
    return jsonify({
        'success': False,
        'error': 'Errore interno del server'
    }), 500

# ============================================
# AVVIO DEL SERVER
# ============================================

if __name__ == '__main__':
    # Porta : utilizza SERVER_PORT (OuiPanel) o 5000 per impostazione predefinita
    port = int(os.getenv('SERVER_PORT', 5000))
    
    # IMPORTANTE : Ascoltare su 0.0.0.0 per OuiPanel
    app.run(host='0.0.0.0', port=port)

⚠️ IMPORTANTE : L'API deve ascoltare su 0.0.0.0 e non localhost o 127.0.0.1 per essere accessibile dall'esterno.


⚡ Opzione B : API con FastAPI

⚠️ Attenzione : FastAPI richiede pydantic che deve essere compilato. Questo richiede molto spazio disco (diversi GB) durante l'installazione. Se ricevi un errore No space left on device, utilizza Flask al suo posto o aumenta lo spazio di archiviazione del tuo server.

File requirements.txt (FastAPI)

fastapi==0.104.1
uvicorn==0.24.0
python-dotenv==1.0.0
Pacchetto Descrizione
fastapi Framework web moderno e veloce
uvicorn Server ASGI per FastAPI
python-dotenv Caricare le variabili da .env

💡 Raccomandazione spazio di archiviazione : Prevedi almeno 5 GB di spazio libero per l'installazione di FastAPI.


File principale (app.py) - FastAPI

import os
from dotenv import load_dotenv

# Caricare le variabili d'ambiente da .env
load_dotenv()

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List

# Creare l'applicazione FastAPI
app = FastAPI(
    title="La mia API FastAPI",
    description="Un'API REST moderna con FastAPI",
    version="1.0.0",
    docs_url="/docs",      # Documentazione Swagger
    redoc_url="/redoc"     # Documentazione ReDoc
)

# ============================================
# MODELLI PYDANTIC (validazione dei dati)
# ============================================

class ItemCreate(BaseModel):
    name: str
    price: float = 0
    description: Optional[str] = None

class Item(BaseModel):
    id: int
    name: str
    price: float
    description: Optional[str] = None

# ============================================
# DATI ESEMPIO (simulando un database)
# ============================================

items_db = [
    {"id": 1, "name": "Item 1", "price": 10.99, "description": "Primo elemento"},
    {"id": 2, "name": "Item 2", "price": 24.99, "description": "Secondo elemento"},
    {"id": 3, "name": "Item 3", "price": 5.49, "description": "Terzo elemento"},
]

# ============================================
# ROUTE DELL'API
# ============================================

# Route principale
@app.get("/", tags=["Generale"])
async def home():
    return {
        "status": "online",
        "message": "Benvenuto nella mia API FastAPI!",
        "version": "1.0.0",
        "docs": "/docs"
    }

# Route di salute (health check)
@app.get("/health", tags=["Generale"])
async def health():
    return {
        "status": "healthy",
        "service": "La mia API FastAPI"
    }

# GET tutti gli elementi
@app.get("/api/items", tags=["Elementi"])
async def get_items():
    return {
        "success": True,
        "data": items_db,
        "count": len(items_db)
    }

# GET un elemento per ID
@app.get("/api/items/{item_id}", tags=["Elementi"])
async def get_item(item_id: int):
    for item in items_db:
        if item["id"] == item_id:
            return {"success": True, "data": item}
    raise HTTPException(status_code=404, detail="Elemento non trovato")

# POST creare un elemento
@app.post("/api/items", status_code=201, tags=["Elementi"])
async def create_item(item: ItemCreate):
    new_id = max(i["id"] for i in items_db) + 1 if items_db else 1
    new_item = {
        "id": new_id,
        "name": item.name,
        "price": item.price,
        "description": item.description
    }
    items_db.append(new_item)
    return {
        "success": True,
        "message": "Elemento creato con successo",
        "data": new_item
    }

# PUT modificare un elemento
@app.put("/api/items/{item_id}", tags=["Elementi"])
async def update_item(item_id: int, item: ItemCreate):
    for index, existing_item in enumerate(items_db):
        if existing_item["id"] == item_id:
            updated_item = {
                "id": item_id,
                "name": item.name,
                "price": item.price,
                "description": item.description
            }
            items_db[index] = updated_item
            return {
                "success": True,
                "message": "Elemento modificato con successo",
                "data": updated_item
            }
    raise HTTPException(status_code=404, detail="Elemento non trovato")

# DELETE eliminare un elemento
@app.delete("/api/items/{item_id}", tags=["Elementi"])
async def delete_item(item_id: int):
    for index, item in enumerate(items_db):
        if item["id"] == item_id:
            items_db.pop(index)
            return {"success": True, "message": f"Elemento {item_id} eliminato"}
    raise HTTPException(status_code=404, detail="Elemento non trovato")

# ============================================
# AVVIO DEL SERVER
# ============================================

if __name__ == "__main__":
    import uvicorn
    
    # Porta : utilizza SERVER_PORT (OuiPanel) o 8000 per impostazione predefinita
    port = int(os.getenv('SERVER_PORT', 8000))
    
    # IMPORTANTE : Ascoltare su 0.0.0.0 per OuiPanel
    uvicorn.run(app, host="0.0.0.0", port=port)

💡 Bonus FastAPI : La documentazione interattiva è generata automaticamente!

  • Swagger UI : http://tuo-ip:porta/docs
  • ReDoc : http://tuo-ip:porta/redoc

📤 Passo 2 : Caricare i File su OuiPanel

Via il Gestore File

  1. Accedi a OuiPanel
  2. Seleziona il tuo server Python
  3. Nel menu laterale, clicca su Gestore file

Immagine

  1. Elimina i file di default (se ci sono)
  2. Clicca su Invia (Upload)
  3. Carica i tuoi file :
    • app.py (o main.py)
    • requirements.txt
    • Le tue cartelle (routes/, models/...) se necessario

Immagine

⚠️ Non caricare : Il file .env sarà creato direttamente sul server (più sicuro).


Via SFTP (Consigliato per più file)

  1. Accedi in SFTP con FileZilla
  2. Trascina e rilascia tutto il contenuto della tua cartella API
  3. Verifica che tutti i file siano stati caricati correttamente

📖 Consulta la guida "Accesso SFTP con FileZilla" per istruzioni dettagliate.


🔑 Passo 3 : Creare il File .env

Creare il file .env

  1. Nel Gestore file, clicca su Nuovo file
  2. Nominalo .env (con il punto davanti)
  3. Aggiungi le tue variabili :
# Configurazione dell'API
DEBUG=false
PORT=8000

# Database (se necessario)
DATABASE_URL=mysql://user:password@host:3306/database

# Chiavi API (esempi)
API_KEY=la_tua_chiave_api_segreta
SECRET_KEY=la_tua_chiave_segreta_per_jwt

Immagine

  1. Clicca su Crea o Salva

⚠️ Importante :

  • Nessuno spazio attorno al =
  • Nessuna virgolette attorno ai valori semplici
  • Non condividere mai questo file

⚙️ Passo 4 : Configurare il File di Avvio

OuiPanel deve sapere quale file Python eseguire all'avvio.

Accedere alle impostazioni

  1. Nel menu laterale, clicca su Configurazione
  2. Clicca su Impostazioni del server

Immagine


Configurare il file da eseguire

Trova il campo File da eseguire (o Main File / Startup File) :Immagine

Il tuo file principale Valore da impostare
app.py app.py
main.py main.py
api.py api.py
src/app.py src/app.py

⚠️ Importante : Il nome deve corrispondere esattamente al tuo file (sensibile al maiuscolo/minuscolo).


🚀 Passo 5 : Avviare l'API

Avviare il server

  1. Nel menu laterale, clicca su Console
  2. Clicca su Avvia

Installazione automatica delle dipendenze

Al primo avvio, il server installa automaticamente i pacchetti :

Flask :

Installing requirements from requirements.txt...
Successfully installed flask-3.0.0 python-dotenv-1.0.0 gunicorn-21.2.0

Running app.py...
 * Running on http://0.0.0.0:25639

FastAPI :

Installing requirements from requirements.txt...
Successfully installed fastapi-0.109.0 uvicorn-0.27.0 python-dotenv-1.0.0

Running app.py...
INFO:     Uvicorn running on http://0.0.0.0:25639

✅ Passo 6 : Testare l'API

Recuperare l'indirizzo

  1. Annota la porta visualizzata nella console (es: 25639)
  2. Recupera l'IP del tuo server nella Vista Globale
  3. L'indirizzo della tua API è : http://IP:PORT

Esempio : http://51.77.xxx.xxx:25639

Immagine

Immagine

Testare gli endpoint

Con un browser :

  • Apri http://51.77.xxx.xxx:25639/ → Dovrebbe visualizzare il JSON di benvenuto
  • Apri http://51.77.xxx.xxx:25639/health → Health check
  • (FastAPI) Apri http://51.77.xxx.xxx:25639/docs → Documentazione Swagger

Con curl :

# GET - Pagina principale
curl http://51.77.xxx.xxx:25639/

# GET - Lista degli elementi
curl http://51.77.xxx.xxx:25639/api/items

# GET - Un elemento specifico
curl http://51.77.xxx.xxx:25639/api/items/1

# POST - Creare un elemento
curl -X POST http://51.77.xxx.xxx:25639/api/items \
  -H "Content-Type: application/json" \
  -d '{"name": "Nuovo elemento", "price": 29.99}'

# PUT - Modificare un elemento
curl -X PUT http://51.77.xxx.xxx:25639/api/items/1 \
  -H "Content-Type: application/json" \
  -d '{"name": "Elemento modificato", "price": 39.99}'

# DELETE - Eliminare un elemento
curl -X DELETE http://51.77.xxx.xxx:25639/api/items/1

Con Postman / Insomnia :

  • Importa l'URL di base : http://51.77.xxx.xxx:25639
  • Testa i tuoi diversi endpoint

Immagine


🌐 Passo 7 : Configurare un Nome di Dominio (Proxy Manager)

Per accedere alla tua API tramite un URL pulito con HTTPS (es: https://api.miosito.com), utilizza il Proxy Manager.

Configurare il DNS

  1. In OuiPanelProxy Manager, annota l'IP del Proxy
  2. Presso il tuo registrar (OVH, Cloudflare, ecc.), crea un record DNS :
Tipo Nome Valore
A api IP del Proxy

Aggiungere il dominio in OuiPanel

  1. Nel menu laterale, clicca su Proxy Manager
  2. Clicca su Aggiungi
  3. Compila :
Campo Valore
Nome di dominio api.miosito.com
Porta La porta della tua API (es: 25639)
SSL ✅ Attivato

Immagine

  1. Clicca su Crea la redirezione

Risultato

La tua API è ora accessibile tramite :

  • https://api.miosito.com (con HTTPS automatico)
  • ✅ Certificato SSL gratuito (Let's Encrypt)

Esempio di chiamata :

curl https://api.miosito.com/api/items

📖 Consulta la guida "Configurare un Nome di Dominio con il Proxy Manager" per ulteriori dettagli.


🗄️ Bonus : Connessione a un Database

MySQL con Flask (PyMySQL)

Aggiungi in requirements.txt :

pymysql==1.1.0

Esempio di connessione :

import pymysql
import os

# Connessione a MySQL
connection = pymysql.connect(
    host=os.getenv('DB_HOST', 'localhost'),
    user=os.getenv('DB_USER', 'root'),
    password=os.getenv('DB_PASSWORD', ''),
    database=os.getenv('DB_NAME', 'mydb'),
    charset='utf8mb4'
)

# Esempio di query
with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM items")
    result = cursor.fetchall()

Variabili .env da aggiungere :

DB_HOST=mysql-host.ouiheberg.com
DB_USER=tuo_user
DB_PASSWORD=tuo_password
DB_NAME=tuo_database

📖 Consulta la guida "Creare e Gestire un Database MySQL" per creare il tuo database.


🔧 Risoluzione dei Problemi

L'API non si avvia

❌ Errore ✅ Soluzione
ModuleNotFoundError: No module named 'flask' Controlla requirements.txt e riavvia
ModuleNotFoundError: No module named 'fastapi' Controlla requirements.txt e riavvia
ModuleNotFoundError: No module named 'dotenv' Aggiungi python-dotenv in requirements.txt
SyntaxError Errore nel tuo codice Python

Errore "No space left on device" (FastAPI)

Questo errore si verifica quando pydantic-core (dipendenza di FastAPI) deve essere compilato con Rust :

error: No space left on device (os error 28)
ERROR: Failed building wheel for pydantic-core
✅ Soluzioni
1. Usa Flask al posto (non richiede compilazione)
2. Aumenta il storage del tuo server (5+ GB raccomandati)
3. Pulisci i file temporanei e riprova

💡 Raccomandazione : Per i piccoli server con poco spazio di archiviazione, Flask è più adatto di FastAPI.


L'API si avvia ma non è accessibile

❌ Causa ✅ Soluzione
Ascolto su localhost Cambia in 0.0.0.0
Porta errata Usa os.getenv('SERVER_PORT')

Controlla il tuo codice :

# ❌ ERRATO - ascolta solo in locale
app.run(host='localhost', port=5000)
app.run(host='127.0.0.1', port=5000)

# ✅ CORRETTO - ascolta su tutte le interfacce
app.run(host='0.0.0.0', port=port)
uvicorn.run(app, host='0.0.0.0', port=port)

Errore 502 Bad Gateway (Proxy Manager)

❌ Causa ✅ Soluzione
API non avviata Avvia il server in OuiPanel
Porta errata nel Proxy Manager Controlla la porta configurata
API crashata Controlla la Console

Il file .env non viene letto

❌ Causa ✅ Soluzione
python-dotenv non installato Controlla requirements.txt
load_dotenv() non chiamato Aggiungi load_dotenv() all'inizio del file
File mal nominato Il file deve chiamarsi esattamente .env

Errore CORS

Se chiami la tua API da un frontend (React, Vue, ecc.) :

❌ Errore ✅ Soluzione
Access-Control-Allow-Origin Aggiungi Flask-CORS o CORSMiddleware (vedi sezione Sicurezza)

🔒 Sicurezza

File .env

✅ Da fare ❌ Da non fare
Creare il .env sul server Caricare il .env dal tuo PC
Aggiungere .env al .gitignore Commit il .env su GitHub
Utilizzare variabili per i segreti Mettere le chiavi API nel codice

Buone pratiche API

  • Valida sempre gli input dell'utente
  • ✅ Usa HTTPS in produzione (Proxy Manager)
  • ✅ Non esporre gli errori dettagliati in produzione
  • ✅ Aggiungi un autenticazione per le rotte sensibili

Attivare CORS (se necessario)

Se la tua API è chiamata da un frontend (React, Vue, ecc.) su un altro dominio :

Flask - Aggiungi flask-cors :

# requirements.txt
flask-cors==4.0.0
from flask_cors import CORS
app = Flask(__name__)
CORS(app)

FastAPI - Il middleware è già disponibile :

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

📂 Struttura Avanzata (Raccomandata)

Per un'API più complessa, organizza il tuo codice :

📁 LaMiaAPI/
├── 📄 app.py               ← Punto di ingresso
├── 📄 requirements.txt
├── 📄 .env
├── 📁 routes/
│   ├── 📄 __init__.py
│   ├── 📄 items.py         ← Rotte /api/items
│   └── 📄 users.py         ← Rotte /api/users
├── 📁 models/
│   └── 📄 item.py          ← Modello Item
└── 📁 utils/
    └── 📄 helpers.py       ← Funzioni utilitarie

💡 Per le grandi API, questa struttura consente di organizzare meglio il codice e facilita la manutenzione.


📝 Riepilogo

1. Scegliere il framework (Flask o FastAPI)
2. Preparare i file (app.py + requirements.txt con python-dotenv)
3. Assicurarsi che il server ascolti su 0.0.0.0:PORT
4. Caricare i file su OuiPanel (senza il .env)
5. Creare il file .env sul server
6. Configurare il file di avvio (app.py, main.py...)
7. Avviare il server
8. Testare tramite http://IP:PORT
9. (Opzionale) Configurare il Proxy Manager per HTTPS

ENDPOINT DI TEST :
├── GET  /              → Pagina principale
├── GET  /health        → Controllo di salute
├── GET  /api/items     → Elenco degli items
├── GET  /api/items/1   → Un item
├── POST /api/items     → Creare un item
├── PUT  /api/items/1   → Modificare un item
└── DELETE /api/items/1 → Eliminare un item

(FastAPI) Documentazione auto :
├── /docs   → Swagger UI
└── /redoc  → ReDoc

Hai bisogno di un hosting Python?

Distribuisci le tue applicazioni Python con il nostro hosting ottimizzato e supporto dedicato.

Vedi le offerte