[Python] JavaScript Fetch Request to Flask Server Fails with "TypeError: Failed to Fetch"

Discussão em 'Python' iniciado por Stack, Janeiro 3, 2025.

  1. Stack

    Stack Membro Participativo

    I'm developing a website using vanilla HTML, CSS, and JavaScript, and I have a Python script that runs an AI model. To facilitate interaction between JavaScript and Python, I set up a Flask server.

    When I send a request from JavaScript, the Flask server receives it correctly, the AI model executes successfully, and I receive a 200 status code in the command line. However, the JavaScript code returns the following error: "TypeError: Failed to Fetch".

    I'm starting the Flask server first and then using Visual Studio Code's live server for the HTML page.

    The flask server is running on port 5000 and the liveserver where the page is located is port 5500.

    Below are the relevant files for my flask server and javascript code:

    Flask Server (app.py):

    import json
    import traceback
    from flask import Flask, request, jsonify, render_template, send_from_directory
    from diagnose import diagnose
    from werkzeug.utils import secure_filename
    import os
    from flask_cors import CORS
    import sys

    # Get the absolute path to the project root
    PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
    UPLOADS_FOLDER = os.path.join(PROJECT_ROOT, 'uploads')

    app = Flask(__name__, static_folder='../')
    CORS(app, resources={
    r"/diagnose": {
    "origins": ["http://127.0.0.1:5500"],
    "methods": ["POST"],
    "allow_headers": ["Content-Type", "Accept"],
    "expose_headers": ["Content-Type"]
    }
    })

    # Add detailed logging
    import logging
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    @app.route('/diagnose', methods=['POST'])
    def diagnose_plant():
    try:
    # Extensive logging of request details
    logger.debug("Diagnosis request received")
    logger.debug(f"Form data: {request.form}")
    logger.debug(f"Files data: {request.files}")

    print("Diagnosis request received")
    print(f"Form data: {request.form}")
    print(f"Files data: {request.files}")

    # Check if image is present in the request
    if 'image' not in request.files:
    logger.error("No image file in request")
    print("No image file in request")
    return jsonify({'error': 'No image file'}), 400

    # Get the uploaded image file
    image_file = request.files['image']

    # Check if filename is empty
    if image_file.filename == '':
    logger.error("No selected file")
    print("No selected file")
    return jsonify({'error': 'No selected file'}), 400

    # Save the image file to the uploads directory
    filename = secure_filename(image_file.filename)
    filepath = os.path.join(UPLOADS_FOLDER, filename)

    # Ensure uploads directory exists
    os.makedirs(UPLOADS_FOLDER, exist_ok=True)
    image_file.save(filepath)

    # Get the plant type from the request form data
    plant_type = request.form['plant_type']

    logger.debug(f"Diagnosing {plant_type} with image: {filepath}")
    print(f"Diagnosing {plant_type} with image: {filepath}")

    # Diagnose the plant disease using the uploaded image
    try:
    diagnosis = diagnose(plant_type, filepath)
    logger.debug(f"Diagnosis result: {diagnosis}")
    print(f"Diagnosis result: {diagnosis}")
    except Exception as diagnose_error:
    logger.error("Error in diagnosis process")
    logger.error(traceback.format_exc())
    print("Error in diagnosis process")
    print(traceback.format_exc())
    return jsonify({
    'error': 'Diagnosis failed',
    'details': str(diagnose_error),
    'traceback': traceback.format_exc()
    }), 500

    response = jsonify({'diagnosis': diagnosis})
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

    except Exception as e:
    # Log the full error traceback
    logger.error("Unexpected error during diagnosis")
    logger.error(traceback.format_exc())
    print("Unexpected error during diagnosis")
    print(traceback.format_exc())

    # Return a more detailed error response
    return jsonify({
    'error': 'Diagnosis failed',
    'details': str(e),
    'traceback': traceback.format_exc()
    }), 500
    finally:
    # Optional: Remove the uploaded file after processing
    if 'filepath' in locals() and os.path.exists(filepath):
    os.remove(filepath)

    if __name__ == '__main__':
    app.run(debug=True)


    JavaScript (app.js):

    // Get the image file input element
    const imageInput = document.getElementById('file-input');

    // Get the dropdown element
    const plantDropdown = document.getElementById('plant-dropdown');

    const plantConversions = {
    'Select Plant Type': null,
    'Apple': 'Apple',
    'Cherry': 'Cherry_(including_sour)',
    'Corn': 'Corn_(maize)',
    'Grape': 'Grape',
    'Peach': 'Peach',
    'Bell Pepper': 'Pepper,_bell',
    'Potato': 'Potato',
    'Strawberry': 'Strawberry',
    'Tomato': 'Tomato'
    }


    const diagnoseButton = document.getElementById('diagnose-button');
    console.log(diagnoseButton)
    // Add an event listener to the diagnose button
    diagnoseButton.addEventListener('click', async (event) => {
    console.log('Button clicked'); // Debug point 1

    const plantType = plantDropdown.options[plantDropdown.selectedIndex].text;
    console.log('Plant type:', plantType); // Debug point 2

    if (!plantConversions[plantType]) {
    alert('Please select a valid plant type');
    return;
    }

    const imageFile = imageInput.files[0];
    console.log('Image file:', imageFile); // Debug point 3

    if (!imageFile) {
    alert('Please select an image');
    return;
    }

    const formData = new FormData();
    formData.append('image', imageFile);
    formData.append('plant_type', plantConversions[plantType]);

    console.log('FormData created with:'); // Debug point 4
    for (let [key, value] of formData.entries()) {
    console.log(key, ':', value);
    }

    try {
    console.log('Starting fetch...');
    const response = await fetch('http://127.0.0.1:5000/diagnose', {
    method: 'POST',
    body: formData,
    headers: {
    'Accept': 'application/json'
    },
    mode: 'cors', // Explicitly state we're making a CORS request
    credentials: 'omit' // Don't send credentials for cross-origin requests
    });
    console.log('Fetch completed, response:', response);

    const data = await response.json();
    console.log('Response data:', data);

    if (data && data.diagnosis) {
    alert(data.diagnosis);
    } else {
    alert('Invalid response format from server');
    }

    } catch (error) {
    console.error('Detailed error:', {
    name: error.name,
    message: error.message,
    stack: error.stack
    });
    alert(`Error: ${error.message}`);
    }
    });


    Here is the detailed error from the browser console:

    Detailed error: {name: 'TypeError', message: 'Failed to fetch', stack: 'TypeError: Failed to fetch\n at HTMLButtonElemen…onymous> (http://127.0.0.1:5500/src/app.js:69:28)'}

    And here are the last few lines that show up in the flask terminal:|

    INFO:werkzeug:127.0.0.1 - - [02/Jan/2025 17:10:04] "POST /diagnose HTTP/1.1" 200 -

    Key Points:

    Flask server receives request and processes AI model successfully.

    AI model provides correct output, and 200 status code is returned.

    JavaScript fetch request fails with "TypeError: Failed to Fetch".

    Flask server is started first, followed by VS Code live server for the HTML page.

    Question: What could be causing the "TypeError: Failed to Fetch" error in my JavaScript code, and how can I resolve this issue?

    What I Tried:

    Verified that the Flask server is running and accessible.

    Confirmed that the AI model executes and returns the expected results on the server side.

    Ensured that the JavaScript code is correctly sending the fetch request.

    Checked for any errors in the console and terminal outputs to identify the issue.

    What I Expected: I expected the JavaScript fetch request to successfully communicate with the Flask server, retrieve the AI model's output, and handle the response without encountering the "TypeError: Failed to Fetch" error.

    Continue reading...

Compartilhe esta Página