Quantcast
Channel: Lucee Dev - Latest topics
Viewing all articles
Browse latest Browse all 424

Gemini API/Lucee give 404 but works in Postman

$
0
0

This is technically related to Gemini but wondering if anybody has any insight.

I signed up for a free version of Gemini so I could test out their API. I have created a key and it works perfectly in Postman when i do a raw JSON post with the url https://generativelanguage.googleapis.com/v1/models/gemini-2.0-flash:generateContent?key=MyKey

With the body

{
  "contents": [
    {
      "parts": [
        {
          "text": "how big is the sun. Tell me in less than 20 characters"
        }
      ]
    }
  ]
}

However, I’ve tried a million and one ways or so it feels to try to get the same thing to work in Lucee, and it keeps kicking back a 404 error. Now the 404 is a bit misleading because I also posted the endpoint into a browser and got the 404 response because the body was missing, but it demonstrated that it gave a 404 even though the endpoint URL was correct.

Here’s one of the many attempts

<cfscript>
// API endpoint - DOUBLE CHECK THIS
apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent";
// API key (IMPORTANT: Define this variable securely!)
apiKey = GEMINI_API_KEY;
// *** URL-encode the API key ***
apiKey = urlEncodedFormat(apiUrl);
cfhttp(url="#apiUrl#?key=#apiKey#", method="post", result="httpResponse") {
    cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8"
    cfhttpparam type="body" value='{"contents": [{"parts":[{"text": "test"}]}]}'
}
writeDump(httpResponse);
</cfscript>

here’s another

<cfscript>
// API endpoint from the working curl example
apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent";

// API key (IMPORTANT: Define this variable securely!)
apiKey = GEMINI_API_KEY;

// Payload from the working curl example
payload = {
    "contents": [
        {
            "parts": [
                {
                    "text": "Tell me about the earth size in less than 30 characters"  // Or "Write a story about a magic backpack."
                }
            ]
        }
    ]
};

// Serialize payload to JSON
payloadJson = serializeJSON(payload);

// *** Debugging: Ensure payloadJson is valid JSON ***
try {
    deserializeJSON(payloadJson); // Try to deserialize it back
    writeOutput("<br>Payload JSON is valid.<br>");
} catch (any e) {
    writeOutput("<br>Payload JSON is NOT valid: #e.message#<br>");
    // If it's invalid, inspect payloadJson closely!
}

// cfhttp to make the API call
cfhttp(url=apiUrl, method="post", result="httpResponse") {
    // API key in the URL (as it works in your Postman example)
    cfhttpparam(type="url", name="key", value="#apiKey#");

    // Content-Type header (with charset) - EXACT MATCH TO POSTMAN
    cfhttpparam(type="header", name="Content-Type", value="application/json; charset=UTF-8");

    // Set the JSON payload as the body
    cfhttpparam(type="body", value=payloadJson);
}

// *** Debugging: Output httpResponse ***
writeDump(httpResponse); // Inspect the entire httpResponse struct

// Process the API response
if (httpResponse.statusCode eq "200 OK") {
    // Successful response
    responseData = deserializeJSON(httpResponse.fileContent);

    // *** Extract the answer - ADJUST THIS BASED ON ACTUAL RESPONSE STRUCTURE ***
    // *** The structure of the response will vary depending on the Gemini model ***
    if (structKeyExists(responseData, "candidates") && arrayLen(responseData.candidates) gt 0) {
        // This is a likely path to the answer, but you *must* verify it
        answer = responseData.candidates[1].content.parts[1].text;
        // *** Gemini API does not provide token usage in the same way as OpenAI ***
        tokensUsed = "N/A";
    } else {
        answer = "Error: No answer received from Gemini API";
        tokensUsed = "N/A";
    }

    // Output the results
    writeOutput("Question: Tell me about the earth size in less than 30 characters<br>");
    writeOutput("Answer: #answer#<br>");
    writeOutput("Tokens Used: #tokensUsed#");

} else {
    // *** Handle errors from the Gemini API ***
    writeOutput("Error: #httpResponse.status_code# - #httpResponse.status_text#<br>");
    writeOutput("Response Content: #httpResponse.fileContent#");

    // *** Log the error for debugging ***
    // <cflog file="GeminiAPIError" text="Status: #httpResponse.statusCode#, #httpResponse.statusText#, Content: #httpResponse.fileContent#">

    // *** Handle specific errors, such as rate limiting ***
    if (httpResponse.status_code eq "429") {
        writeOutput("<br>Rate limit exceeded. Please try again later.");
        // Implement retry logic if needed (e.g., wait and try again)
    }
}
</cfscript>

I’d use gemini and Deepseek to try and create these solutions (hence all the comments in there)

I’m hoping somebody else has come across this issue and might be able to help. Btw I’m running it locally on HTTP but I did also try it on HTTPS

Tech stack

  • Lucee 6.1.1.118 (updating to 6.2.shortly)
  • Java 11.0.21 (Eclipse Adoptium) 64bit
  • Windows Server 2022 (10.0) 64bit
  • IIS 10

21 posts - 3 participants

Read full topic


Viewing all articles
Browse latest Browse all 424

Trending Articles